Post

Use IAM roles to connect GitHub Actions to actions in AWS

Use Web Identity or OpenID Connect (OIDC) federated identity providers instead of creating AWS Identity and Access Management users in your AWS account. With an identity provider (IdP), you can manage your user identities outside of AWS and give these external user identities permissions to access AWS resources in your account.

Prerequisites

To follow along with this blog post, you should have the following prerequisites in place:

Create OIDC provider, IAM role and scope the trust policy

Connect to your AWS account and create the oidc.sh script.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/bin/bash

NAME="$1"
INFRA_REPO="$2"
FRONTEND_REPO="$3"
BACKEND_REPO="$4"
URL="$5"
ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account --no-cli-pager)

# Create OIDC id
OIDC_URL=$(curl $URL \
  | jq -r '.jwks_uri | split("/")[2]')

OIDC_ID=$(echo | openssl s_client -servername "$OIDC_URL" -showcerts -connect "$OIDC_URL":443 2> /dev/null \
  | sed -n -e '/BEGIN/h' -e '/BEGIN/,/END/H' -e '$x' -e '$p' | tail +2 \
  | openssl x509 -fingerprint -noout \
  | sed -e "s/.*=//" -e "s/://g" \
  | tr "ABCDEF" "abcdef")

# Create an OIDC provider in your account
aws iam create-open-id-connect-provider \
  --url "https://token.actions.githubusercontent.com" \
  --thumbprint-list "$OIDC_ID" \
  --client-id-list "sts.amazonaws.com"

# Create OIDC Role
REPOS=("$INFRA_REPO" "$FRONTEND_REPO" "$BACKEND_REPO")
OIDC_TRUST='{
    "Version": "2012-10-17",
    "Statement": ['

# Loop through the repositories to create the trust statements
for REPO in "${REPOS[@]}"; do
    OIDC_TRUST+="
        {
            \"Effect\": \"Allow\",
            \"Principal\": {
                \"Federated\": \"arn:aws:iam::$ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com\"
            },
            \"Action\": \"sts:AssumeRoleWithWebIdentity\",
            \"Condition\": {
                \"StringEquals\": {
                    \"token.actions.githubusercontent.com:sub\": \"repo:$REPO::ref:refs/heads/main\",
                    \"token.actions.githubusercontent.com:aud\": \"sts.amazonaws.com\"
                }
            }
        },"
done

# Remove the trailing comma and close the JSON
OIDC_TRUST=${OIDC_TRUST%,}
OIDC_TRUST+='
    ]
}'

aws iam create-role \
  --role-name "$NAME"-oidc \
  --description "OIDC role" \
  --assume-role-policy-document "$OIDC_TRUST" \
  --no-cli-pager

OIDC_POLICY=$(echo -n '{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Effect": "Allow",
          "Action": [
              "*"
          ],
          "Resource": "*"
      }
      ]
}')

aws iam put-role-policy \
  --role-name "$NAME"-oidc \
  --policy-name "$NAME"-oidc-policy \
  --policy-document "$OIDC_POLICY" \

Edit OIDC_POLICY: Assign a minimum level of permissions to the role.

oidc.sh script allows you to create the OIDC connection IAM Role for new the AWS environment.

Usage

1
2
3
4
5
6
7
NAME="Name"
INFRA_REPO="account/project-infra"
FRONTEND_REPO="account/project-frontend"
BACKEND_REPO="account/project-backend"
URL="https://token.actions.githubusercontent.com/.well-known/openid-configuration"

./oidc.sh "$NAME" "$INFRA_REPO" "$FRONTEND_REPO" "$BACKEND_REPO" "$URL"

Create a GitHub action to invoke the AWS CLI

  • Create a basic workflow file, such as main.yml, in the .github/workflows directory of your repository.

  • Paste the following example workflow into the file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# This is a basic workflow to help you get started with Actions
name:Connect to an AWS role from a GitHub repository

# Controls when the action will run. Invokes the workflow on push events but only for the main branch
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  AWS_REGION : <"us-east-1"> #Change to reflect your Region
  NAME: <name> #Change to reflect your IAM role’s name

# Permission can be added at job level or workflow level    
permissions:
      id-token: write   # This is required for requesting the JWT
      contents: read    # This is required for actions/checkout
jobs:
  AssumeRoleAndCallIdentity:
    runs-on: ubuntu-latest
    steps:
      - name: Git clone the repository
        uses: actions/checkout@v3
      - name: configure aws credentials
        uses: aws-actions/configure-aws-credentials@v1.7.0
        with:
          role-to-assume: <arn:aws:iam::111122223333:role/$-oidc>
          role-session-name: GitHub_to_AWS_via_FederatedOIDC
          aws-region: $
      # Hello from AWS: WhoAmI
      - name: Sts GetCallerIdentity
        run: |
          aws sts get-caller-identity

Audit the role usage: Query CloudTrail logs

The final step is to view the AWS CloudTrail logs in your account to audit the use of this role.

To view the event logs for the GitHub action:

  1. In the AWS Management Console, open CloudTrail and choose Event History.
  2. In the Lookup attributes list, choose Event source.
  3. In the search bar, enter sts.amazonaws.com.
  4. You should see the GetCallerIdentity and AssumeRoleWithWebIdentity events.

You can also view one event at a time.

Creating a Github OIDC Provider with CloudFormation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Description: OpenID Connect provider for GitHub Actions
Resources:
  GithubOidc:
    Type: AWS::IAM::OIDCProvider
    Properties:
      Url: https://token.actions.githubusercontent.com
      ThumbprintList:
        - ****
      ClientIdList:
        - sts.amazonaws.com
Outputs:
  GithubOidcProviderArn:
    Value: !Ref GithubOidc
    Export:
      Name: GithubOidcProviderArn
This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.