Skip to main content

Methods for getting AWS account IDs

Grab the Basic ~/.aws/config for AdministratorAccess from 1password.

In the management/root account

aws iam create-open-id-connect-provider \
  --profile unkey-root-admin \
  --url https://token.actions.githubusercontent.com \
  --client-id-list sts.amazonaws.com \
  --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1
To get the ARN for the OIDC provider… (you don’t need to do this as it’s embedded in the policy below, but it’s here for reference)
aws iam list-open-id-connect-providers --profile unkey-root-admin --output text --no-cli-pager
Create a github-actions-trust-policy.json for Github Actions role in the root/management account for the unkeyed/infra:* repo for all (*) branches. This already has the ARN from the above command in place.
cat > github-actions-trust-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "$(aws iam list-open-id-connect-providers --profile unkey-root-admin --output text --no-cli-pager --query "OpenIDConnectProviderList[0].Arn")"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
        },
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:unkeyed/infra:*"
        }
      }
    }
  ]
}
EOF
Create the role with the trust policy
aws iam create-role \
  --profile unkey-root-admin \
  --role-name GitHubActionsOIDCRole \
  --assume-role-policy-document file://github-actions-trust-policy.json
Create cross-account-policy.json. Note: This renders like it didn’t interpolate the *_ACCOUNT vars, but less cross-account-policy.json will show it correctly.
SANDBOX_ACCOUNT=$(aws sts get-caller-identity --profile unkey-sandbox-admin --query Account --output text)
CANARY_ACCOUNT=$(aws sts get-caller-identity --profile unkey-canary-admin --query Account --output text)
PRODUCTION001_ACCOUNT=$(aws sts get-caller-identity --profile unkey-production001-admin --query Account --output text)
cat > cross-account-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": [
        "arn:aws:iam::${SANDBOX_ACCOUNT}:role/UnkeyPulumiAWSExecutor",
        "arn:aws:iam::${CANARY_ACCOUNT}:role/UnkeyPulumiAWSExecutor",
        "arn:aws:iam::${PRODUCTION001_ACCOUNT}:role/UnkeyPulumiAWSExecutor"
      ]
    },
    {
      "Effect": "Allow",
      "Action": ["ec2:DescribeAvailabilityZones", "ec2:DescribeRegions"],
      "Resource": "*"
    }
  ]
}
EOF
Create the policy in the root/management account… grab the ARN once it creates, you’ll need it later.
aws iam create-policy \
  --profile unkey-root-admin \
  --policy-name CrossAccountAssumeRole \
  --policy-document file://cross-account-policy.json
Attach the policy to the Github Actions role thingy
aws iam attach-role-policy \
  --profile unkey-root-admin \
  --role-name GitHubActionsOIDCRole \
  --policy-arn "arn:aws:iam::333769656712:policy/CrossAccountAssumeRole"

The Pulumi Executor role

This one is a bit of a doozy… You’ll have to do this for EACH account… I’ve tried to streamline/automate most of it, but be mindful and RTFM closely! First, get the SSO role ID for AdministratorAccess for each account in {sandbox,canary,production001}
aws iam list-roles \
  --profile unkey-sandbox-admin \
  --query "Roles[?contains(RoleName, 'AWSReservedSSO_AdministratorAccess')].{Arn:Arn}" --output text
The one we want is for the AdministratorAccess role.. this is what sandbox’s role ARN looks like…
arn:aws:iam::343218208612:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_AdministratorAccess_c23a3ed1d84d0d63
Now, that needs to added to the pulumi-executor-<ACCOUNT>-trust-policy.json we’ll create… this policy says that anyone with the AWSReservedSSO_AdministratorAccess_* role from <ACCOUNT_NAME> and the GithubActionsOIDCRole from the root/management account can assume this role.
# I'm sorry for this bash...
for account in sandbox canary production001; do
ROLE_ID=$(aws iam list-roles \
  --profile "unkey-${account}-admin" \
  --query "Roles[?contains(RoleName, 'AWSReservedSSO_AdministratorAccess')].{Arn:Arn}" --output text)
cat > "pulumi-executor-${account}-trust-policy.json" <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "${ROLE_ID}",
          "arn:aws:iam::333769656712:role/GitHubActionsOIDCRole"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
unset ROLE_ID;
done
Add the role with the policy to each account…
for account in sandbox canary production001; do
aws iam create-role \
  --profile "unkey-${account}-admin" \
  --no-cli-pager \
  --role-name UnkeyPulumiAWSExecutor \
  --assume-role-policy-document file://pulumi-executor-${account}-trust-policy.json
done
Create the unkey-pulumi-policy.json. (Just once!)
cat > unkey-pulumi-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "cloudformation:*",
        "cloudwatch:*",
        "ec2:*",
        "ecr:*",
        "ecs:*",
        "elasticache:*",
        "elasticloadbalancing:*",
        "globalaccelerator:*",
        "iam:AttachRolePolicy",
        "iam:CreateRole",
        "iam:DeleteRole",
        "iam:DeleteRolePolicy",
        "iam:DetachRolePolicy",
        "iam:GetRole",
        "iam:GetRolePolicy",
        "iam:PassRole",
        "iam:PutRolePolicy",
        "iam:ListRolePolicies",
        "iam:ListAttachedRolePolicies",
        "iam:ListInstanceProfilesForRole",
        "kms:*",
        "logs:*",
        "ssm:*"
      ],
      "Resource": "*"
    }
  ]
}
EOF
Now add the policy to each account and attach it to the role…
for account in sandbox canary production001; do
POLICY_ARN=$(aws iam create-policy \
  --profile "unkey-${account}-admin" \
  --policy-name UnkeyPulumiPolicy \
  --policy-document file://unkey-pulumi-policy.json \
  --query 'Policy.Arn' --output text)

# Attach the policy to the role
aws iam attach-role-policy \
  --profile "unkey-${account}-admin" \
  --no-cli-pager \
  --role-name UnkeyPulumiAWSExecutor \
  --policy-arn "${POLICY_ARN}";
done