GitHub ActionsでAWS SAMアプリケーションをデプロイするときの権限を考えてみた

GitHub ActionsでAWS SAMアプリケーションをデプロイするときの権限を考えてみた

GitHub Actionsを実行させてAWS SAMアプリケーションをデプロイする権限について考えてみました。OIDC用IAMロールとAWS CloudFormation用サービスロールの2つに分けて、それぞれで必要な権限を付与することになります。
Clock Icon2025.05.05

AWS SAMアプリケーションをGitHub Actionsでデプロイする場合のIAM権限を考えたい

おのやんです。

みなさん、AWS SAMアプリケーションをGitHub Actionsでデプロイする場合にIAM権限をどうするか考えたことはありませんか?私はあります。

このIAM権限まわりを設定する機会がありましたので、今回紹介していきます。

アーキテクチャ

GitHub ActionsからSAMアプリケーションをデプロイする場合、GitHub Actions上でsam deployを実行します。またSAMアプリケーションデプロイ時には、内部でAWS CloudFormation(以下、CFn)を使ってAWSリソースを作成します。

GitHub Actionsが操作できる範囲は、AWS上で作成するOIDCプロバイダをPrincipalとしたIAMロールで制御できます。またCFnがスタックを作成する場合、CFnのサービスロールを使用して作成可能なリソースを制御できます。

したがって、次の2つのIAMロールを使えば、権限を分散したアクセス制御ができると考えました。

  1. GitHub ActionsからSAMの操作を行うのに必要な権限を設定したIAMロール(図中だと「OIDC用IAMロール」)
  2. CFnからAWSのリソースを作成するのに必要な権限を設定したIAMロール(図中だと「CloudFormation用サービスロール」)

architecture

OIDC用IAMロール

OIDC用IAMロールは、GitHub ActionsからSAMの操作を行うのに必要な権限を設定したIAMロールです。GitHub Actionsではsam deployなどの操作を行うのみですので、基本はSAMデプロイ関係の権限をつけることになります。

今回のケースで必要な「SAMデプロイ関係の権限」は、公式ドキュメントで調べた限りですとAWSCloudFormationFullAccessAmazonS3FullAccessです。

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-permissions-cloudformation.html

たとえば、サンプルの Hello World アプリケーションをデプロイするには、次の AWS 管理ポリシーで十分です。

  • AWSCloudFormationFullAccess
  • IAMFullAccess
  • AWSLambda_FullAccess
  • AmazonAPIGatewayAdministrator
  • AmazonS3FullAccess
  • AmazonEC2ContainerRegistryFullAccess

ですので、OIDC用IAMロールをCFnテンプレートで記述するとこんな感じになります。ポイントとしては次の点が挙げられます。

  • マネージドポリシーとしてAWSCloudFormationFullAccessAmazonS3FullAccessをつけている
  • CfnサービスロールをPassRoleする際、PassRoleの対象にできるAWSサービスをCFnに限定
AWSTemplateFormatVersion: 2010-09-09
Description: IAM Role for OIDC

Resources:
  AWSTestGitHubActionsOICDRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: aws-test-github-actions-oicd-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Federated: arn:aws:iam::xxxxxxxxxxxx:oidc-provider/token.actions.githubusercontent.com
            Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringEquals:
                token.actions.githubusercontent.com:aud: sts.amazonaws.com
              StringLike:
                token.actions.githubusercontent.com:sub: repo:aws-test-organization/aws-test-github-repository:*
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AWSCloudFormationFullAccess
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      Policies:
        - PolicyName: aws-test-github-actions-oicd-policy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - iam:PassRole
                Resource: !GetAtt AWSTestCloudFormationServiceRole.Arn # 後述します
                Condition:
                  StringEqualsIfExists:
                    iam:PassedToService: cloudformation.amazonaws.com

CloudFormation用サービスロール

CloudFormation用サービスロールは、CFnからAWSのリソースを作成するのに必要な権限を設定したIAMロールです。sam deployの実行役としてCFnが動作しますので、ここには構築最小となるAWSサービスについて一通り許可していくことになります。

AWSTemplateFormatVersion: 2010-09-09
Description: IAM Role for AWS CloudFormation

Resources:
  AWSTestCloudFormationServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: aws-test-cfn-service-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
        - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
        - arn:aws:iam::aws:policy/AmazonSQSFullAccess
        - arn:aws:iam::aws:policy/AmazonSNSFullAccess
        - arn:aws:iam::aws:policy/AmazonECS_FullAccess

CFnテンプレート全体

冒頭で示したアーキテクチャのIAMロールをひとつのCFnテンプレートに記載すると、次のようになります。

AWSTemplateFormatVersion: 2010-09-09
Description: IAM Role for OIDC

#====================================#
# GitHub Actions OICD 用 IAM ロールと
# Cloud Formation 用 サービスロールの
# 合計2ロール
#====================================#

Resources:
  #====================================#
  # GitHub Actions OICD 用 IAM ロール
  #====================================#

  AWSTestGitHubActionsOICDRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: aws-test-github-actions-oicd-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Federated: arn:aws:iam::xxxxxxxxxxxx:oidc-provider/token.actions.githubusercontent.com
            Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringEquals:
                token.actions.githubusercontent.com:aud: sts.amazonaws.com
              StringLike:
                token.actions.githubusercontent.com:sub: repo:aws-test-organization/aws-test-github-repository:*
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AWSCloudFormationFullAccess
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      Policies:
        - PolicyName: aws-test-github-actions-oicd-policy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - iam:PassRole
                Resource: !GetAtt AWSTestCloudFormationServiceRole.Arn # 後述します
                Condition:
                  StringEqualsIfExists:
                    iam:PassedToService: cloudformation.amazonaws.com

  #====================================#
  # Cloud Formation 用 サービスロール
  #====================================#

  AWSTestCloudFormationServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: aws-test-cfn-service-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
        - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
        - arn:aws:iam::aws:policy/AmazonSQSFullAccess
        - arn:aws:iam::aws:policy/AmazonSNSFullAccess
        - arn:aws:iam::aws:policy/AmazonECS_FullAccess

「最小権限」というのにFullAccess付与は大丈夫なの?

AWSのベストプラクティスに従うと、IAMロールには最小権限を付与するべきです。しかし、CFn用サービスロールには構築対象のAWSサービスのFullAccess権限を付与しています。これを持って「最小権限」と言っていいのか、疑問に思うこともあるかと思います。

今回に関しては「デプロイ用のIAMロールなので、AdministratorAccessを付与するよりはいい」という落とし所です。デプロイ用ロールですので、どんなサービスもデプロイできるよう、ほとんどの場合、実質的なAdministratorAccessが求められることになります。しかし、AdministratorAccessをそのまま付与するのはさすがに危険です。

そこから、「せめて構築対象のAWSサービスに絞ろう」という流れで今回のFullAccess付与に落ち着いています。デプロイ対象のAWSサービスが新しく追加されるタイミングで、IAMロールにもそのサービスのFullAccess権限をつける、という運用になるでしょう。

OIDC用ロールでも、どのサービスに対してPassRoleできるかはConditionで指定しています。

Condition:
  StringEqualsIfExists:
          iam:PassedToService: cloudformation.amazonaws.com

この考えは、いわば「運用負荷とセキュリティのバランスを考えた案」です。セキュリティ要件をより重視する場合は、AWSサービスをデプロイする際に必要なアクションを細かく調べ上げ、本当の意味で最小権限にする選択肢もあります。このアプローチは、セキュリティ的に最も安全でしょう。構築対象のAWSサービス増加にともない、デプロイ時に必要なアクションが増える場合は、そのアクションを再度調べ、アタッチし、意図したデプロイ動作になるか細かく検証することになるかと思います。運用の負荷は増えますが、セキュリティ面ではより安全な権限設定になります。

権限の設定は難しい

CFnのサービスロールに付与する権限は悩みました。現状は運用不可と天秤にかけてこの構成をとっていますが、今後の運用方法は変わっていくかもしれません。

より適した運用案が出てきた場合は、またブログで共有したいと思います。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.