Workload identity enables you to assign distinct, fine-grained identities and authorization for each application in your cluster. Workload identity is the recommended way for applications running within GKE on AWS to access AWS and Google Cloud services. For more information, see Workload identity.
This topic explains how to create an OIDC provider, provision service accounts, and test a sample workload using workload identity. This page is for Identity and account admins, Operators, and Developers who want to create and manage policies related to user permissions. To learn more about common roles and example tasks that we reference in Google Cloud content, see Common GKE Enterprise user roles and tasks.
Create an AWS IAM OIDC provider for your cluster
To use workload identity with your cluster, you first create an AWS IAM OIDC provider that references your cluster. If you already have an IAM OIDC provider for your cluster, you can skip this section.
To create the provider, follow these steps:
Determine the OIDC issuer URI for your cluster:
gcloud container aws clusters describe CLUSTER_NAME \ --location=GOOGLE_CLOUD_LOCATION \ --format='value(workloadIdentityConfig.issuerUri)'
Replace the following:
CLUSTER_NAME
: the name of your clusterGOOGLE_CLOUD_LOCATION
: the name of the Google Cloud location from which this node pool will be managed, as defined in Google Cloud management regions
The output includes your cluster's OIDC issuer URI. Save this value for the following step.
Next, create an AWS IAM OIDC provider that references your cluster with the following command:
aws iam create-open-id-connect-provider \ --url ISSUER_URI \ --client-id-list sts.amazonaws.com \ --thumbprint-list 08745487e891c19e3078c1f2a07e452950ef36f6
Replace
ISSUER_URI
with your issuer URI from the previous step.The thumbprint of the Google Cloud service that serves the issuer URI is always
08745487e891c19e3078c1f2a07e452950ef36f6
.
Configure an AWS IAM role with an attached IAM policy
To configure an AWS IAM role and attach a policy to it, follow these steps:
Determine the issuer host by removing the
https://
prefix from the issuer URI. For example, if your URI ishttps://oidc-provider.com/v1/projects/pid/locations/us-west1/awsClusters/awscluster
, the host isoidc-provider.com/v1/projects/pid/locations/us-west1/awsClusters/awscluster
. Save this value. You'll need it later.Determine the provider's Amazon Resource Name (ARN) by running:
aws iam list-open-id-connect-providers --output=text \ --query 'OpenIDConnectProviderList[?ends_with(Arn, `ISSUER_HOST`) == `true`].Arn'
Replace
ISSUER_HOST
with the hostname from the issuer URI for the cluster.Next, create a trust policy to provide OIDC credentials to the Kubernetes service account. Create a file named
trust-policy.json
with the following contents:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "PROVIDER_ARN" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "ISSUER_HOST:sub": "system:serviceaccount:NAMESPACE:KSA_NAME" } } } ] }
Replace the following:
PROVIDER_ARN
: the ARN of the cluster's IAM OIDC providerISSUER_HOST
: the hostname from the issuer URI for the cluster.NAMESPACE
: the Kubernetes namespace where the application runsKSA_NAME
: the Kubernetes service account (KSA) to use for the application
Create an AWS IAM role:
aws iam create-role --role-name=AWS_ROLE_NAME \ --assume-role-policy-document file://trust-policy.json
Replace
AWS_ROLE_NAME
with the AWS IAM role name for the application.Attach an AWS IAM policy to the role:
aws iam attach-role-policy --role-name=AWS_ROLE_NAME \ --policy-arn=AWS_POLICY_ARN
Replace the following:
-
AWS_ROLE_NAME
: the AWS IAM role name for the application
For example, to create a role named
ec2-readonly
, with thearn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
policy, run the following command:aws iam attach-role-policy --role-name=ec2-readonly \ --policy-arn=arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
-
Deploy a sample application
To test workload identity, follow these steps to deploy a sample application:
Determine the role's ARN:
aws iam get-role --role-name=AWS_ROLE_NAME --query 'Role.Arn'
Replace
AWS_ROLE_NAME
.Create a manifest for a Kubernetes Namespace, KSA, and Pod. Copy the following manifest into a file named
workload-identity-test.yaml
:apiVersion: v1 kind: Namespace metadata: name: NAMESPACE --- apiVersion: v1 kind: ServiceAccount metadata: name: KSA_NAME namespace: NAMESPACE automountServiceAccountToken: false --- apiVersion: v1 kind: Pod metadata: name: aws-cli-example namespace: NAMESPACE spec: serviceAccount: KSA_NAME containers: - name: aws-cli image: amazon/aws-cli:latest command: - /bin/bash - -c - "set -eu -o pipefail; while true; do aws ec2 describe-availability-zones; sleep 5; done" env: - name: AWS_ROLE_ARN value: AWS_ROLE_ARN - name: AWS_WEB_IDENTITY_TOKEN_FILE value: /var/run/secrets/aws-iam-token/serviceaccount/token - name: AWS_REGION value: AWS_REGION volumeMounts: - mountPath: /var/run/secrets/aws-iam-token/serviceaccount name: aws-iam-token readOnly: true volumes: - name: aws-iam-token projected: defaultMode: 420 sources: - serviceAccountToken: audience: sts.amazonaws.com expirationSeconds: 86400 path: token
Replace the following:
NAMESPACE
KSA_NAME
AWS_ROLE_ARN
: the ARN of the AWS IAM role for the applicationAWS_REGION
: the AWS region of the cluster
Apply the manifest:
kubectl apply -f workload-identity-test.yaml
Wait several minutes for the Pod to start, and proceed to the following section.
Verify the sample application is working
To verify the sample application can access the EC2 API, look at the pod's logs:
kubectl logs -f aws-cli-example -n NAMESPACE
If the Pod can access the EC2 API, the output includes information on EC2 availability zones and looks similar to the following:
-------------------------------------------------
| DescribeAvailabilityZones |
+-----------------------------------------------+
|| AvailabilityZones ||
|+---------------------+-----------------------+|
|| GroupName | us-west-2 ||
|| NetworkBorderGroup | us-west-2 ||
|| OptInStatus | opt-in-not-required ||
|| RegionName | us-west-2 ||
|| State | available ||
|| ZoneId | usw2-az1 ||
|| ZoneName | us-west-2a ||
|+---------------------+-----------------------+|
|| AvailabilityZones ||
|+---------------------+-----------------------+|
|| GroupName | us-west-2 ||
|| NetworkBorderGroup | us-west-2 ||
|| OptInStatus | opt-in-not-required ||
|| RegionName | us-west-2 ||
|| State | available ||
|| ZoneId | usw2-az2 ||
|| ZoneName | us-west-2b ||
|+---------------------+-----------------------+|
|| AvailabilityZones ||
|+---------------------+-----------------------+|
|| GroupName | us-west-2 ||
|| NetworkBorderGroup | us-west-2 ||
|| OptInStatus | opt-in-not-required ||
|| RegionName | us-west-2 ||
|| State | available ||
|| ZoneId | usw2-az3 ||
|| ZoneName | us-west-2c ||
|+---------------------+-----------------------+|
|| AvailabilityZones ||
|+---------------------+-----------------------+|
|| GroupName | us-west-2 ||
|| NetworkBorderGroup | us-west-2 ||
|| OptInStatus | opt-in-not-required ||
|| RegionName | us-west-2 ||
|| State | available ||
|| ZoneId | usw2-az4 ||
|| ZoneName | us-west-2d ||
|+---------------------+-----------------------+|
Clean up
To remove this sample application, follow these steps:
Delete the sample application's manifest from your cluster:
kubectl delete -f workload-identity-test.yaml
Detach the AWS IAM policy from the role:
aws iam detach-role-policy --role-name AWS_ROLE_NAME \ --policy-arn arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
Replace
AWS_ROLE_NAME
with the AWS IAM role name for the application.Delete the AWS IAM role:
aws iam delete-role --role-name AWS_ROLE_NAME
Replace
AWS_ROLE_NAME
with the AWS IAM role name for the application.Delete the AWS IAM OIDC provider:
aws iam delete-open-id-connect-provider --open-id-connect-provider-arn PROVIDER_ARN
Replace
PROVIDER_ARN
with the ARN of the IAM OIDC provider for the cluster.
What's next
- Learn about Using workload identity with Google Cloud services.