Skip to content

Instantly share code, notes, and snippets.

@kev-bi
Created January 12, 2025 06:11
Show Gist options
  • Save kev-bi/16d24e42137d26a0e94903f847bac250 to your computer and use it in GitHub Desktop.
Save kev-bi/16d24e42137d26a0e94903f847bac250 to your computer and use it in GitHub Desktop.
GCP service account to AWS IAM role federation for terraform aws provider

GCP service account to AWS IAM role federation for aws terraform provider

On the off chance you have GCP workloads (i.g. GCE VMs or Cloud Run services) that need to apply terraform templates to create resources in an AWS account you can do so by fetching an identity token from the metadata server and using the token for workload identity federation.

Prereqs

This assumes your Cloud Run service or GCE VM already has a service account assigned.

Steps

  1. Get the OAuth 2 Client ID of your Google service account. In the Google Cloud console follow IAM & Admin > Service Accounts and copy the OAuth 2 Client ID value. Alternatively run the following gcloud cli command:
gcloud iam service-accounts describe <service-account> | grep "oauth2ClientId"
  1. Create an AWS IAM role with Web identity as the Trusted entity type and Google as the Identity provider. Edit the Trust Relationship section to look something like the following:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "accounts.google.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "accounts.google.com:aud": "<oauth2-client-id>"
        }
      }
    }
  ]
}
  1. Assign a policy to the IAM role, for instance if you want to manage manage EC2 instances through the service account your policy should look something like the following:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "ec2:AttachVolume",
        "ec2:CreateTags",
        "ec2:CreateVolume",
        "ec2:DeleteTags",
        "ec2:DeleteVolume",
        "ec2:DescribeImages",
        "ec2:DescribeInstanceAttribute",
        "ec2:DescribeInstances",
        "ec2:DescribeInstanceStatus",
        "ec2:DescribeInstanceTypes",
        "ec2:DescribeTags",
        "ec2:DescribeVolumeAttribute",
        "ec2:DescribeVolumes",
        "ec2:DescribeVolumeStatus",
        "ec2:DetachVolume",
        "ec2:ModifyInstanceAttribute",
        "ec2:MonitorInstances",
        "ec2:RebootInstances",
        "ec2:RunInstances",
        "ec2:StartInstances",
        "ec2:StopInstances",
        "ec2:TerminateInstances",
        "ec2:UnmonitorInstances",
      ],
      "Resource": "*"
    }
  ]
}
  1. Get the ARN of the IAM role. In the AWS console follow IAM > Role, click on the role you created and copy the ARN value. Alternatively run the following aws cli command:
aws iam get-role --role-name <iam-role> --query "Role.Arn"
  1. In terraform define an http resource with https://aws.amazon.com as the audience to get an identity token from the metadataserver:
data "http" "id_token_request" {
  url = "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://aws.amazon.com&format=full&licenses=FALSE"

  request_headers = {
    Metadata-Flavor = "Google"
  }
}
  1. In terraform define the aws resource with a assume_role_with_web_identity block using the ARN of the IAM role and the identity token fetched from the metadata server:
provider "aws" {
  assume_role_with_web_identity {
    role_arn = <iam-role-arn>
    session_name = "gcp-to-aws"
    web_identity_token = data.http.id_token_request.response_body
  }
  ...
}
  1. Define the rest of your terraform template + apply = profit

Validation

The http request only works for GCP resources that have a service account attached to it and can access the metadata server. To validate locally we need to use the gcloud auth print-identity-token command while impersonating the service account. (You will need the necessary GCP role to impersonate).

id_token=$(gcloud auth print-identity-token --audiences=https://aws.amazon.com --impersonate-service-account <service-account>  --include-email)

Once you have the token you can inspect it.

curl "https://oauth2.googleapis.com/tokeninfo?id_token=${id_token}"

You can also test assuming the IAM role in AWS with this token.

aws sts assume-role-with-web-identity \
  --role-arn <iam-role-arn> \
  --role-session-name "gcp-to-aws" \
  --web-identity-token ${id_token}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment