From 14ce5957f81081cee83896fd2b980b71ac4f9357 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 15 Oct 2024 11:54:06 +0100 Subject: [PATCH 01/14] Start hacking on AWS + Workload Identity JWT SVID guide --- .../aws-oidc-identity-provider-federation.mdx | 343 ++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 docs/pages/enroll-resources/workload-identity/aws-oidc-identity-provider-federation.mdx diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-identity-provider-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-identity-provider-federation.mdx new file mode 100644 index 0000000000000..0cb426a63f3a8 --- /dev/null +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-identity-provider-federation.mdx @@ -0,0 +1,343 @@ +--- +title: Configuring Workload Identity and AWS OIDC Federation with JWTs +description: Configuring AWS to accept Workload Identity JWTs as authentication using OIDC Federation +--- + + +Teleport Workload Identity is currently in Preview. This means that some +features may be missing. We're actively looking for design partners to help us +shape the future of Workload Identity and would love to +[hear your feedback](mailto:product@goteleport.com). + + +Teleport Workload Identity issues flexible short-lived identities in JWT format. +AWS OIDC Federation allows you to use these JWTs to authenticate to AWS +services. + +This can be useful in cases where a machine needs to securely authenticate with +AWS services without the use of a long-lived credential. This is because the +machine can authenticate with Teleport without using any shared secrets by +using one of our delegated join methods. + +In this guide, we'll configure Teleport Workload Identity and AWS to allow our +workload to authenticate to the AWS S3 API and upload content to a bucket. + +## How it works + +This implementation differs from using the Teleport Application Service to protect +AWS APIs in a few ways: + +- Requests to AWS are not proxied through the Teleport Proxy Service, meaning + reduced latency but also less visibility, as these requests will not be + recorded in Teleport's audit log. +- Workload Identity works with any AWS client, including the command-line tool + but also their SDKs. +- Using the Teleport Application Service to access AWS does not work with Machine + ID and therefore cannot be used when a machine needs to authenticate with AWS. + +## Prerequisites + +(!docs/pages/includes/edition-prereqs-tabs.mdx!) + +- (!docs/pages/includes/tctl.mdx!) +- `tbot` must already be installed and configured on the host where the +workloads which need to access Teleport Workload Identity will run. For more +information, see the [deployment guides](../machine-id/deployment.mdx). + +### Deciding on a SPIFFE ID structure + +Within Teleport Workload Identity, all identities are represented using a +SPIFFE ID. This is a URI that uniquely identifies the entity that the identity +represents. The scheme is always `spiffe://`, and the host will be the name of +your Teleport cluster. The structure of the path of this URI is up to you. + +For the purposes of this guide, we will be granting access to GCP to the +`spiffe://example.teleport.sh/svc/example-service` SPIFFE ID. + +If you have already deployed Teleport Workload Identity, then you will already +have a SPIFFE ID structure in place. If you have not, then you will need to +decide on a structure for your SPIFFE IDs. + +If you are only using Teleport Workload Identity with AWS OIDC Federation, you +may structure your SPIFFE IDs so that they explicitly specify the AWS role they +are allowed to assume. However, it often makes more sense to name the workload +or person that will use the SPIFFE ID. See the +[best practices guide](./best-practices.mdx) for further advice. + +## Step 1/4. Configure AWS + +Configuring AWS OIDC Federation for the first time involves a few steps. Some of +these may not be necessary if you have previously configured AWS OIDC Federation +for your Teleport cluster. + +### Create an OpenID Connect Identity Provider + +First, you'll need to create a + +When configuring the provider, you need to specify the issuer URI. This will be +the public address of your Teleport Proxy Service with the path +`/workload-identity` appended. Your Teleport Proxy Service must be accessible +by AWS in order for OIDC federation to work. + + + + +When using the AWS Terraform Provider, you must also determine the thumbprint of +the certificate used by the Teleport Proxy Service. + +```hcl +resource "aws_iam_openid_connect_provider" "leaf_tele_ottr_sh_workload_identity" { + // Replace "example.teleport.sh" with the hostname used to access your + // Teleport Proxy Service. + url = "https://example.teleport.sh/workload-identity" + + client_id_list = [ + "sts.amazonaws.com", + ] + + thumbprint_list = [ + "5f28d9c589ee4bf31a11b78c72b8d13f079ddc45" + ] +} +``` + + + +Use the `aws` CLI to create an OpenID connect identity provider: + +```code +# Replace "workload-id-pool" with a meaningful, unique name. +$ aws iam create-open-id-connect-provider \ + --url "https://example.teleport.sh/workload-identity" \ + --client-id-list "sts.amazonaws.com" +``` + + + + + +### Create an S3 bucket and RBAC + +For the purposes of this guide, we'll be granting the workload access to an +AWS S3 bucket. You can substitute this step to grant access to a different +service within AWS of your choice. + +To grant our workload access to the bucket, we'll create a new IAM role for it +to assume, and create an IAM policy that grants the necessary permissions to +bucket. + +When creating the IAM role, we'll create a trust policy that controls which +workload identities are able to assume the role. This policy will contain +conditions which will be evaluated against the claims within the JWT SVID +issued by Teleport Workload Identity. + + + + +```hcl +resource "google_storage_bucket" "demo" { + // Replace with a meaningful, unique name. + name = "example" + location = "EU" + force_destroy = true + + uniform_bucket_level_access = true +} + +locals { + // Replace with the SPIFFE ID of the workload that will access the bucket. + allow_spiffe_id = "spiffe://example.teleport.sh/svc/example-service" +} + +resource "google_storage_bucket_iam_binding" "binding" { + bucket = google_storage_bucket.demo.name + role = "roles/storage.admin" + members = [ + "principal://iam.googleapis.com/projects/${data.google_project.project.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.leaf_cluster.workload_identity_pool_id}/subject/${local.allow_spiffe_id}", + ] +} +``` + + + + +Create a storage bucket using the `gcloud` CLI: + +```code +# Replace "example" with a meaningful, unique name. +$ gcloud storage buckets create gs://example \ + --location=EU \ + --uniform-bucket-level-access +``` + +Use the `gcloud` CLI to grant our workload access to the bucket: + +```code +$ ROLE="roles/storage.admin" +# Replace PROJECT_NUMBER with your GCP project number. +$ PROJECT_NUMBER="123456789000" +# Replace POOL_ID with the ID of the Workload Identity Pool you created. +$ POOL_ID="workload-id-pool" +# Replace SPIFFE_ID with the SPIFFE ID of the workload that will access the bucket. +$ SPIFFE_ID="spiffe://example.teleport.sh/svc/example-service" +$ MEMBER="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_ID}/subject/${SPIFFE_ID}" +$ gcloud storage buckets add-iam-policy-binding gs://example --member=$MEMBER --role=$ROLE +``` + + + + +## Step 2/4. Configure Teleport RBAC + +Now we need to configure Teleport to allow a JWT to be issued containing the +SPIFFE ID we have chosen. + +Create `role.yaml` with the following content: + +```yaml +kind: role +version: v6 +metadata: + name: my-workload-gcp +spec: + allow: + spiffe: + - path: /svc/example-service +``` + +Replace: + +- `my-workload-gcp` with a descriptive name for the role. +- `/svc/example-service` with the path part of the SPIFFE ID you have chosen. + +Apply this role to your Teleport cluster using `tctl`: + +```code +$ tctl create -f role.yaml +``` + +You now need to assign this role to the bot: + +```code +$ tctl bots update my-bot --add-roles my-workload-gcp +``` + +## Step 3/4. Issue Workload Identity JWTs + +You'll now configure `tbot` to issue and renew the short-lived JWT SVIDs for +your workload. It'll write the JWT as a file on disk, where you can then +configure GCP clients and SDKs to read it. + +Before configuring this, you'll need to determine the correct audience to +request in the JWT SVIDs. This is specific to the Workload Identity Federation +configuration you have just created and contains three components: + +- The project number of your GCP project +- The name of your Workload Identity Federation pool as configured in GCP +- The name of your Workload Identity Federation provider as configured in GCP + +It has the following format: `https://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_NAME/providers/$PROVIDER_NAME`. + +Take your already deployed `tbot` service and configure it to issue SPIFFE SVIDs +by adding the following to the `tbot` configuration file: + +```yaml +outputs: + - type: spiffe-svid + destination: + type: directory + path: /opt/workload-identity + svid: + path: /svc/example-service + jwts: + - audience: https://iam.googleapis.com/projects/123456789000/locations/global/workloadIdentityPools/workload-id-pool/providers/workload-id-oidc + file_name: gcp-jwt +``` + +Replace: + +- `123456789000` with your GCP project number. +- `workload-id-pool` with the name of your Workload Identity Federation pool. +- `workload-id-oidc` with the name of your Workload Identity Federation provider. + +Restart your `tbot` service to apply the new configuration. You should see a +file created at `/opt/workload-identity/gcp-jwt` containing the JWT. + +## Step 4/4. Configure GCP CLIs and SDKs + +Finally, you need to create a configuration file to configure the GCP CLIs and +SDKs to authenticate using Workload Identity. This configuration file will +specify the path to the JWT file that `tbot` is writing and will specify which +Workload Identity Federation pool and provider to use. + +You can generate this configuration file using the `gcloud` CLI: + +```code +$ gcloud iam workload-identity-pools create-cred-config \ + projects/123456789000/locations/global/workloadIdentityPools/workload-id-pool/providers/workload-id-oidc \ + --output-file=gcp-workload-identity.json \ + --credential-source-file=/opt/workload-identity/gcp-jwt \ + --credential-source-type=text +``` + +Replace: + +- `123456789000` with your GCP project number. +- `workload-id-pool` with the name of your Workload Identity Federation pool. +- `workload-id-oidc` with the name of your Workload Identity Federation provider. +- `/opt/workload-identity/gcp-jwt` with the path to the JWT file that `tbot` is + writing. + +The command should have created a file called `gcp-workload-identity.json` in +the current directory. + +### `gcloud` CLI + +To configure the `gcloud` CLI to authenticate using Workload Identity, you use +the `gcloud auth login` command and specify the path to the configuration file +that you have just created: + +```code +$ gcloud auth login --cred-file gcp-workload-identity.json +``` + +You can now test authenticating to the GCP Storage API. Create a file which +you can upload to your bucket: + +```code +$ echo "Hello, World!" > hello.txt +``` + +Now, use the `gcloud` CLI to upload this file to your bucket: + +```code +$ gcloud storage cp hello.txt gs://example +``` + +If everything is configured correctly, you should see this file uploaded to your +bucket. Inspecting the audit logs on GCP should indicate that the request was +authenticated using Workload Identity and specify the SPIFFE ID of the workload +that made the request. + +### GCP SDKs + +To configure the GCP SDKs to authenticate using Workload Identity, you need to +set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of the +configuration file that you have just created: + +```code +$ export GOOGLE_APPLICATION_CREDENTIALS=gcp-workload-identity.json +``` + +## Next steps + +- [GCP Workload Identity Federation documentation](https://cloud.google.com/iam/docs/workload-identity-federation): +The official GCP documentation for Workload Identity Federation. +- [Workload Identity Overview](./introduction.mdx): Overview of Teleport +Workload Identity. +- [JWT SVID Overview](./jwt-svids.mdx): Overview of the JWT SVIDs issued by +Teleport Workload Identity. +- [Best Practices](./best-practices.mdx): Best practices for using Workload +Identity in Production. +- Read the [configuration reference](../../reference/machine-id/configuration.mdx) to explore +all the available configuration options. From 9e428c4a83b907a474d84a0767df9e3e564e3c41 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 15 Oct 2024 13:03:14 +0100 Subject: [PATCH 02/14] Add Roles Anywhere vs OIDC federation section --- ...federation.mdx => aws-oidc-federation.mdx} | 19 +++++++++++++++++++ .../workload-identity/aws-roles-anywhere.mdx | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) rename docs/pages/enroll-resources/workload-identity/{aws-oidc-identity-provider-federation.mdx => aws-oidc-federation.mdx} (93%) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-identity-provider-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx similarity index 93% rename from docs/pages/enroll-resources/workload-identity/aws-oidc-identity-provider-federation.mdx rename to docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index 0cb426a63f3a8..d47fd351076bd 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-identity-provider-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -35,6 +35,25 @@ AWS APIs in a few ways: - Using the Teleport Application Service to access AWS does not work with Machine ID and therefore cannot be used when a machine needs to authenticate with AWS. +## OIDC Federation vs Roles Anywhere + +The AWS platform offers two routes for workload identity federation: OIDC +Federation and Roles Anywhere. Teleport Workload Identity supports both of these +methods. + +There are a number of differences between the two methods: + +- OIDC Federation exchanges a JWT SVID for an AWS credential, whereas Roles + Anywhere exchanges an X509 SVID for an AWS credential. The use of X509 SVIDs + is generally considered more secure. +- OIDC Federation does not require the additional installation of an AWS + credential helper alongside workloads, whereas Roles Anywhere does. +- OIDC Federation requires that your Teleport Proxy Service is reachable by + AWS, whereas Roles Anywhere does not. + +This guide covers configuring OIDC federation, for Roles Anywhere, see +[Configuring Workload Identity and AWS Roles Anywhere](./aws-roles-anywhere.mdx). + ## Prerequisites (!docs/pages/includes/edition-prereqs-tabs.mdx!) diff --git a/docs/pages/enroll-resources/workload-identity/aws-roles-anywhere.mdx b/docs/pages/enroll-resources/workload-identity/aws-roles-anywhere.mdx index 3d3d3e49b4113..bbbe4116ae9d3 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-roles-anywhere.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-roles-anywhere.mdx @@ -37,6 +37,25 @@ Whilst this guide is primarily aimed at allowing a machine to access AWS, the `tsh svid issue` command can be used in place of Machine ID to allow a human user to authenticate with using AWS Roles Anywhere. +## OIDC Federation vs Roles Anywhere + +The AWS platform offers two routes for workload identity federation: OIDC +Federation and Roles Anywhere. Teleport Workload Identity supports both of these +methods. + +There are a number of differences between the two methods: + +- Roles Anywhere exchanges an X509 SVID for an AWS credential, whereas OIDC + Federation exchanges a JWT SVID for an AWS credential. The use of X509 SVIDs + is generally considered more secure. +- Roles Anywhere requires the installation of an AWS credential helper alongside + the workloads, whereas OIDC Federation does not. +- Roles Anywhere does not require the Teleport Proxy Service to be reachable by + AWS, whereas OIDC Federation does. + +This guide covers configuring Roles Anywhere, for OIDC federation, see +[Configuring Workload Identity and AWS OIDC Federation](./aws-oidc-federation.mdx). + ## Prerequisites (!docs/pages/includes/edition-prereqs-tabs.mdx!) From 8e26b89f14fbd6e580c67f1f4c1995a6a816a9d7 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 15 Oct 2024 14:20:24 +0100 Subject: [PATCH 03/14] Set up links for AWS OIDC federation docs --- .../workload-identity/aws-oidc-federation.mdx | 4 ++-- .../enroll-resources/workload-identity/introduction.mdx | 5 +++-- docs/pages/enroll-resources/workload-identity/jwt-svids.mdx | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index d47fd351076bd..ed714ad26a5f3 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -350,8 +350,8 @@ $ export GOOGLE_APPLICATION_CREDENTIALS=gcp-workload-identity.json ## Next steps -- [GCP Workload Identity Federation documentation](https://cloud.google.com/iam/docs/workload-identity-federation): -The official GCP documentation for Workload Identity Federation. +- [AWS OIC Federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html): +The official AWS documentation for OIDC federation. - [Workload Identity Overview](./introduction.mdx): Overview of Teleport Workload Identity. - [JWT SVID Overview](./jwt-svids.mdx): Overview of the JWT SVIDs issued by diff --git a/docs/pages/enroll-resources/workload-identity/introduction.mdx b/docs/pages/enroll-resources/workload-identity/introduction.mdx index 2c1af78ce8e87..8c50fdcdcf306 100644 --- a/docs/pages/enroll-resources/workload-identity/introduction.mdx +++ b/docs/pages/enroll-resources/workload-identity/introduction.mdx @@ -157,8 +157,9 @@ Learn how to configure Teleport Workload Identity for specific use-cases: - [Getting Started](./getting-started.mdx): How to configure Teleport for Workload Identity. - [TSH Support](./tsh.mdx): How to use `tsh` with Workload Identity to issue SVIDs to users. -- [AWS Roles Anywhere](./aws-roles-anywhere.mdx): Configuring AWS to accept Workload ID certificates as authentication using AWS Roles Anywhere. -- [GCP Workload Identity Federation](./gcp-workload-identity-federation-jwt.mdx): Configuring GCP to accept Workload ID JWTs as authentication using GCP Workload Identity Federation. +- [AWS Roles Anywhere](./aws-roles-anywhere.mdx): Configuring AWS to accept Workload Identity certificates as authentication using AWS Roles Anywhere. +- [AWS OIDC Federation](./aws-oidc-federation.mdx): Configuring AWS to accept Workload Identity JWTs as authentication using AWS OIDC Federation. +- [GCP Workload Identity Federation](./gcp-workload-identity-federation-jwt.mdx): Configuring GCP to accept Workload Identity JWTs as authentication using GCP Workload Identity Federation. ### Other resources diff --git a/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx b/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx index d4d376b89a0a9..88d85d4bbc835 100644 --- a/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx +++ b/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx @@ -59,7 +59,7 @@ Teleport Proxy service as the issuer URL for OIDC configuration. We have tested Teleport Workload Identity issued JWT-SVIDs with the following platforms: -- AWS +- [AWS](./aws-oidc-federation.mdx) - [Google Cloud Platform](./gcp-workload-identity-federation-jwt.mdx) - Azure From e61e65cc8a0b146a4cea03f0ddca2fd1f2155f99 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 15 Oct 2024 17:43:46 +0100 Subject: [PATCH 04/14] Keep hacking on docs --- .../workload-identity/aws-oidc-federation.mdx | 155 +++++++++--------- 1 file changed, 80 insertions(+), 75 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index ed714ad26a5f3..bef514302cb5f 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -91,7 +91,10 @@ for your Teleport cluster. ### Create an OpenID Connect Identity Provider -First, you'll need to create a +First, you'll need to create an OIDC identity provider in AWS. This will define +a trust relationship between AWS and your Teleport cluster's Workload Identity +issuer. You can reuse this OIDC identity provider to grant different workloads +using Teleport Workload Identity access to AWS services. When configuring the provider, you need to specify the issuer URI. This will be the public address of your Teleport Proxy Service with the path @@ -101,8 +104,14 @@ by AWS in order for OIDC federation to work. -When using the AWS Terraform Provider, you must also determine the thumbprint of -the certificate used by the Teleport Proxy Service. +Before you can configure the OIDC identity provider, you need to determine the +thumbprint of the TLS certificate used by your Teleport Proxy Service. You can +do this using `curl`: + +```code +$ curl https://example.teleport.sh/webapi/thumbprint +"example589ee4bf31a11b78c72b8d13f0example"% +``` ```hcl resource "aws_iam_openid_connect_provider" "leaf_tele_ottr_sh_workload_identity" { @@ -115,21 +124,15 @@ resource "aws_iam_openid_connect_provider" "leaf_tele_ottr_sh_workload_identity" ] thumbprint_list = [ - "5f28d9c589ee4bf31a11b78c72b8d13f079ddc45" + // Replace with the thumbprint you determined using curl. + "example589ee4bf31a11b78c72b8d13f0example" ] } ``` -Use the `aws` CLI to create an OpenID connect identity provider: -```code -# Replace "workload-id-pool" with a meaningful, unique name. -$ aws iam create-open-id-connect-provider \ - --url "https://example.teleport.sh/workload-identity" \ - --client-id-list "sts.amazonaws.com" -``` @@ -137,72 +140,86 @@ $ aws iam create-open-id-connect-provider \ ### Create an S3 bucket and RBAC -For the purposes of this guide, we'll be granting the workload access to an +For the purposes of this guide, you'll be granting the workload access to an AWS S3 bucket. You can substitute this step to grant access to a different service within AWS of your choice. -To grant our workload access to the bucket, we'll create a new IAM role for it -to assume, and create an IAM policy that grants the necessary permissions to -bucket. +First, you'll create an IAM role. This role will be assumed by the workload +after it authenticates to AWS using the JWT SVID issued by Teleport Workload +Identity. -When creating the IAM role, we'll create a trust policy that controls which +When creating the IAM role, you'll define a trust policy that controls which workload identities are able to assume the role. This policy will contain conditions which will be evaluated against the claims within the JWT SVID issued by Teleport Workload Identity. +With the IAM role created, you will then attach an IAM policy to it to define +what privileges the workload will have when it assumes the role. + ```hcl -resource "google_storage_bucket" "demo" { - // Replace with a meaningful, unique name. - name = "example" - location = "EU" - force_destroy = true +// Create an S3 bucket +resource "aws_s3_bucket" "example" { + // Replace "example" with a meaningful, unique name. + bucket = "workload-id-demo" +} - uniform_bucket_level_access = true +// Create a role that the workload identity will assume. +resource "aws_iam_role" "example" { + // Choose a unique, meaningful name that describes the role and the workload + // that will assume it. + name = "workload-id-demo" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Principal = { + Federated = aws_iam_openid_connect_provider.example.arn + } + Action = "sts:AssumeRoleWithWebIdentity" + Condition = { + StringEquals = { + "${aws_iam_openid_connect_provider.example.url}:aud" = "sts.amazonaws.com" + "${aws_iam_openid_connect_provider.example.url}:sub" = "spiffe://example.teleport.sh/svc/example-service" + } + } + }] + }) } -locals { - // Replace with the SPIFFE ID of the workload that will access the bucket. - allow_spiffe_id = "spiffe://example.teleport.sh/svc/example-service" +resource "aws_iam_policy" "example" { + // Choose a unique, meaningful name that describes what the policy grants + // access to. + name = "workload-id-s3-full-access" + path = "/" + + // This example policy grants full access to AWS S3. In production, you + // may wish to grant a less permissive policy. + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = "s3:*" + Effect = "Allow" + Resource = [ + aws_s3_bucket.workload_id_demo.arn, + "${aws_s3_bucket.workload_id_demo.arn}/*" + ] + }] + }) } -resource "google_storage_bucket_iam_binding" "binding" { - bucket = google_storage_bucket.demo.name - role = "roles/storage.admin" - members = [ - "principal://iam.googleapis.com/projects/${data.google_project.project.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.leaf_cluster.workload_identity_pool_id}/subject/${local.allow_spiffe_id}", - ] +// Attach the policy to the role +resource "aws_iam_role_policy_attachment" "example" { + role = aws_iam_role.example.name + policy_arn = aws_iam_policy.example.arn } ``` -Create a storage bucket using the `gcloud` CLI: - -```code -# Replace "example" with a meaningful, unique name. -$ gcloud storage buckets create gs://example \ - --location=EU \ - --uniform-bucket-level-access -``` - -Use the `gcloud` CLI to grant our workload access to the bucket: - -```code -$ ROLE="roles/storage.admin" -# Replace PROJECT_NUMBER with your GCP project number. -$ PROJECT_NUMBER="123456789000" -# Replace POOL_ID with the ID of the Workload Identity Pool you created. -$ POOL_ID="workload-id-pool" -# Replace SPIFFE_ID with the SPIFFE ID of the workload that will access the bucket. -$ SPIFFE_ID="spiffe://example.teleport.sh/svc/example-service" -$ MEMBER="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_ID}/subject/${SPIFFE_ID}" -$ gcloud storage buckets add-iam-policy-binding gs://example --member=$MEMBER --role=$ROLE -``` - @@ -217,7 +234,7 @@ Create `role.yaml` with the following content: kind: role version: v6 metadata: - name: my-workload-gcp + name: my-workload-aws spec: allow: spiffe: @@ -226,7 +243,7 @@ spec: Replace: -- `my-workload-gcp` with a descriptive name for the role. +- `my-workload-aws` with a descriptive name for the role. - `/svc/example-service` with the path part of the SPIFFE ID you have chosen. Apply this role to your Teleport cluster using `tctl`: @@ -238,24 +255,14 @@ $ tctl create -f role.yaml You now need to assign this role to the bot: ```code -$ tctl bots update my-bot --add-roles my-workload-gcp +$ tctl bots update my-bot --add-roles my-workload-aws ``` ## Step 3/4. Issue Workload Identity JWTs You'll now configure `tbot` to issue and renew the short-lived JWT SVIDs for your workload. It'll write the JWT as a file on disk, where you can then -configure GCP clients and SDKs to read it. - -Before configuring this, you'll need to determine the correct audience to -request in the JWT SVIDs. This is specific to the Workload Identity Federation -configuration you have just created and contains three components: - -- The project number of your GCP project -- The name of your Workload Identity Federation pool as configured in GCP -- The name of your Workload Identity Federation provider as configured in GCP - -It has the following format: `https://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_NAME/providers/$PROVIDER_NAME`. +configure AWS clients and SDKs to read it. Take your already deployed `tbot` service and configure it to issue SPIFFE SVIDs by adding the following to the `tbot` configuration file: @@ -269,20 +276,18 @@ outputs: svid: path: /svc/example-service jwts: - - audience: https://iam.googleapis.com/projects/123456789000/locations/global/workloadIdentityPools/workload-id-pool/providers/workload-id-oidc - file_name: gcp-jwt + - audience: sts.amazonaws.com + file_name: aws-jwt ``` Replace: -- `123456789000` with your GCP project number. -- `workload-id-pool` with the name of your Workload Identity Federation pool. -- `workload-id-oidc` with the name of your Workload Identity Federation provider. +- Restart your `tbot` service to apply the new configuration. You should see a -file created at `/opt/workload-identity/gcp-jwt` containing the JWT. +file created at `/opt/workload-identity/aws-jwt` containing the JWT. -## Step 4/4. Configure GCP CLIs and SDKs +## Step 4/4. Configure AWS CLIs and SDKs Finally, you need to create a configuration file to configure the GCP CLIs and SDKs to authenticate using Workload Identity. This configuration file will From fbe019a26f7af6b6ab11a4e82017b283f804694e Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Wed, 16 Oct 2024 10:01:56 +0100 Subject: [PATCH 05/14] Add AWS Console steps --- .../workload-identity/aws-oidc-federation.mdx | 189 ++++++++++++------ .../gcp-workload-identity-federation-jwt.mdx | 5 + .../workload-identity/jwt-svids.mdx | 2 + 3 files changed, 136 insertions(+), 60 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index bef514302cb5f..302c4a54c107c 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -63,6 +63,11 @@ This guide covers configuring OIDC federation, for Roles Anywhere, see workloads which need to access Teleport Workload Identity will run. For more information, see the [deployment guides](../machine-id/deployment.mdx). + +Issuing JWT SVIDs with Teleport Workload Identity requires at minimum version +16.4.3. + + ### Deciding on a SPIFFE ID structure Within Teleport Workload Identity, all identities are represented using a @@ -115,34 +120,68 @@ $ curl https://example.teleport.sh/webapi/thumbprint ```hcl resource "aws_iam_openid_connect_provider" "leaf_tele_ottr_sh_workload_identity" { - // Replace "example.teleport.sh" with the hostname used to access your - // Teleport Proxy Service. - url = "https://example.teleport.sh/workload-identity" - - client_id_list = [ - "sts.amazonaws.com", - ] - - thumbprint_list = [ - // Replace with the thumbprint you determined using curl. - "example589ee4bf31a11b78c72b8d13f0example" - ] + // Replace "example.teleport.sh" with the hostname used to access your + // Teleport Proxy Service. + url = "https://example.teleport.sh/workload-identity" + + client_id_list = [ + "sts.amazonaws.com", + ] + + thumbprint_list = [ + // Replace with the thumbprint you determined using curl. + "example589ee4bf31a11b78c72b8d13f0example" + ] } ``` +1. Browse to IAM +2. Select "Identity Providers" from the sidebar +3. Select "Add provider" +4. Select "OpenID Connect" as the "Provider type". +5. Specify the public hostname of your Teleport Proxy Service, with + "/workload-identity" appended as the "Provider URL", e.g + `https://example.teleport.sh/workload-identity` +6. Specify `sts.amazonaws.com` as the Audience +7. Click "Add Provider". - -### Create an S3 bucket and RBAC +### Create an S3 bucket For the purposes of this guide, you'll be granting the workload access to an -AWS S3 bucket. You can substitute this step to grant access to a different -service within AWS of your choice. +AWS S3 bucket. Before we can dive into configuring the RBAC, we'll need to +create our bucket. + +You can omit this step if you wish to grant access to a different service +within AWS. + + + +```hcl +// Create an S3 bucket +resource "aws_s3_bucket" "example" { + // Replace "example" with a meaningful, unique name. + bucket = "workload-id-demo" +} +``` + + + +1. Browse to S3 +2. Select "Create bucket" +3. Enter a meaningful, unique name for your bucket, e.g `workload-id-demo` +4. Leave other settings as default +5. Click "Create bucket". + + + + +### Configuring RBAC First, you'll create an IAM role. This role will be assumed by the workload after it authenticates to AWS using the JWT SVID issued by Teleport Workload @@ -151,7 +190,8 @@ Identity. When creating the IAM role, you'll define a trust policy that controls which workload identities are able to assume the role. This policy will contain conditions which will be evaluated against the claims within the JWT SVID -issued by Teleport Workload Identity. +issued by Teleport Workload Identity. In our case, the only claim we want to +evaluate is the `sub` claim, which will contain our workload's SPIFFE ID. With the IAM role created, you will then attach an IAM policy to it to define what privileges the workload will have when it assumes the role. @@ -160,54 +200,48 @@ what privileges the workload will have when it assumes the role. ```hcl -// Create an S3 bucket -resource "aws_s3_bucket" "example" { - // Replace "example" with a meaningful, unique name. - bucket = "workload-id-demo" -} - // Create a role that the workload identity will assume. resource "aws_iam_role" "example" { - // Choose a unique, meaningful name that describes the role and the workload - // that will assume it. - name = "workload-id-demo" - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [{ - Effect = "Allow" - Principal = { - Federated = aws_iam_openid_connect_provider.example.arn - } - Action = "sts:AssumeRoleWithWebIdentity" - Condition = { - StringEquals = { - "${aws_iam_openid_connect_provider.example.url}:aud" = "sts.amazonaws.com" - "${aws_iam_openid_connect_provider.example.url}:sub" = "spiffe://example.teleport.sh/svc/example-service" - } - } - }] - }) + // Choose a unique, meaningful name that describes the role and the workload + // that will assume it. + name = "workload-id-demo" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Principal = { + Federated = aws_iam_openid_connect_provider.example.arn + } + Action = "sts:AssumeRoleWithWebIdentity" + Condition = { + StringEquals = { + "${aws_iam_openid_connect_provider.example.url}:aud" = "sts.amazonaws.com" + "${aws_iam_openid_connect_provider.example.url}:sub" = "spiffe://example.teleport.sh/svc/example-service" + } + } + }] + }) } resource "aws_iam_policy" "example" { - // Choose a unique, meaningful name that describes what the policy grants - // access to. - name = "workload-id-s3-full-access" - path = "/" - - // This example policy grants full access to AWS S3. In production, you - // may wish to grant a less permissive policy. - policy = jsonencode({ - Version = "2012-10-17" - Statement = [{ - Action = "s3:*" - Effect = "Allow" - Resource = [ - aws_s3_bucket.workload_id_demo.arn, - "${aws_s3_bucket.workload_id_demo.arn}/*" - ] - }] - }) + // Choose a unique, meaningful name that describes what the policy grants + // access to. + name = "workload-id-s3-full-access" + path = "/" + + // This example policy grants full access to AWS S3. In production, you + // may wish to grant a less permissive policy. + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = "s3:*" + Effect = "Allow" + Resource = [ + aws_s3_bucket.workload_id_demo.arn, + "${aws_s3_bucket.workload_id_demo.arn}/*" + ] + }] + }) } // Attach the policy to the role @@ -220,6 +254,41 @@ resource "aws_iam_role_policy_attachment" "example" { +### Creating an IAM Policy + +1. Browse to IAM +2. Select "Policies" from the sidebar +3. Click "Create policy" +4. Choose the "S3" service +5. Under "Actions allowed", choose "All S3 actions" +6. Under "Resources", choose "Specific" + 6a. For "bucket" enter the name of the bucket you created earlier. + 6b. For "object" enter the name of the bucket you created earlier and select + "All objects" +7. Click "Next" +8. Enter a unique and meaningful name for this policy, in our example, this will + be `workload-id-s3-full-access` +9. Click "Create policy" + +### Creating an IAM Role + +1. Browse to IAM +2. Select "Roles" from the sidebar +3. Click "Create role" +4. Select "Web identity" for the "Trusted entity type" +5. Select your identity provider +6. Select the `sts.amazonaws.com` audience +7. Click "Add condition" + 7a. Select `example.teleport.sh:sub` for the key + 7b. Select "StringEquals" for the condition + 7c. Enter the SPIFFE ID of your workload for the value. In our example, this + will be `spiffe://example.teleport.sh/svc/example +8. Click "Next" +9. Select the IAM policy you created earlier, and click "Next" +10. Enter a unique and meaningful name for this role, in our example, this will + be `workload-id-demo` +11. Click "Create role" + diff --git a/docs/pages/enroll-resources/workload-identity/gcp-workload-identity-federation-jwt.mdx b/docs/pages/enroll-resources/workload-identity/gcp-workload-identity-federation-jwt.mdx index 7feec924773a6..fe0a0c7b876d5 100644 --- a/docs/pages/enroll-resources/workload-identity/gcp-workload-identity-federation-jwt.mdx +++ b/docs/pages/enroll-resources/workload-identity/gcp-workload-identity-federation-jwt.mdx @@ -45,6 +45,11 @@ GCP APIs in a few ways: workloads which need to access Teleport Workload Identity will run. For more information, see the [deployment guides](../machine-id/deployment.mdx). + +Issuing JWT SVIDs with Teleport Workload Identity requires at minimum version +16.4.3. + + ### Deciding on a SPIFFE ID structure Within Teleport Workload Identity, all identities are represented using a diff --git a/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx b/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx index 88d85d4bbc835..ca2e47ec2c5cc 100644 --- a/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx +++ b/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx @@ -14,6 +14,8 @@ One type of credential that can be issued by Teleport Workload Identity is a JWT SVID. This is a short-lived JSON Web Token (JWT) that contains the identity of the workload and is signed by the Teleport Workload Identity CA. +The ability is issue JWT SVIDs has been available since Teleport 16.4.3. + ## Claims The JWT contains the following claims: From c6e24aa0a1136a6379757fea7aed5fa4f4909b57 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Wed, 16 Oct 2024 10:16:32 +0100 Subject: [PATCH 06/14] Finish AWS OIDC federation guide --- .../workload-identity/aws-oidc-federation.mdx | 91 +++++++++---------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index 302c4a54c107c..a21fef6203519 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -75,7 +75,7 @@ SPIFFE ID. This is a URI that uniquely identifies the entity that the identity represents. The scheme is always `spiffe://`, and the host will be the name of your Teleport cluster. The structure of the path of this URI is up to you. -For the purposes of this guide, we will be granting access to GCP to the +For the purposes of this guide, we will be granting access to AWS to the `spiffe://example.teleport.sh/svc/example-service` SPIFFE ID. If you have already deployed Teleport Workload Identity, then you will already @@ -351,81 +351,76 @@ outputs: Replace: -- +- /opt/workload-identity with the directory where you want the JWT to be + written. +- /svc/example-service with the SPIFFE ID you have chosen. Restart your `tbot` service to apply the new configuration. You should see a file created at `/opt/workload-identity/aws-jwt` containing the JWT. ## Step 4/4. Configure AWS CLIs and SDKs -Finally, you need to create a configuration file to configure the GCP CLIs and -SDKs to authenticate using Workload Identity. This configuration file will -specify the path to the JWT file that `tbot` is writing and will specify which -Workload Identity Federation pool and provider to use. +Finally, you need to configure the AWS CLIs and SDKs to use the JWT SVID for +authentication. -You can generate this configuration file using the `gcloud` CLI: +This can be done using the configuration file located at `~/.aws/config` or by +using environment variables. -```code -$ gcloud iam workload-identity-pools create-cred-config \ - projects/123456789000/locations/global/workloadIdentityPools/workload-id-pool/providers/workload-id-oidc \ - --output-file=gcp-workload-identity.json \ - --credential-source-file=/opt/workload-identity/gcp-jwt \ - --credential-source-type=text -``` - -Replace: +To proceed, you'll need to know the ARN of the role you created earlier. -- `123456789000` with your GCP project number. -- `workload-id-pool` with the name of your Workload Identity Federation pool. -- `workload-id-oidc` with the name of your Workload Identity Federation provider. -- `/opt/workload-identity/gcp-jwt` with the path to the JWT file that `tbot` is - writing. + + + +Add the following to your `~/.aws/config` file: + +```ini +# You can replace "workload-id-demo" with a recognisable name that identifies +# your use-case. +[profile workload-id-demo] +# Replace with the ARN of the role you created earlier. +role_arn=arn:aws:iam:123456789012:role/workload-id-demo +# Replace with the directory and file name you configured `tbot` to write the +# JWT to. +web_identity_token_file=/opt/workload-identity/aws-jwt +``` -The command should have created a file called `gcp-workload-identity.json` in -the current directory. + + -### `gcloud` CLI +Configure the following environment variables: -To configure the `gcloud` CLI to authenticate using Workload Identity, you use -the `gcloud auth login` command and specify the path to the configuration file -that you have just created: +- `AWS_ROLE_ARN`: The ARN of the role you created earlier, e.g + `arn:aws:iam::123456789012:role/workload-id-demo` +- `AWS_WEB_IDENTITY_TOKEN_FILE`: The path to the JWT file that `tbot` is writing, + e.g `/opt/workload-identity/aws-jwt` -```code -$ gcloud auth login --cred-file gcp-workload-identity.json -``` + + -You can now test authenticating to the GCP Storage API. Create a file which -you can upload to your bucket: +You can now test authenticating to the AWS S3 API. Create a file which you can +upload to your bucket: ```code $ echo "Hello, World!" > hello.txt ``` -Now, use the `gcloud` CLI to upload this file to your bucket: +Now, use the AWS CLI to upload this file to your bucket: ```code -$ gcloud storage cp hello.txt gs://example +$ aws s3 cp hello.txt s3://workload-id-demo ``` If everything is configured correctly, you should see this file uploaded to your -bucket. Inspecting the audit logs on GCP should indicate that the request was -authenticated using Workload Identity and specify the SPIFFE ID of the workload -that made the request. - -### GCP SDKs - -To configure the GCP SDKs to authenticate using Workload Identity, you need to -set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of the -configuration file that you have just created: - -```code -$ export GOOGLE_APPLICATION_CREDENTIALS=gcp-workload-identity.json -``` +bucket. Inspecting the audit logs on CloudTrail should indicate that the request +was authenticated using Workload Identity and specify the SPIFFE ID of the +workload that made the request. ## Next steps -- [AWS OIC Federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html): +- [AWS OIDC Federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html): The official AWS documentation for OIDC federation. +- [AWS CLI documentation](https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-role.html#cli-configure-role-oidc): +The official AWS CLI documentation for configuring a role to be assumed. - [Workload Identity Overview](./introduction.mdx): Overview of Teleport Workload Identity. - [JWT SVID Overview](./jwt-svids.mdx): Overview of the JWT SVIDs issued by From 8618ff645fd3e9c37de1de689a7bd5c7f3035c15 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Mon, 21 Oct 2024 16:56:23 +0100 Subject: [PATCH 07/14] Update docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx Co-authored-by: Paul Gottschling --- .../enroll-resources/workload-identity/aws-oidc-federation.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index a21fef6203519..b9b9f5f1afa13 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -181,7 +181,7 @@ resource "aws_s3_bucket" "example" { -### Configuring RBAC +### Configure RBAC First, you'll create an IAM role. This role will be assumed by the workload after it authenticates to AWS using the JWT SVID issued by Teleport Workload From 74d279357e3bd24c8abfa42652b0b7f0adfd5268 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 22 Oct 2024 09:37:54 +0100 Subject: [PATCH 08/14] Update docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx Co-authored-by: Paul Gottschling --- .../enroll-resources/workload-identity/aws-oidc-federation.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index b9b9f5f1afa13..a922041da9101 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -51,7 +51,7 @@ There are a number of differences between the two methods: - OIDC Federation requires that your Teleport Proxy Service is reachable by AWS, whereas Roles Anywhere does not. -This guide covers configuring OIDC federation, for Roles Anywhere, see +This guide covers configuring OIDC federation. For Roles Anywhere, see [Configuring Workload Identity and AWS Roles Anywhere](./aws-roles-anywhere.mdx). ## Prerequisites From a29d4c92ad3e6ee24e67b8a5252ba2d1ad99aa93 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 22 Oct 2024 09:43:09 +0100 Subject: [PATCH 09/14] Use 1 for all OL elementss --- .../workload-identity/aws-oidc-federation.mdx | 77 +++++++++++-------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index a922041da9101..18ffebc542fda 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -118,6 +118,9 @@ $ curl https://example.teleport.sh/webapi/thumbprint "example589ee4bf31a11b78c72b8d13f0example"% ``` +Insert the following into a Terraform configuration file which has already +been configured to manage your AWS account: + ```hcl resource "aws_iam_openid_connect_provider" "leaf_tele_ottr_sh_workload_identity" { // Replace "example.teleport.sh" with the hostname used to access your @@ -139,14 +142,14 @@ resource "aws_iam_openid_connect_provider" "leaf_tele_ottr_sh_workload_identity" 1. Browse to IAM -2. Select "Identity Providers" from the sidebar -3. Select "Add provider" -4. Select "OpenID Connect" as the "Provider type". -5. Specify the public hostname of your Teleport Proxy Service, with +1. Select "Identity Providers" from the sidebar +1. Select "Add provider" +1. Select "OpenID Connect" as the "Provider type". +1. Specify the public hostname of your Teleport Proxy Service, with "/workload-identity" appended as the "Provider URL", e.g `https://example.teleport.sh/workload-identity` -6. Specify `sts.amazonaws.com` as the Audience -7. Click "Add Provider". +1. Specify `sts.amazonaws.com` as the Audience +1. Click "Add Provider". @@ -173,10 +176,10 @@ resource "aws_s3_bucket" "example" { 1. Browse to S3 -2. Select "Create bucket" -3. Enter a meaningful, unique name for your bucket, e.g `workload-id-demo` -4. Leave other settings as default -5. Click "Create bucket". +1. Select "Create bucket" +1. Enter a meaningful, unique name for your bucket, e.g `workload-id-demo` +1. Leave other settings as default +1. Click "Create bucket". @@ -257,37 +260,37 @@ resource "aws_iam_role_policy_attachment" "example" { ### Creating an IAM Policy 1. Browse to IAM -2. Select "Policies" from the sidebar -3. Click "Create policy" -4. Choose the "S3" service -5. Under "Actions allowed", choose "All S3 actions" -6. Under "Resources", choose "Specific" - 6a. For "bucket" enter the name of the bucket you created earlier. - 6b. For "object" enter the name of the bucket you created earlier and select +1. Select "Policies" from the sidebar +1. Click "Create policy" +1. Choose the "S3" service +1. Under "Actions allowed", choose "All S3 actions" +1. Under "Resources", choose "Specific" + 1. For "bucket" enter the name of the bucket you created earlier. + 1. For "object" enter the name of the bucket you created earlier and select "All objects" -7. Click "Next" -8. Enter a unique and meaningful name for this policy, in our example, this will +1. Click "Next" +1. Enter a unique and meaningful name for this policy, in our example, this will be `workload-id-s3-full-access` -9. Click "Create policy" +1. Click "Create policy" ### Creating an IAM Role 1. Browse to IAM -2. Select "Roles" from the sidebar -3. Click "Create role" -4. Select "Web identity" for the "Trusted entity type" -5. Select your identity provider -6. Select the `sts.amazonaws.com` audience -7. Click "Add condition" - 7a. Select `example.teleport.sh:sub` for the key - 7b. Select "StringEquals" for the condition - 7c. Enter the SPIFFE ID of your workload for the value. In our example, this +1. Select "Roles" from the sidebar +1. Click "Create role" +1. Select "Web identity" for the "Trusted entity type" +1. Select your identity provider +1. Select the `sts.amazonaws.com` audience +1. Click "Add condition" + 1. Select `example.teleport.sh:sub` for the key + 1. Select "StringEquals" for the condition + 1. Enter the SPIFFE ID of your workload for the value. In our example, this will be `spiffe://example.teleport.sh/svc/example -8. Click "Next" -9. Select the IAM policy you created earlier, and click "Next" -10. Enter a unique and meaningful name for this role, in our example, this will +1. Click "Next" +1. Select the IAM policy you created earlier, and click "Next" +1. Enter a unique and meaningful name for this role, in our example, this will be `workload-id-demo` -11. Click "Create role" +1. Click "Create role" @@ -411,7 +414,13 @@ $ aws s3 cp hello.txt s3://workload-id-demo ``` If everything is configured correctly, you should see this file uploaded to your -bucket. Inspecting the audit logs on CloudTrail should indicate that the request +bucket: + +```code +$ aws s3 ls s3://workload-id-demo +``` + +Inspecting the audit logs on CloudTrail should indicate that the request was authenticated using Workload Identity and specify the SPIFFE ID of the workload that made the request. From 433634cf78a51a74153e9a187c1e4468bd5b8485 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 22 Oct 2024 09:46:27 +0100 Subject: [PATCH 10/14] Drop JWT from title --- .../enroll-resources/workload-identity/aws-oidc-federation.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index 18ffebc542fda..bf208e6c93c76 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -1,5 +1,5 @@ --- -title: Configuring Workload Identity and AWS OIDC Federation with JWTs +title: Configuring Workload Identity and AWS OIDC Federation description: Configuring AWS to accept Workload Identity JWTs as authentication using OIDC Federation --- From 922bf0318bdd3f76b64c20f7a199825596f25161 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 22 Oct 2024 09:59:08 +0100 Subject: [PATCH 11/14] Split role and policy creation --- .../workload-identity/aws-oidc-federation.mdx | 105 +++++++++++------- 1 file changed, 63 insertions(+), 42 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index bf208e6c93c76..a74cde7514c4a 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -186,46 +186,21 @@ resource "aws_s3_bucket" "example" { ### Configure RBAC -First, you'll create an IAM role. This role will be assumed by the workload -after it authenticates to AWS using the JWT SVID issued by Teleport Workload -Identity. +#### Create an IAM Policy -When creating the IAM role, you'll define a trust policy that controls which -workload identities are able to assume the role. This policy will contain -conditions which will be evaluated against the claims within the JWT SVID -issued by Teleport Workload Identity. In our case, the only claim we want to -evaluate is the `sub` claim, which will contain our workload's SPIFFE ID. +First, create an IAM policy that will grant access to the S3 bucket. Later, +you'll attach this to a role that the workload will assume. -With the IAM role created, you will then attach an IAM policy to it to define -what privileges the workload will have when it assumes the role. +To keep things simple within this guide, the policy will grant full access to +the bucket. In a production environment, you should modify this to grant the +least privileges necessary. -```hcl -// Create a role that the workload identity will assume. -resource "aws_iam_role" "example" { - // Choose a unique, meaningful name that describes the role and the workload - // that will assume it. - name = "workload-id-demo" - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [{ - Effect = "Allow" - Principal = { - Federated = aws_iam_openid_connect_provider.example.arn - } - Action = "sts:AssumeRoleWithWebIdentity" - Condition = { - StringEquals = { - "${aws_iam_openid_connect_provider.example.url}:aud" = "sts.amazonaws.com" - "${aws_iam_openid_connect_provider.example.url}:sub" = "spiffe://example.teleport.sh/svc/example-service" - } - } - }] - }) -} +Insert the following into your Terraform configuration file: +```hcl resource "aws_iam_policy" "example" { // Choose a unique, meaningful name that describes what the policy grants // access to. @@ -246,19 +221,11 @@ resource "aws_iam_policy" "example" { }] }) } - -// Attach the policy to the role -resource "aws_iam_role_policy_attachment" "example" { - role = aws_iam_role.example.name - policy_arn = aws_iam_policy.example.arn -} ``` -### Creating an IAM Policy - 1. Browse to IAM 1. Select "Policies" from the sidebar 1. Click "Create policy" @@ -273,7 +240,61 @@ resource "aws_iam_role_policy_attachment" "example" { be `workload-id-s3-full-access` 1. Click "Create policy" -### Creating an IAM Role + + + +#### Create an IAM Role + +Now, you'll create an IAM role. This role will be assumed by the workload +after it authenticates to AWS using the JWT SVID issued by Teleport Workload +Identity. + +When creating the IAM role, you'll define a trust policy that controls which +workload identities are able to assume the role. This policy will contain +conditions which will be evaluated against the claims within the JWT SVID +issued by Teleport Workload Identity. In our case, the only claim we want to +evaluate is the `sub` claim, which will contain our workload's SPIFFE ID. + +Finally, we'll attach the IAM policy we created earlier to this role to grant it +the privileges specified within the policy. + + + + +Insert the following into your Terraform configuration file: + +```hcl +// Create a role that the workload identity will assume. +resource "aws_iam_role" "example" { + // Choose a unique, meaningful name that describes the role and the workload + // that will assume it. + name = "workload-id-demo" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Principal = { + Federated = aws_iam_openid_connect_provider.example.arn + } + Action = "sts:AssumeRoleWithWebIdentity" + Condition = { + StringEquals = { + "${aws_iam_openid_connect_provider.example.url}:aud" = "sts.amazonaws.com" + "${aws_iam_openid_connect_provider.example.url}:sub" = "spiffe://example.teleport.sh/svc/example-service" + } + } + }] + }) +} + +// Attach the policy we created earlier to our role. +resource "aws_iam_role_policy_attachment" "example" { + role = aws_iam_role.example.name + policy_arn = aws_iam_policy.example.arn +} +``` + + 1. Browse to IAM 1. Select "Roles" from the sidebar From 45a8f3c2e413290c2b3c259bf35de47dfba41a8f Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 22 Oct 2024 10:14:53 +0100 Subject: [PATCH 12/14] Rewrite minimum version statement --- .../workload-identity/aws-oidc-federation.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index a74cde7514c4a..9756317dbb66c 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -64,8 +64,8 @@ workloads which need to access Teleport Workload Identity will run. For more information, see the [deployment guides](../machine-id/deployment.mdx). -Issuing JWT SVIDs with Teleport Workload Identity requires at minimum version -16.4.3. +Issuing JWT SVIDs with Teleport Workload Identity requires at least Teleport +version 16.4.3. ### Deciding on a SPIFFE ID structure From dc94aab9b12ce41d2a6184df78c7f4cba42d13c4 Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 22 Oct 2024 10:22:54 +0100 Subject: [PATCH 13/14] Remove the word "simple" --- .../workload-identity/aws-oidc-federation.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index 9756317dbb66c..9442a159a42ea 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -191,9 +191,9 @@ resource "aws_s3_bucket" "example" { First, create an IAM policy that will grant access to the S3 bucket. Later, you'll attach this to a role that the workload will assume. -To keep things simple within this guide, the policy will grant full access to -the bucket. In a production environment, you should modify this to grant the -least privileges necessary. +The examples in this guide will create an IAM policy that will grant full access +to the example bucket. In a production environment, you should modify this to +grant the least privileges necessary. From c5d1d790ec93717b10f60001a9b81ceec50830ba Mon Sep 17 00:00:00 2001 From: Noah Stride Date: Tue, 22 Oct 2024 10:50:06 +0100 Subject: [PATCH 14/14] Appease spell-checker --- .../workload-identity/aws-oidc-federation.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx index 9442a159a42ea..6febebfaf106b 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-oidc-federation.mdx @@ -122,7 +122,7 @@ Insert the following into a Terraform configuration file which has already been configured to manage your AWS account: ```hcl -resource "aws_iam_openid_connect_provider" "leaf_tele_ottr_sh_workload_identity" { +resource "aws_iam_openid_connect_provider" "example_teleport_sh_workload_identity" { // Replace "example.teleport.sh" with the hostname used to access your // Teleport Proxy Service. url = "https://example.teleport.sh/workload-identity" @@ -398,7 +398,7 @@ To proceed, you'll need to know the ARN of the role you created earlier. Add the following to your `~/.aws/config` file: ```ini -# You can replace "workload-id-demo" with a recognisable name that identifies +# You can replace "workload-id-demo" with a recognizable name that identifies # your use-case. [profile workload-id-demo] # Replace with the ARN of the role you created earlier.