Skip to content
Terrateam

Gatekeeper - Manual Approval Gates

Gatekeeper allows you to create manual approval gates in your Terrateam workflows, enabling authorized users to override failures from security scans, policy checks, or custom validations. This is particularly useful when you need human judgment to determine if certain violations are acceptable given the context.

When a gated workflow step fails (such as a security scan detecting issues or a policy check finding violations), instead of failing the plan, Gatekeeper:

  1. Records a gate for the directory and workspace the step ran in
  2. Lets the rest of the plan workflow continue
  3. Blocks the apply of that directory and workspace until the gate is approved

This allows teams to maintain strict automated checks while providing flexibility for legitimate exceptions.

Gates can be associated with a token, which requires users to explicitly approve every gate that their approval has been requested on, using a pull request comment.

Gates that are not associated with a token require all requested approvers to approve the pull request in the VCS provider before changes can be applied.

  1. A gated step fails: A workflow step configured with a gate encounters a failure condition during the plan.

  2. Gate recorded: Terrateam records the gate for the directory and workspace. The failure of the step is ignored and the plan continues.

  3. Apply is blocked: When an apply is attempted, Terrateam checks every gate for the directories and workspaces being applied. If any gate is not satisfied, Terrateam posts a comment that lists:

    • The gate token or name
    • The directory and workspace
    • Who can approve the gate and how many approvals are still required
  4. Authorized user reviews: Team members review the failure and determine if it’s acceptable.

  5. Approval granted: An authorized user approves the gate. For gates with a token, comment:

    terrateam gate approve <token>

    Multiple tokens can be approved in one comment: terrateam gate approve <token1> <token2>.

    For gates without a token, approve the pull request.

  6. Apply continues: Once every gate is satisfied, the apply proceeds.

There are three ways to create gates:

  • The gate key on the checkov, conftest, and opa workflow step types. The gate is created when the step fails.
  • The on_error key on the run workflow step and hook type, with an entry of type: gate. The gate is created when the command exits non-zero.
  • The gates workflow step and hook type, which runs a command that outputs the gates to create. Use this to compute gates dynamically, for example based on the plan output.

These keys are accepted in the gate object, in an on_error entry of type: gate, and in each gate output by a gates step.

Key Type Description
token String A unique identifier for this gate. Gates with a token are approved with terrateam gate approve <token>. Gates without a token are approved by approving the pull request.
name String A name to give the gate. This is useful for identifying why the gate was created when a token is not used.
all_of List List of users, teams, or roles that must ALL approve the gate.
any_of List List of users, teams, or roles from which any_of_count approvals are required.
any_of_count Integer Number of approvals required from the any_of list. Default is 0, which means no approval from the any_of list is required. Set it to 1 or more when using any_of.

Entries in all_of and any_of use the same syntax as access control: user:<username>, team:<team-slug>, role:<repository-role>, or *.

A gate is satisfied when every entry in all_of has approved and at least any_of_count distinct approvers matching any_of have approved.

Gatekeeper supports flexible authorization patterns:

Single Approver:

gate:
token: "security-override"
any_of: ["user:security-lead"]
any_of_count: 1

Any Team Member:

gate:
token: "platform-approval"
any_of: ["team:platform", "team:sre"]
any_of_count: 1

Multiple Required Approvers:

gate:
token: "critical-override"
all_of: ["team:security", "team:compliance"]

N-of-M Approvals:

gate:
token: "cost-approval"
any_of: ["user:cfo", "user:cto", "user:eng-director", "user:finance-lead"]
any_of_count: 2

The run step does not accept a gate key. Use on_error instead. When a run step has a gate in on_error, ignore_errors defaults to true for that step so the failed command does not fail the plan.

workflows:
- tag_query: ""
plan:
- type: init
- type: plan
- type: run
cmd: ['./scripts/cost-check.sh']
on_error:
- type: gate
token: "cost-threshold"
any_of: ["team:finance", "user:budget-owner"]
any_of_count: 1

Creating gates dynamically with the gates step

Section titled “Creating gates dynamically with the gates step”

The gates step runs a command and reads the gates to create from its standard output. The command must print a JSON object with a gates list. Each gate accepts the keys above plus add_reviewers (default true), which requests a review on the pull request from the user: and team: entries in all_of and any_of. The step always counts as failed so that its gates are recorded; it never fails the plan.

workflows:
- tag_query: ""
plan:
- type: init
- type: plan
- type: gates
cmd: ['./scripts/compute-gates.sh']

Example output of ./scripts/compute-gates.sh:

{
"gates": [
{
"token": "database-change",
"name": "Database schema change",
"any_of": ["team:dba"],
"any_of_count": 1,
"add_reviewers": true
}
]
}

The gates step accepts these keys:

Key Type Description
cmd List Command to run. Required.
env Object Environment variables to set for this execution.
run_on String When to run the step: success, failure, or always. Default is success.

Require approval from specific team based on which resources were modified

Section titled “Require approval from specific team based on which resources were modified”

Assuming a Rego policy file which defines a value networking_team_resources_modifed if any resources that the networking team manages have been modified, require someone from the networking team to approve the pull request before it can be applied.

workflows:
- tag_query: ""
plan:
- type: init
- type: plan
- type: opa
fail_on: defined
extra_args: ['-d', 'policy.rego', 'data.terraform.networking_team_resources_modifed']
gate:
any_of: ["team:networking"]
any_of_count: 1

Allow security teams to approve known false positives or accepted risks:

workflows:
- tag_query: ""
plan:
- type: init
- type: plan
- type: checkov
gate:
token: "checkov-override"
any_of: ["team:security", "team:platform"]
any_of_count: 1

When Checkov detects issues, security or platform team members can review and approve if the findings are acceptable.

Enable compliance teams to grant exceptions to policy violations:

workflows:
- tag_query: "production"
plan:
- type: init
- type: plan
- type: conftest
gate:
token: "policy-exception"
all_of: ["team:compliance"]
any_of: ["user:compliance-lead", "user:ciso"]
any_of_count: 1

This requires both general compliance team approval and approval from either the compliance lead or CISO.

Require finance approval when infrastructure changes exceed cost thresholds:

workflows:
- tag_query: ""
plan:
- type: init
- type: plan
- type: run
cmd: ['./scripts/cost-check.sh']
on_error:
- type: gate
token: "cost-threshold"
any_of: ["team:finance", "user:budget-owner"]
any_of_count: 1

If the cost check script fails (indicating costs exceed thresholds), finance team members can review and approve the changes.

Combine multiple gated checks with different approval requirements:

workflows:
- tag_query: "production"
plan:
- type: init
- type: plan
# Security scanning with override capability
- type: checkov
gate:
token: "security-scan"
any_of: ["team:security"]
any_of_count: 1
# Compliance validation with stricter approval
- type: conftest
gate:
token: "compliance-check"
all_of: ["team:compliance"]
any_of: ["user:compliance-lead"]
any_of_count: 1
# Custom validation with multiple approvers required
- type: run
cmd: ['./scripts/validate-production.sh']
on_error:
- type: gate
token: "prod-validation"
any_of: ["team:platform", "team:sre", "team:devops"]
any_of_count: 2