Add an option to request session tags in the OIDC token#18
Conversation
|
Hmm. It would be good to mention that session tags are captured in cloudtrail logs too. Maybe with an example? |
|
@yob I think it would be good to demo using an org identifier as well, given org slug can be changed. |
764dcd8 to
cf00f74
Compare
|
@wolfeidau how's this? |
|
Nice! Would folks expect to be able to use arrays too? Doesn't have to be a right-now thing. steps:
- command: aws sts get-caller-identity
plugins:
- aws-assume-role-with-web-identity#v1.1.0:
role-arn: arn:aws:iam::AWS-ACCOUNT-ID:role/SOME-ROLE
session-tags:
- organization_slug
- pipeline_slug
- build_branch |
|
I was thinking we could add |
1337458 to
84a761e
Compare
I like it. Since making session tags the default behaviour is a breaking change, and that flag doesn't exist yet: maybe we can mull over ideas for a future v2 release that use session tags by default and has an option to disable the default claims if they're not needed. Or even, turn off the default claims and go all in on session tags 🤔
Hmm. The array syntax definitely reads nicer. I'll look into it! |
0f45e3f to
1d5c63f
Compare
|
I've switched the syntax to accept claims for array instead of CSV string |
Session tags are a more secure way for customers to define which tokens
can assume an IAM role. Rather than use the error prone `sub` claim with
colon separators, the trust policy of an IAM Role can target specific
claims and the required values (like `organization_slug`,
`pipeline_slug`, and `build_branch`.
Unfortunately any OIDC token with session tags needs an additional
permission in the trust policy of the role they are assuming
(`sts:TagSession`, see below). Automatically adding session tags would
break role assuming for customers with existing roles and trust
policies, so for now we default the option to blank and request no
session tags.
Maybe it a v2.0.0 release we could invert the behaviour and default to a
few commonly used session tags? I'd suggest
* organization_slug
* pipeline_slug
* build_branch
For now users can opt in to session tags like so, using any valid claim
from the Buildkite OIDC docs[1].
```yaml
steps:
- command: aws sts get-caller-identity
plugins:
- aws-assume-role-with-web-identity#v1.1.0:
role-arn: arn:aws:iam::AWS-ACCOUNT-ID:role/SOME-ROLE
session-tags: "organization_slug,pipeline_slug,build_branch"
```
The resulting token duplicates the requested claims into a nested
`https://aws.amazon.com/tags` claim:
```json
{
"iss": "https://agent.buildkite.com",
"sub": "organization:example-org:pipeline:example-pipeline:ref:refs/heads/main:commit:cb9c1decb3b7c3c0fcd8a4368bb6a492e631b571:step:",
"aud": "https://sts.amazonaws.com",
"iat": 1739694861,
"nbf": 1739694861,
"exp": 1739695161,
"organization_slug": "example-org",
"pipeline_slug": "example-pipeline",
"build_number": 2,
"build_branch": "main",
"build_tag": null,
"build_commit": "cb9c1decb3b7c3c0fcd8a4368bb6a492e631b571",
"step_key": null,
"job_id": "01950de4-b414-4ef4-a604-6599c16ec9d9",
"agent_id": "01950de4-bef7-4802-ad00-b509d14f66ab",
"build_source": "ui",
"runner_environment": "buildkite-hosted",
"https://aws.amazon.com/tags": {
"principal_tags": {
"organization_slug": [
"example-org"
],
"pipeline_slug": [
"example-pipeline"
],
"build_branch": [
"main"
]
}
}
}
```
Here's an example trust policy for a role that can only be assumed by
`main` branch builds in the https://buildkite.com/example-org/example-pipeline
pipeline
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::111111111111:oidc-provider/agent.buildkite.com"
},
"Action": [
"sts:AssumeRoleWithWebIdentity",
"sts:TagSession"
],
"Condition": {
"StringEquals": {
"agent.buildkite.com:aud": "sts.amazonaws.com"
},
"ForAnyValue:StringEquals": {
"aws:RequestTag/organization_slug": "example-org",
"aws:RequestTag/pipeline_slug": "example-pipeline",
"aws:RequestTag/build_branch": "main"
}
}
}
]
}
```
Note the addition of the `sts:TagSession` action, which we previously
haven't documented as required. Without this, any call to
`AssumeRoleWithWebIdentity` with a token that has session tags will
fail. [2] was useful in highlighting this requirement.
[1] https://buildkite.com/docs/agent/v3/cli-oidc#request-oidc-token
[2] https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html
Suggested by Sam. I tried it out, and I like it a lot more. The bash required to wrangle it is a pain, but the UX for customers is much nicer. Hat tip to these sources for bash help: * docker plugin https://github.com/buildkite-plugins/docker-buildkite-plugin/blob/db8815a107fa6588d78855c8491dae969a15fefd/lib/shared.bash#L28-L48 * stackoverflow: https://stackoverflow.com/a/17841619 * https://linuxize.com/post/bash-functions/
pzeballos
left a comment
There was a problem hiding this comment.
Nice! I think is great that we'll ship this for now and work on a v2 with the breaking changes.
…t-token` This flag was added in agent version v3.83.0 of the agent, and is useful for the common use case of assuming an AWS IAM role using OIDC. In [1] I've confirmed how the flag works and built support for it into our official plugin for AWS+OIDC, but I thought it was worth leaving a few breadcrumbs of documentation about the low level flag and command as well. No doubt some customer will find it helpful. I'd like to also expand the higher level documentation on using OIDC to integrate with AWS [2], but I'll tackle that in a separate PR. [1] buildkite-plugins/aws-assume-role-with-web-identity-buildkite-plugin#18 [2] https://buildkite.com/docs/pipelines/security/oidc/aws
Session tags are a more secure way for customers to define which tokens can assume an IAM role. Rather than use the error prone
subclaim with colon separators, the trust policy of an IAM Role can target specific claims and the required values (likeorganization_slug,pipeline_slug, andbuild_branch.Unfortunately any OIDC token with session tags needs an additional permission in the trust policy of the role they are assuming (
sts:TagSession, see below). Automatically adding session tags would break role assuming for customers with existing roles and trust policies, so for now we default the option to blank and request no session tags.Maybe in a v2.0.0 release we could invert the behaviour and default to a few commonly used session tags? I'd suggest
For now, users can opt in to session tags like so, using any valid claim from the Buildkite OIDC docs.
The resulting token duplicates the requested claims into a nested
https://aws.amazon.com/tagsclaim:{ "iss": "https://agent.buildkite.com", "sub": "organization:example-org:pipeline:example-pipeline:ref:refs/heads/main:commit:cb9c1decb3b7c3c0fcd8a4368bb6a492e631b571:step:", "aud": "https://sts.amazonaws.com", "iat": 1739694861, "nbf": 1739694861, "exp": 1739695161, "organization_slug": "example-org", "pipeline_slug": "example-pipeline", "build_number": 2, "build_branch": "main", "build_tag": null, "build_commit": "cb9c1decb3b7c3c0fcd8a4368bb6a492e631b571", "step_key": null, "job_id": "01950de4-b414-4ef4-a604-6599c16ec9d9", "agent_id": "01950de4-bef7-4802-ad00-b509d14f66ab", "build_source": "ui", "runner_environment": "buildkite-hosted", "https://aws.amazon.com/tags": { "principal_tags": { "organization_slug": [ "example-org" ], "pipeline_slug": [ "example-pipeline" ], "build_branch": [ "main" ] } } }Here's an example trust policy for a role that can only be assumed by
mainbranch builds in the https://buildkite.com/example-org/example-pipeline pipeline{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::111111111111:oidc-provider/agent.buildkite.com" }, "Action": [ "sts:AssumeRoleWithWebIdentity", "sts:TagSession" ], "Condition": { "StringEquals": { "agent.buildkite.com:aud": "sts.amazonaws.com" }, "ForAnyValue:StringEquals": { "aws:RequestTag/organization_slug": "example-org", "aws:RequestTag/pipeline_slug": "example-pipeline", "aws:RequestTag/build_branch": "main" } } } ] }Note the addition of the
sts:TagSessionaction, which we previously haven't documented as required. Without this, any call toAssumeRoleWithWebIdentitywith a token that has session tags will fail. These docs were useful in highlighting this requirement.