継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

GitHub Actions の IAM ユーザーのクレデンシャルを IAM ロールに切り替えた時の経験をまとめる

タダです.

GitHub Actions にて OpenID Connect 経由して認証し,AWS へのアクセス可能になったというアナウンスが出て以降に,これまでは IAM ユーザーのアクセスキー/シークレットアクセスキーを設定して認証したのを IAM ロールに入れ替えました.既に試された記事を出されている方々の情報を参考に,入れ替えたときの経験をこの記事にまとめていきます.

github.blog

OIDC Provider と IAM ロールを作成する

GitHub Actions が使う OIDC Provider と IAM ロールを CloudFormation で作っていきます.S3 にアップロードする処理を過去記事で書いていたのでその権限を付与するものを作ってみます.

AWSTemplateFormatVersion: "2010-09-09"
Description: "For GHA"

Resources:
  Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: hoge-role
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: sts:AssumeRoleWithWebIdentity
            Principal:
              Federated: !Ref Oidc
            Condition:
              StringLike:
                token.actions.githubusercontent.com:sub:[リポジトリ名]:*

  Policy:
    Type: AWS::IAM::Policy
    Properties: 
      PolicyName: hoge-role-policy
      Roles:
       - !Ref Role
      PolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 's3:ListAllMyBuckets'
            Resource: 'arn:aws:s3:::*'
          - Effect: Allow
            Action:
              - 's3:ListBucket'
              - 's3:PutObject'
              - 's3:GetObject'
            Resource: 
              - !Sub 'arn:aws:s3:::hoge/*'
              - !Sub 'arn:aws:s3:::hoge'

  Oidc:
    Type: AWS::IAM::OIDCProvider
    Properties:
      Url: https://token.actions.githubusercontent.com
      ClientIdList: [sts.amazonaws.com]
      ThumbprintList: [a031c46782e6e6c662c2c87c76da9aa62ccabd8e]

作成が成功すると IAM ロールと IAM ポリシーのインラインのもの,信頼関係として次のものが出来上がります.また,OpenID Connect のプロバイダーもできあがります.

{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::[アカウント番号]:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:[リポジトリ名]:*"
        }
      }
    }
  ]
}

f:id:sadayoshi_tada:20211226225050p:plain

参考記事

tech.guitarrapc.com

上記とは別の権限をつけた IAM ロールを作りたい場合

上記の S3 アップロードとは別の権限を付与したいということがあると思います.ここでは AWS SAM による Lambda デプロイを GitHub Actions でやっていたので,このデプロイ で使う IAM ロールを追加で作ります.上記との違いは Federated: !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com' の定義を入れることで先ほど作った OIDC Provider を参照して信頼関係を作ることができます.

AWSTemplateFormatVersion: "2010-09-09"
Description: "Lambda Release IAM Role for GHA"

Resources:
  Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: hoge-lambda-role
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: sts:AssumeRoleWithWebIdentity
            Principal:
              Federated: !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com'
            Condition:
              StringLike:
                token.actions.githubusercontent.com:sub:
                  - "repo:hoge/hoge:*"

  Policy:
    Type: AWS::IAM::Policy
    Properties: 
      PolicyName: hoge-lambda-role-policy
      Roles:
       - !Ref Role
      PolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 'iam:CreateRole'
              - 'iam:AttachRolePolicy'
              - 'lambda:Get*'
              - 'iam:PassRole'
              - 'iam:DetachRolePolicy'
              - 'states:Get*'
              - 'lambda:DeleteFunction'
              - 'states:CreateStateMachine'
              - 'iam:Get*'
              - 'iam:List*'
              - 'iam:DeleteRole'
              - 'cloudformation:*'
              - 'lambda:*'
              - 'apigateway:*'
              - 'states:*'
              - 'iam:PutRolePolicy'
              - 'iam:DeleteRolePolicy'
              - 'iam:TagRole'
              - 'logs:*'
              - 'ssm:Describe*'
              - 'ssm:Get*'
              - 'ssm:List*'
              - 'events:PutRule'
              - 'events:Describe*'
              - 'events:List*'
              - 'events:DeleteRule'
              - 'events:RemoveTargets'
              - 'events:PutTargets'
              - 'sns:Publish'
              - 'ec2:Describe*'
              - 's3:CreateBucket'
              - 's3:PutBucketNotification'
              - 'secretsmanager:GetSecretValue'
            Resource: '*'
          - Effect: Allow
            Action:
              - 's3:ListAllMyBuckets'
            Resource: 'arn:aws:s3:::*'
          - Effect: Allow
            Action:
              - 's3:ListBucket'
              - 's3:GetBucketLocation'
            Resource: 
              - 'arn:aws:s3:::hoge'
          - Effect: Allow
            Action:
              - 's3:PutObject'
              - 's3:GetObject'
              - 's3:DeleteObject'
            Resource: 
              - 'arn:aws:s3:::hoge/*'

複数リポジトリを信頼関係に登録したい場合

IAM ロールを使って処理させたいリポジトリのコードが複数あるケースに対応するには次のような CloudFormation テンプレートを書けばよいです.Policy 以降は割愛していますが,Condition > StringLike で条件内に複数列挙することで対応させることができました.

AWSTemplateFormatVersion: "2010-09-09"
Description: "hoge Release IAM Role for GHA"

Resources:
  Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: hoge-deploy-role
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: sts:AssumeRoleWithWebIdentity
            Principal:
              Federated: !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com'
            Condition:
              StringLike:
                token.actions.githubusercontent.com:sub:
                  - "repo:hoge/hoge1:*"
                  - "repo:hoge/hoge2:*"
                  - "repo:hoge/hoge3:*"

  Policy:
    Type: AWS::IAM::Policy
~中略~

まとめ

GitHub Actions の OpenID Connect 経由認証向けの設定に切り替える上で,IAM 周りの設定を自分の経験からまとめました.切り替えたことで IAM ユーザーのクレデンシャルやユーザーを管理する負担が減ってセキュリティ向上にも寄与するためこのアップデートはありがたかったです.