HashiCorp Cloud Platform
Conditional access statements
This page describes conditional access statements and how to format them. A conditional access statement is a boolean expression that determines the eligibility of the external credentials sent to HCP during workload identity federation. When HCP evaluates the conditional access statement as true
, it accepts the credential.
Conditional access statements allow additional control over which credentials and workloads can receive an HCP access token. They help ensure that only the intended workloads are allowed to access HCP services.
Create an expression
A single expression is a matching operator with a selector and value. They are written in plain text format, and they support boolean logic and parenthesization. In general whitespace is ignored, except within literal strings.
Matching operators
All matching operators use a selector or value to choose what data should be matched. The following reference provides supported expressions for matching selectors and values.
// Equality & Inequality checks
<Selector> == "<Value>"
<Selector> != "<Value>"
// Emptiness checks
<Selector> is empty
<Selector> is not empty
// Contains checks or Substring Matching
"<Value>" in <Selector>
"<Value>" not in <Selector>
<Selector> contains "<Value>"
<Selector> not contains "<Value>"
// Regular Expression Matching
<Selector> matches "<Value>"
<Selector> not matches "<Value>"
Selectors
Selectors create an expression. Define a selector using dot notation (name.name.name
). Each name must start with an ASCII letter, and it can contain ASCII letters, numbers, and underscores.
When part of the selector references a map value, you can use the form ["<map key name>"]
instead of .<map key name>
. This syntax allows the possibility of using map keys that are not valid selectors by themselves.
The following example demonstrates how to format a selector.
// Accessing nested claims
// https://cloud.google.com/compute/docs/instances/verifying-instance-identity#payload
jwt_claims.google.compute_engine.project_id
// Also selects the same key
jwt_claims["google"]["compute_engine"]["project_id"]
AWS
With AWS, you can use the following selectors, which correspond to the AWS GetCallerIdentity response.
aws.arn
: The AWS ARN associated with the calling entityaws.account_id
: The AWS account ID number of the account that owns or contains the calling entityaws.user_id
: The unique identifier of the calling entity
OIDC Providers
When exchanging an OIDC Token for access to HCP, the conditional access statement has access to all the claims in the token with the jwt_claims.
prefix. The following example is a token for a GitHub Actions Workflow.
{
"jti": "example-id",
"sub": "repo:octo-org/octo-repo:environment:prod",
"environment": "prod",
"aud": "https://github.com/octo-org",
"ref": "refs/heads/main",
"sha": "example-sha",
"repository": "octo-org/octo-repo",
"repository_owner": "octo-org",
"actor_id": "12",
"repository_visibility": "private",
"repository_id": "74",
"repository_owner_id": "65",
"run_id": "example-run-id",
"run_number": "10",
"run_attempt": "2",
"runner_environment": "github-hosted",
"actor": "octocat",
"workflow": "example-workflow",
"head_ref": "",
"base_ref": "",
"event_name": "workflow_dispatch",
"ref_type": "branch",
"job_workflow_ref": "octo-org/octo-automation/.github/workflows/oidc.yml@refs/heads/main",
"iss": "https://token.actions.githubusercontent.com",
"nbf": 1632492967,
"exp": 1632493867,
"iat": 1632493567
}
The following table contains a non-exhaustive list of valid selectors and the values they match:
Selector | Matched value |
---|---|
jwt_claims.repository | octo-org/octo-repo |
jwt_claims.workflow | example-workflow |
jwt_claims.environment | prod |
Values
Operators match values when evaluating an expression.
Values can be any valid selector, a number, or a string. Numbers can be either base 10 integers or floating point numbers.
It is a best practice to use quotation marks with values. When quoting strings, you can use double quotes or backticks. When enclosed in backticks, values are treated as raw strings and escape sequences such as \n
are expanded.
Compound expressions
There are several methods for connecting expressions into larger compound expressions. You can connect expressions with one or more of the following:
- logical
or
- logical
and
- logical
not
- grouping with parentheses
- matching expressions
The following example demonstrates common syntax options for compound expressions.
// Logical Or - evaluates to true if either sub-expression does
<Expression 1> or <Expression 2>
// Logical And - evaluates to true if both sub-expressions do
<Expression 1 > and <Expression 2>
// Logical Not - evaluates to true if the sub-expression does not
not <Expression 1>
// Grouping - Overrides normal precedence rules
( <Expression 1> )
// Inspects data to check for a match
<Matching Expression 1>
Standard operator precedence applies to expressions. For example, the following two expressions are equivalent:
<Expression 1> and not <Expression 2> or <Expression 3>
( <Expression 1> and (not <Expression 2> )) or <Expression 3>
Examples
The following examples demonstrate common patterns for conditional access statement expressions.
Use matches
to restricts access from workloads with the AWS Role my-app-role
.
`aws.arn matches ^arn:aws:sts::123456789012:assumed-role/my-app-role/`
Use matches
and or
to restrict access from workloads with the AWS Role my-app-role
or my-other-app-role
.
`aws.arn matches ^arn:aws:sts::123456789012:assumed-role/my-app-role/ or aws.arn matches ^arn:aws:sts::123456789012:assumed-role/my-other-app-role/`
Use ==
to restrict access to GCP workloads with the Service Account 106356042740441904560
and running in the project ID my-app-project-191923
.
`jwt_claims.sub == 106356042740441904560 and jwt_claims.google.compute_engine.project_id == my-app-project-191923`