注目の記事

GitHub ActionsでAWSの永続的なクレデンシャルを渡すことなくIAM Roleが利用できるようになったようです

2021.09.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

アクセスキー、撲滅してますか?

ナカヤマです。

目黒方面より、以下のような福音が聞こえてきました。

元ネタはこちら。

「ほんとにぃ~?」と思ったので試してみました。

元ネタのブログにも記載されていますが、現時点(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がこの世に存在してよい理由の一つがなくなりました。 これらが必要なケースがまだまだ存在しますし、必要であれば「用法用量を守って正しく」使って頂く分には問題はありません。 しかし、永続的な認証情報はなんやかんやで事故の元なので、無くせるものは無くしていきたいものです。

公式発表が待たれます。