Skip to content

Commit 55bacfc

Browse files
authored
feat(credentials): configurable audience for keyless AWS, Databricks, Snowflake, Microsoft, and Google credentials (#9962)
* feat(credentials): configurable audience for keyless AWS, Databricks, Snowflake, Microsoft, and Google credentials * fix(credentials): check the audience in the connect dialog before showing setup commands * fix(credentials): name Google's default audience in the keyless catalog hint
1 parent b266bd9 commit 55bacfc

38 files changed

Lines changed: 1229 additions & 211 deletions

‎apps/docs/content/docs/cli/credentials.mdx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ Keyless (workload identity) credentials take two steps.
9393

9494
Step 1: run `sim credentials keyless-subject <providerId> --output json` and configure your cloud to trust the printed issuer, audience, and subject. Its requiredConfigFields lists the values your provider's keylessConfig still needs.
9595

96+
The printed audience is the default. To have Sim sign tokens for your own audience instead, set audience in keylessConfig and trust that value. Google Cloud prints no audience: its default is the credential's own workload identity pool provider.
97+
9698
Step 2: add those values to keylessConfig and pass it to `sim credentials create <providerId> --credentials @file`.
9799

98100
The proof expires after 24 hours and works only for the user who requested it, with the same providerId. If creation reports WORKLOAD_IDENTITY_PROOF_EXPIRED, WORKLOAD_IDENTITY_PROOF_INVALID, WORKLOAD_IDENTITY_SUBJECT_REQUIRED, WORKLOAD_IDENTITY_SUBJECT_IN_USE, run step 1 again, trust the new subject, and retry.
@@ -366,6 +368,8 @@ Keyless (workload identity) credentials take two steps.
366368

367369
Step 1: run `sim credentials keyless-subject <providerId> --output json` and configure your cloud to trust the printed issuer, audience, and subject. Its requiredConfigFields lists the values your provider's keylessConfig still needs.
368370

371+
The printed audience is the default. To have Sim sign tokens for your own audience instead, set audience in keylessConfig and trust that value. Google Cloud prints no audience: its default is the credential's own workload identity pool provider.
372+
369373
Step 2: add those values to keylessConfig and pass it to `sim credentials create <providerId> --credentials @file`.
370374

371375
The proof expires after 24 hours and works only for the user who requested it, with the same providerId. If creation reports WORKLOAD_IDENTITY_PROOF_EXPIRED, WORKLOAD_IDENTITY_PROOF_INVALID, WORKLOAD_IDENTITY_SUBJECT_REQUIRED, WORKLOAD_IDENTITY_SUBJECT_IN_USE, run step 1 again, trust the new subject, and retry.

‎apps/docs/content/docs/cli/reference.mdx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,8 @@ Keyless (workload identity) credentials take two steps.
780780

781781
Step 1: run `sim credentials keyless-subject <providerId> --output json` and configure your cloud to trust the printed issuer, audience, and subject. Its requiredConfigFields lists the values your provider's keylessConfig still needs.
782782

783+
The printed audience is the default. To have Sim sign tokens for your own audience instead, set audience in keylessConfig and trust that value. Google Cloud prints no audience: its default is the credential's own workload identity pool provider.
784+
783785
Step 2: add those values to keylessConfig and pass it to `sim credentials create <providerId> --credentials @file`.
784786

785787
The proof expires after 24 hours and works only for the user who requested it, with the same providerId. If creation reports WORKLOAD_IDENTITY_PROOF_EXPIRED, WORKLOAD_IDENTITY_PROOF_INVALID, WORKLOAD_IDENTITY_SUBJECT_REQUIRED, WORKLOAD_IDENTITY_SUBJECT_IN_USE, run step 1 again, trust the new subject, and retry.
@@ -816,6 +818,8 @@ Keyless (workload identity) credentials take two steps.
816818

817819
Step 1: run `sim credentials keyless-subject <providerId> --output json` and configure your cloud to trust the printed issuer, audience, and subject. Its requiredConfigFields lists the values your provider's keylessConfig still needs.
818820

821+
The printed audience is the default. To have Sim sign tokens for your own audience instead, set audience in keylessConfig and trust that value. Google Cloud prints no audience: its default is the credential's own workload identity pool provider.
822+
819823
Step 2: add those values to keylessConfig and pass it to `sim credentials create <providerId> --credentials @file`.
820824

821825
The proof expires after 24 hours and works only for the user who requested it, with the same providerId. If creation reports WORKLOAD_IDENTITY_PROOF_EXPIRED, WORKLOAD_IDENTITY_PROOF_INVALID, WORKLOAD_IDENTITY_SUBJECT_REQUIRED, WORKLOAD_IDENTITY_SUBJECT_IN_USE, run step 1 again, trust the new subject, and retry.

‎apps/docs/content/docs/integrations/aws-credentials.mdx‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,27 @@ STS **Get Session Token** works only with an **Access keys** credential: AWS ref
4646
</Step>
4747
</Steps>
4848

49+
### Use your own audience [#keyless-audience]
50+
51+
Tokens Sim signs for a keyless role carry the audience `sts.amazonaws.com` by default. To have your account accept only tokens issued for it, enter your own **Audience** in the dialog (for example your AWS account ID): up to 255 letters, digits, and `. _ ~ : / ? # @ & + = % -`. The **Role trust policy** then uses it in its `aud` condition.
52+
53+
AWS accepts a token only when its audience is one of the identity provider's audiences (client IDs), so add yours to the provider. In the IAM console, open the provider and choose **Add audience**, or run:
54+
55+
```bash
56+
aws iam add-client-id-to-open-id-connect-provider \
57+
--open-id-connect-provider-arn arn:aws:iam::<account ID>:oidc-provider/<issuer host and path> \
58+
--client-id <your audience>
59+
```
60+
61+
A provider holds up to 100 audiences. Once no role relies on `sts.amazonaws.com` any more, you can remove it from the provider. Reconnecting the credential keeps its audience; clearing the field returns it to the default.
62+
4963
<Callout type="info">
5064
The subject is unique to the credential. Reconnecting a keyless credential keeps its subject by default, so the role's trust policy keeps working; choose **Issue a new subject** only if you also update the trust policy.
5165
</Callout>
5266

5367
### From the API or CLI [#keyless-api-cli]
5468

55-
Run `sim credentials keyless-subject aws-service-account`, trust the printed subject as above, then add `roleArn` (optionally `stsRegion` and `sessionDurationSeconds`) to its `keylessConfig` and pass it to `sim credentials create aws-service-account`. See [the CLI credentials reference](/cli/credentials) for the full two-step example; the proof expires after 24 hours and works only for the user who requested it.
69+
Run `sim credentials keyless-subject aws-service-account`, trust the printed subject as above, then add `roleArn` (optionally `stsRegion`, `sessionDurationSeconds`, and `audience`) to its `keylessConfig` and pass it to `sim credentials create aws-service-account`. See [the CLI credentials reference](/cli/credentials) for the full two-step example; the proof expires after 24 hours and works only for the user who requested it.
5670

5771
## Use access keys
5872

@@ -80,6 +94,6 @@ Without a signing key, the keyless option is unavailable and access keys work as
8094

8195
## Troubleshooting
8296

83-
- **`InvalidIdentityToken` or "No OpenIDConnect provider found":** the IAM identity provider's URL or audience doesn't match the dialog exactly, or AWS can't reach the issuer. Open `<issuer>/.well-known/openid-configuration` from outside your network; it must load over `https`.
97+
- **`InvalidIdentityToken` or "No OpenIDConnect provider found":** the IAM identity provider's URL doesn't match the dialog exactly, its audiences don't include the credential's audience, or AWS can't reach the issuer. Open `<issuer>/.well-known/openid-configuration` from outside your network; it must load over `https`.
8498
- **"Sim could not assume this role: Not authorized to perform sts:AssumeRoleWithWebIdentity":** the role's trust policy doesn't trust this credential's subject. Paste the trust policy from the dialog again; if you chose **Issue a new subject**, update the policy to the new one.
8599
- **"This role trusts every Sim subject":** the trust policy is missing the `sub` condition. Use the policy from the dialog.

‎apps/docs/content/docs/integrations/databricks-credentials.mdx‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,34 @@ Every option resolves on Sim's servers at run time; tokens never appear in block
2929
In Sim, add a **Databricks connection**, choose **Service principal (keyless, via Sim OIDC)**, and enter the workspace host and the service principal's **application ID**.
3030
</Step>
3131
<Step>
32-
A Databricks account admin runs the **Federation policy** command from the dialog with the service principal's numeric ID. First sign in to the account with `databricks auth login --host <account console URL> --account-id <account ID>` (not a workspace profile or the workspace web terminal). Find the numeric ID with `databricks account service-principals list --filter 'applicationId eq "<application ID>"'`, or on the service principal's page in the account console. The policy trusts Sim's issuer, the Sim audience, and this connection's subject only.
32+
A Databricks account admin runs the **Federation policy** command from the dialog with the service principal's numeric ID. First sign in to the account with `databricks auth login --host <account console URL> --account-id <account ID>` (not a workspace profile or the workspace web terminal). Find the numeric ID with `databricks account service-principals list --filter 'applicationId eq "<application ID>"'`, or on the service principal's page in the account console. The policy trusts Sim's issuer, the audience, and this connection's subject only.
3333
</Step>
3434
<Step>
3535
Make sure the service principal can access the workspace and the resources your workflows use, then save. Sim verifies the connection by exchanging a token and reading the service principal's identity, and refuses a policy that would also trust a different subject, since every Sim workspace shares the issuer and audience.
3636
</Step>
3737
</Steps>
3838

39-
Reconnecting a keyless connection keeps its subject by default, so the federation policy keeps working.
39+
Reconnecting a keyless connection keeps its subject and audience by default, so the federation policy keeps working.
40+
41+
### Use your own audience [#keyless-audience]
42+
43+
By default Sim's tokens carry the audience `sim-databricks`, which every Sim connection shares. To pin the federation policy to a value only your tokens carry, such as your Databricks account ID, enter it in the dialog's **Audience** field before you copy the command. Sim then issues this connection's tokens for that audience, and the command lists it in the policy's `audiences`:
44+
45+
```bash
46+
databricks account service-principal-federation-policy create <SERVICE_PRINCIPAL_NUMERIC_ID> --json '{"oidc_policy":{"issuer":"<issuer>","audiences":["<your audience>"],"subject":"<subject>"}}'
47+
```
48+
49+
Databricks accepts any non-empty audience; Sim takes up to 255 letters, digits, and `. _ ~ : / ? # @ & + = % -`, and refuses another cloud's default audience. To change the audience of an existing connection, add the new value to the policy's `audiences` (with `databricks account service-principal-federation-policy update`), then reconnect with it. Clearing the field goes back to the default.
4050

4151
### From the API or CLI [#keyless-api-cli]
4252

43-
Run `sim credentials keyless-subject databricks-service-account`, trust the printed subject as above, then add `host` and `clientId` to its `keylessConfig` and pass it to `sim credentials create databricks-service-account`. See [the CLI credentials reference](/cli/credentials) for the full two-step example; the proof expires after 24 hours and works only for the user who requested it.
53+
Run `sim credentials keyless-subject databricks-service-account`, trust the printed subject as above, then add `host` and `clientId` (and optionally `audience`) to its `keylessConfig` and pass it to `sim credentials create databricks-service-account`. See [the CLI credentials reference](/cli/credentials) for the full two-step example; the proof expires after 24 hours and works only for the user who requested it.
4454

4555
## Self-hosted deployments
4656

4757
Keyless connections need `WORKLOAD_IDENTITY_SIGNING_KEY` set and an `https` issuer Databricks can reach over the public internet. See [AWS credentials](/integrations/aws-credentials#self-hosted-deployments) for the same settings and for rotating the signing key.
4858

4959
## Troubleshooting
5060

51-
- **"Databricks rejected the token request":** the federation policy's issuer, audience, or subject doesn't match the dialog, or the policy is on a different service principal than the application ID you entered.
61+
- **"Databricks rejected the token request":** the federation policy's issuer, audience, or subject doesn't match the dialog (the error names the audience Sim sent), or the policy is on a different service principal than the application ID you entered.
5262
- **"This service principal's federation policy also trusts other Sim credentials":** the policy's `subject_claim` isn't `sub`, so it matches more than this connection. Recreate it with the command from the dialog.

‎apps/docs/content/docs/integrations/google-service-account.mdx‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ Keyless credentials work with Google Cloud APIs that the service account calls a
218218
--member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT"
219219
```
220220

221-
The provider sets no allowed audiences, so it accepts its own resource name, which is the **Audience** the dialog shows.
221+
By default the provider sets no allowed audiences, so it accepts its own resource name, which Sim's token carries as its `aud`.
222222
</Step>
223223
<Step>
224224
Save in Sim. Sim exchanges a token at STS and impersonates the service account; a token from that step proves the setup works. It also checks that a subject no credential holds can't impersonate the service account, so only this credential can use it. New IAM bindings can take a few minutes to apply; if saving fails right after you run the commands, wait and try again.
@@ -229,13 +229,25 @@ Keyless credentials work with Google Cloud APIs that the service account calls a
229229
Keep the attribute condition and bind the role to the exact `principal://…/subject/SUBJECT` member. Without the condition, the provider accepts a token for any Sim subject, and a role granted to a `principalSet` for the whole pool would let other Sim credentials act with it. Sim refuses to save a service account that another subject can impersonate, but it can't see roles you grant the pool directly on other resources.
230230
</Callout>
231231

232+
### Custom audience [#keyless-custom-audience]
233+
234+
To pin the provider to a value of your own instead of its resource name, enter it under **Audience** (up to 255 letters, digits, and `. _ ~ : / ? # @ & + = % -`). Sim's token then carries that value as its `aud`, and the setup commands add it to the provider's [allowed audiences](https://cloud.google.com/iam/docs/reference/rest/v1/projects.locations.workloadIdentityPools.providers#oidc), which then accept only the listed values:
235+
236+
```bash
237+
gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
238+
... \
239+
--allowed-audiences="AUDIENCE"
240+
```
241+
242+
For an existing provider, run `gcloud iam workload-identity-pools providers update-oidc PROVIDER_ID --project="PROJECT_NUMBER" --location="global" --workload-identity-pool="POOL_ID" --allowed-audiences="AUDIENCE"` before reconnecting the credential with the new audience. Sim still exchanges the token at STS for the provider itself. To go back to the default, clear **Audience** and remove the allowed audiences from the provider (or add its resource name, `https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID`). Another cloud's default audience, such as `sts.amazonaws.com`, is refused.
243+
232244
Each keyless credential has its own subject; reconnecting keeps it by default so your provider and binding keep working. Use one provider per credential (a pool can hold many). Keyless credentials are available for workspace credentials, not organization credentials. Sim uses impersonation rather than direct federated access because some Google Cloud APIs don't accept federated tokens, and impersonation keeps the same identity a JSON key would use.
233245

234246
Self-hosted deployments need `WORKLOAD_IDENTITY_SIGNING_KEY` set and an `https` issuer Google can reach over the public internet. See [AWS credentials](/integrations/aws-credentials#self-hosted-deployments).
235247

236248
### From the API or CLI [#keyless-api-cli]
237249

238-
Run `sim credentials keyless-subject google-service-account`, trust the printed subject as above, then add `projectNumber`, `poolId`, `providerId`, and `serviceAccountEmail` to its `keylessConfig` and pass it to `sim credentials create google-service-account`. See [the CLI credentials reference](/cli/credentials) for the full two-step example; the proof expires after 24 hours and works only for the user who requested it. For domain-wide delegation, also add `"delegation": {"user": "alice@yourcompany.com", "services": ["gmail", "google-drive"]}`, listing any of `gmail`, `google-drive`, `google-docs`, `google-sheets`, and `google-calendar`.
250+
Run `sim credentials keyless-subject google-service-account`, trust the printed subject as above, then add `projectNumber`, `poolId`, `providerId`, and `serviceAccountEmail` (and optionally `audience`) to its `keylessConfig` and pass it to `sim credentials create google-service-account`. See [the CLI credentials reference](/cli/credentials) for the full two-step example; the proof expires after 24 hours and works only for the user who requested it. For domain-wide delegation, also add `"delegation": {"user": "alice@yourcompany.com", "services": ["gmail", "google-drive"]}`, listing any of `gmail`, `google-drive`, `google-docs`, `google-sheets`, and `google-calendar`.
239251

240252
### Keyless domain-wide delegation [#keyless-domain-wide-delegation]
241253

@@ -265,7 +277,7 @@ A keyless credential acts only as the Workspace user you entered. A workflow tha
265277

266278
### Troubleshooting keyless access
267279

268-
- **"Google Cloud refused Sim's token for this workload identity provider":** the project number, pool ID, or provider ID doesn't match; the provider is disabled, has allowed audiences set, or uses a different issuer; or its attribute condition doesn't allow this credential's subject.
280+
- **"Google Cloud refused Sim's token for this workload identity provider":** the project number, pool ID, or provider ID doesn't match; the provider is disabled or uses a different issuer; its allowed audiences don't accept the credential's audience (with the default, it needs none set, or its own resource name among them; with a custom audience, that value must be listed); or its attribute condition doesn't allow this credential's subject.
269281
- **"Google Cloud could not fetch the signing keys from Sim's issuer":** the issuer isn't reachable over public HTTPS (self-hosted deployments).
270282
- **"The service account … does not let this credential impersonate it":** run the `add-iam-policy-binding` command with the exact member shown, and enable the IAM Service Account Credentials API.
271283
- **"This service account also trusts other Sim credentials":** remove any `principalSet` binding for the pool from the service account and keep the attribute condition.

0 commit comments

Comments
 (0)