Skip to content

Commit e4ee81a

Browse files
Add documentation for AWS identities with IAM outbound identity federation (#2878)
AWS recently added a new feature that allows you to generate an OIDC token for an AWS IAM role or user. This finally allows customers to do assumable identities on AWS in the same way they would on other platforms, without our crazy custom implementation. I've marked the existing method as 'Legacy' but left it around. I've also removed the EC2 and Lambda docs. At this point, I don't think either page really adds anything beyond the other two pages and it just adds confusion as to which page to read. --------- Signed-off-by: Mark Drake <[email protected]> Co-authored-by: Mark Drake <[email protected]>
1 parent 5fc83a6 commit e4ee81a

File tree

4 files changed

+236
-473
lines changed

4 files changed

+236
-473
lines changed

content/chainguard/administration/assumable-ids/identity-examples/aws-ec2-identity.md

Lines changed: 0 additions & 154 deletions
This file was deleted.
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
---
2+
title : "Create an Assumable Identity to Authenticate from AWS"
3+
linktitle: "AWS"
4+
lead: ""
5+
description: "Tutorial outlining how to create a Chainguard identity that can be assumed by an AWS user or role using outbound identity federation."
6+
type: "article"
7+
date: 2026-01-05T09:00:00+00:00
8+
lastmod: 2026-01-05T09:00:00+00:00
9+
draft: false
10+
tags: ["Chainguard Containers"]
11+
images: []
12+
weight: 011
13+
---
14+
15+
Chainguard's [*assumable identities*](/chainguard/administration/assumable-ids/assumable-ids/) are identities that can be assumed by external applications or workflows in order to access Chainguard resources or perform certain actions.
16+
17+
This tutorial outlines how to create a Chainguard identity that can be assumed by an AWS IAM user or IAM role using [AWS IAM outbound identity federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_outbound.html).
18+
19+
## Prerequisites
20+
21+
To complete this guide, outbound identity federation must be enabled for your AWS account. Follow [the official AWS documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_outbound_getting_started.html#enable-outbound-federation) to set this up.
22+
23+
You will also need the following tools.
24+
25+
* The AWS CLI. Review the official documentation for information on [how to install or update to the latest version of the tool](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).
26+
* To create the assumable identity, you will need one of the following tools:
27+
* [`chainctl`](/chainguard/chainctl-usage/getting-started-with-chainctl/) — the Chainguard command line interface tool. Follow our guide on [How to Install `chainctl`](/chainguard/chainctl-usage/how-to-install-chainctl/) to set this up.
28+
* [`terraform`](https://developer.hashicorp.com/terraform) — an Infrastructure as Code tool developed by Hashicorp. Follow [the official Terraform documentation](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) for instructions on installing the tool.
29+
30+
## Retrieve Token Issuer URL
31+
32+
Each AWS account has a different issuer URL for outbound identity federation. You can retrieve it from the AWS Console UI by navigating to `IAM > Account settings > STS` as described in [the official getting started guide](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_outbound_getting_started.html).
33+
34+
The token issuer URL will align with the following format:
35+
36+
```
37+
https://<uuid>.tokens.sts.global.api.aws
38+
```
39+
40+
## Create the Identity
41+
42+
This guide outlines two methods for creating an identity that can be assumed by an AWS user or IAM role: one using `chainctl` over a command-line interface, and another using Terraform.
43+
44+
### CLI
45+
46+
Firstly, attach a policy to your AWS role or user that allows it to call `sts:GetWebIdentityToken` for the `https://issuer.enforce.dev` audience. The following example is a minimal policy that allows this:
47+
48+
```json
49+
{
50+
"Version": "2012-10-17",
51+
"Statement": [
52+
{
53+
"Effect": "Allow",
54+
"Action": "sts:GetWebIdentityToken",
55+
"Resource": "*",
56+
"Condition": {
57+
"ForAnyValue:StringEquals": {
58+
"sts:IdentityTokenAudience": "https://issuer.enforce.dev"
59+
},
60+
"NumericLessThanEquals": {
61+
"sts:DurationSeconds": 300
62+
}
63+
}
64+
}
65+
]
66+
}
67+
```
68+
69+
Then, run this command which uses `chainctl` to create a Chainguard identity and assign it the `registry.pull` role. Substitute `<identity-name>`, `<issuer-url>` and `<aws-arn>` with the name you want to give the identity, the issuer URL you just retrieved and the ARN of the AWS user or role you want to assume the identity with, respectively.
70+
71+
```shell
72+
chainctl iam id create <identity-name> --identity-issuer=<issuer-url> --subject=<aws-arn> --role=registry.pull
73+
```
74+
75+
This command should return the identity's [UIDP (unique identity path)](/chainguard/administration/cloudevents/events-reference/#uidp-identifiers). Note this value down, as you'll need it to assume the identity later.
76+
77+
If you need to retrieve the UIDP later on, you can always run the following `chainctl` command to list the identity.
78+
79+
```sh
80+
chainctl iam identities list --name=<identity-name>
81+
```
82+
83+
If you're unsure which ARN or issuer URL to provide to `chainctl iam id create`, you can issue a token with `aws sts get-web-identity-token` and inspect the claims with `jwt`. To complete this command, you must install `jwt` as described on [this page](https://github.com/mike-engel/jwt-cli#installation).
84+
85+
```shell
86+
aws sts get-web-identity-token \
87+
--audience=https://issuer.enforce.dev \
88+
--signing-algorithm=ES384 \
89+
--query WebIdentityToken \
90+
--output text \
91+
| jwt decode -j - \
92+
```
93+
94+
The output will look like this:
95+
96+
```json
97+
{
98+
"header": {
99+
"typ": "JWT",
100+
"alg": "ES384",
101+
"kid": "EC384_0"
102+
},
103+
"payload": {
104+
"aud": "https://issuer.enforce.dev",
105+
"exp": 1766915543,
106+
"https://sts.amazonaws.com/": {
107+
"aws_account": "123456789012",
108+
"org_id": "o-anih79mrvn",
109+
"original_session_exp": "2025-12-28T10:45:29Z",
110+
"ou_path": [
111+
"o-anih79mrvn/r-amv9/ou-amv9-ndi0nlgq/"
112+
],
113+
"principal_id": "arn:aws:iam::123456789012:role/example",
114+
"source_region": "us-west-2"
115+
},
116+
"iat": 1766915243,
117+
"iss": "https://00000000-0000-0000-0000-000000000000.tokens.sts.global.api.aws",
118+
"jti": "00000000-0000-0000-0000-000000000000",
119+
"sub": "arn:aws:iam::123456789012:role/example"
120+
}
121+
}
122+
```
123+
124+
The `sub` and `iss` claims are the values you should provide to `--subject` and `--identity-issuer`, respectively.
125+
126+
### Terraform
127+
128+
You can also create an assumable identity with the [Chainguard Terraform provider](https://registry.terraform.io/providers/chainguard-dev/chainguard/latest). The following example demonstrates creating an identity that can be assumed by an IAM role. It binds the `registry.pull` role to the identity.
129+
130+
Substitute your Chainguard organization name for `<org-name>` and the issuer URL for `<issuer-url>`.
131+
132+
```hcl
133+
terraform {
134+
required_providers {
135+
aws = { source = "hashicorp/aws" }
136+
chainguard = { source = "chainguard-dev/chainguard" }
137+
}
138+
}
139+
140+
data "aws_caller_identity" "current" {}
141+
142+
resource "aws_iam_role" "example" {
143+
name = "example-role"
144+
145+
# Configuration omitted for brevity
146+
}
147+
148+
resource "aws_iam_role_policy" "example_policy" {
149+
name = "web-identity-token-policy"
150+
role = aws_iam_role.example.id
151+
152+
policy = jsonencode({
153+
Version = "2012-10-17"
154+
Statement = [
155+
{
156+
Effect = "Allow"
157+
Action = "sts:GetWebIdentityToken"
158+
Resource = "*"
159+
Condition = {
160+
"ForAnyValue:StringEquals" = {
161+
"sts:IdentityTokenAudience" = "https://issuer.enforce.dev"
162+
}
163+
"NumericLessThanEquals" : {
164+
"sts:DurationSeconds" : 300
165+
}
166+
}
167+
}
168+
]
169+
})
170+
}
171+
172+
data "chainguard_group" "org" {
173+
name = "<org-name>"
174+
}
175+
176+
resource "chainguard_identity" "my_identity_name" {
177+
parent_id = data.chainguard_group.org.id
178+
name = "my-identity-name"
179+
claim_match {
180+
issuer = "<issuer-url>"
181+
subject = aws_iam_role.example.arn
182+
}
183+
}
184+
185+
data "chainguard_role" "registry_pull" {
186+
name = "registry.pull"
187+
}
188+
189+
resource "chainguard_rolebinding" "my_identity_name_registry_pull" {
190+
identity = chainguard_identity.my_identity_name.id
191+
role = data.chainguard_role.registry_pull.items[0].id
192+
group = data.chainguard_group.org.id
193+
}
194+
195+
output "my_identity_name_id" {
196+
value = chainguard_identity.my_identity_name.id
197+
}
198+
```
199+
200+
The `my_identity_name_id` output provides the identity’s [UIDP (unique identity path)](/chainguard/administration/cloudevents/events-reference/#uidp-identifiers). You’ll need this value to assume the identity later.
201+
202+
## Assume the Identity
203+
204+
After creating an identity with either method outlined previously, generate a token with `aws sts get-web-identity-token`:
205+
206+
```shell
207+
TOK=$(aws sts get-web-identity-token --audience=https://issuer.enforce.dev --signing-algorithm=ES384 --query WebIdentityToken --output text)
208+
```
209+
210+
Then use the token to log in with `chainctl`. Provide the UIDP of the identity as `<identity-id>`:
211+
212+
```shell
213+
chainctl auth login \
214+
--identity <identity-id> \
215+
--identity-token "${TOK}"
216+
```
217+
218+
Now you will be able to issue `chainctl` commands under this assumed identity. For instance, you could list the container image repositories available to your organization:
219+
220+
```shell
221+
chainctl image repo list
222+
```
223+
224+
## Learn More
225+
226+
By following this guide, you will have created a Chainguard identity that you can use to authenticate to Chainguard from AWS. For more information about how assumable identities work in Chainguard, check out our [conceptual overview of assumable identities](/chainguard/administration/assumable-ids/assumable-ids/). Additionally, we encourage you to read through the rest of our documentation on [Administering Chainguard resources](/chainguard/administration/).

0 commit comments

Comments
 (0)