
GitHub ActionsでAWSの永続的なクレデンシャルを渡すことなくIAM Roleが利用できるようになったようです
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
アクセスキー、撲滅してますか?
ナカヤマです。
目黒方面より、以下のような福音が聞こえてきました。
何がどのくらい最高かと言いますと!
GitHub Actions に AWS クレデンシャルを直接渡さずに IAM ロールが使えるようになることがまず最高で!
クレデンシャル直渡しを回避するためだけの Self-hosted runner が必要なくなるところも最高です!!✨✨✨ https://t.co/IUQmfzkIB0
— Tori Hara (@toricls) September 15, 2021
元ネタはこちら。
Ok I blogged about it. That's how excited I am.
1. Deploy this CFN template
2. Write this GHA workflow
3. Never worry about IAM users again
https://t.co/KJrr2Jw4bE pic.twitter.com/9IcocgurxP— Aidan W Steele (@__steele) September 15, 2021
「ほんとにぃ~?」と思ったので試してみました。
元ネタのブログにも記載されていますが、現時点(2021年9月16日)で公式なアナウンスやドキュメントが存在しないようです。検証などは自己責任でお願いします。
やってみた
とりあえず、元ネタのブログに沿ってやってみることにします。
- リポジトリの作成
- IAM RoleおよびIdentity Providerの作成
- Workflowの作成
リポジトリの作成
てきとうにリポジトリを作成します。
IAM RoleおよびIdentity Providerの作成
GitHub Actionsで利用するIAM Roleおよび認証連携のためのIdentity Providerを作成します。 このIAM Roleでは、特定のリポジトリのWorkflowでのみ利用できるように制限されています。
なお、IAM Roleに付与する権限は元ネタのブログで付与しているものより大幅に削減しました。
AWSTemplateFormatVersion: "2010-09-09"
Description: "IAM Role for GHA"
Parameters:
  RepoName:
    Type: String
    Default: nakayamanobuhiro/test-20210916-oidc-gha
Resources:
  Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ExampleGithubRole
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: sts:AssumeRoleWithWebIdentity
            Principal:
              Federated: !Ref GithubOidc
            Condition:
              StringLike:
                vstoken.actions.githubusercontent.com:sub: !Sub repo:${RepoName}:*
  Policy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: test-gha
      Roles:
       - !Ref Role
      PolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 'sts:GetCallerIdentity'
            Resource: '*'
  GithubOidc:
    Type: AWS::IAM::OIDCProvider
    Properties:
      Url: https://vstoken.actions.githubusercontent.com
      ClientIdList: [sigstore]
      ThumbprintList: [a031c46782e6e6c662c2c87c76da9aa62ccabd8e]
Outputs:
  Role:
    Value: !GetAtt Role.Arn
Workflowの作成
リポジトリにWorkflowを作成します。
Workflowファイルは以下の通りです。
環境変数 AWS_ROLE_ARN には、先ほど作成したIAM RoleのARNを設定します。
name: Example
on:
  push:
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - run: sleep 5 # there's still a race condition for now
      - name: Configure AWS
        run: |
          export AWS_ROLE_ARN=arn:aws:iam::xxxxxxxxxxxx:role/ExampleGithubRole
          export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds
          export AWS_DEFAULT_REGION=us-east-1
          echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV
          echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV
          echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV
          curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sigstore" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE
      - run: aws sts get-caller-identity
しばらく待ちますと。。。
動いた。まじか。
その他
その他、気になった点を確認します。
(随時追記するかも)
CloudTrail
以下のようなイベントレコードが記録されていました。
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROAXXXXXXXXXXXXXXXXX:botocore-session-1631723176",
        "arn": "arn:aws:sts::xxxxxxxxxxxx:assumed-role/ExampleGithubRole/botocore-session-1631723176",
        "accountId": "xxxxxxxxxxxx",
        "accessKeyId": "ASIAXXXXXXXXXXXXXXXX",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROAXXXXXXXXXXXXXXXXX",
                "arn": "arn:aws:iam::xxxxxxxxxxxx:role/ExampleGithubRole",
                "accountId": "xxxxxxxxxxxx",
                "userName": "ExampleGithubRole"
            },
            "webIdFederationData": {
                "federatedProvider": "arn:aws:iam::xxxxxxxxxxxx:oidc-provider/vstoken.actions.githubusercontent.com",
                "attributes": {}
            },
            "attributes": {
                "mfaAuthenticated": "false",
                "creationDate": "2021-09-15T16:26:17Z"
            }
        }
    },
    "eventTime": "2021-09-15T16:26:17Z",
    "eventSource": "sts.amazonaws.com",
    "eventName": "GetCallerIdentity",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "20.97.4.66",
    "userAgent": "aws-cli/2.2.35 Python/3.8.8 Linux/5.8.0-1040-azure exe/x86_64.ubuntu.20 prompt/off command/sts.get-caller-identity",
    "requestParameters": null,
    "responseElements": {
        "userId": "AROAXXXXXXXXXXXXXXXXX:botocore-session-1631723176",
        "account": "xxxxxxxxxxxx",
        "arn": "arn:aws:sts::xxxxxxxxxxxx:assumed-role/ExampleGithubRole/botocore-session-1631723176"
    },
    "requestID": "4c8435f1-85c9-4fa2-81f0-60629461e576",
    "eventID": "acc48e40-738d-4f7c-a656-ac51e3738526",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "eventCategory": "Management",
    "recipientAccountId": "xxxxxxxxxxxx",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "sts.us-east-1.amazonaws.com"
    }
}
まとめ
IAM User / Access Keyがこの世に存在してよい理由の一つがなくなりました。 これらが必要なケースがまだまだ存在しますし、必要であれば「用法用量を守って正しく」使って頂く分には問題はありません。 しかし、永続的な認証情報はなんやかんやで事故の元なので、無くせるものは無くしていきたいものです。
公式発表が待たれます。















