4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Github ActionsからAWSにアクセスする際にリポジトリやブランチで動的なポリシー制御(ABAC)をする方法

Last updated at Posted at 2025-01-27

いきなりまとめ

  • リポジトリやブランチごとにRoleやポリシーを定義したくない
  • ABACとはタグを用いたアクセス制御
  • configure-aws-credentialsを使用してGithub ActionsからOIDCでIAM Roleを使用する場合では、セッションにタグは付与されない
  • 原因はAssumeRoleWithWebIdentity のAPIではタグ付与がされないことにある
  • 一方でAssumeRole APIではタグ付与をサポートしているため、AssumeRoleWithWebIdentityで取得したIAM Role認証から更に、role-chainingで別のRoleへAssumeRoleすることでタグ付与が可能
  • タグ付与の際には sts:TagSession の権限付与が必要なため注意
  • Branchの値は実際にはGITHUB_REFなため、単純なブランチ名ではないことに注意

設定例

GitHubアクション例

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        aws-region: us-east-2
        role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
        role-session-name: MySessionName
    - name: Configure other AWS Credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        aws-region: us-east-2
        role-to-assume: arn:aws:iam::987654321000:role/my-second-role
        role-session-name: MySessionName
        role-chaining: true

OIDC Roleに設定するPolicy(GithubOIDCRole)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ],
            "Resource": "arn:aws:iam::XXXXXXXXXXXX:role/GithubABACRole"
        }
    ]
}

実際にアクションを行うRoleに設定するPolicy(GithubABACRole)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXXXX:role/GithubOIDCRole"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ],
            "Condition": {}
        }
    ]
}

ABACを用いたPolicy

{
	"Version": "2012-10-17",
	"Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::abac-test-bucket/${aws:PrincipalTag/Branch}/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::only-main-branch/*"
            ]
            "Condition": {
				"StringEquals": {
					"aws:PrincipalTag/Branch": "main"
				}
			}
        }
    ]
}

前提

リポジトリやブランチごとにRoleやポリシーを定義したくない

OIDC便利ですよね。IAM Userを使っていたころには戻れません

信頼ポリシーで指定のリポジトリ・ブランチのみで使用可能なRoleを作成することも可能です

一方で、mainブランチとトピックブランチでS3にファイルをアップロード/削除する処理があるとして、それを1つのIAM Roleで実施する場合、トピックブランチの変更によってmainブランチでアップロードされたS3ファイルの変更ができてしまいます。

なので、前述の信頼ポリシーを設定するのですが、これをしていくと制御したいブランチごとにRoleが必要になります。
これが複数リポジトリあれば、さらに増えていきます

なので、前述の制御をIAM Policyで使用できたらと思うのですが、それは使用できません

ABACとはタグを用いたアクセス制御

こういった用途と言えば、ABACです。
ResourceやCondition内でタグの値を使用できるので、それを使って制御しようというものです

主にaws:PrincipalTagを使って制御をしていきます

ABACの詳細については以下の記事を参考にしてください

Github Actionsでタグ付与自体はサポートしているようだが。。。?

configure-aws-credentialsを見ると、どうやらセッションタグを付与しているようです

The default session name is "GitHubActions", and you can modify it by specifying
the desired name in role-session-name. The session will be tagged with the
following tags: (Refer to GitHub's documentation for GITHUB_ environment
variable definitions
)

Key Value
GitHub "Actions"
Repository GITHUB_REPOSITORY
Workflow GITHUB_WORKFLOW
Action GITHUB_ACTION
Actor GITHUB_ACTOR
Branch GITHUB_REF
Commit GITHUB_SHA

ドキュメントでもAssumeRole時にタグ付与が可能で、それを使用した制御が書かれています

しかし、以下のような不穏な記述があります

The action will use session tagging by default during role assumption, unless you follow our recommendation and are assuming a role with a WebIdentity.
For WebIdentity role assumption, the session tags have to be included in the encoded WebIdentity token.
This means that tags can only be supplied by the OIDC provider, and they cannot set during the AssumeRoleWithWebIdentity API call within the Action. See #419 for more information.

要するにAssumeRoleWithWebIdentityのAPIではタグ付与はされないということのようです。

そしてOIDCでAWSにアクセスする際に使用するAPIはAssumeRoleWithWebIdentityです。

実際に試してみましたが、タグ付与はされず、当然ながらaws:PrincipalTagも機能しません

AssumeRole APIを呼び出せば使用可能

AssumeRoleWithWebIdentityではできないだけで、AssumeRoleであればできそうです。

なので、実際に試したところタグ付与の確認とそれを使用したaws:PrincipalTagによる制御が可能でした

いきなりworkflowからAssumeRoleはできないので、まずはAssumeRoleWithWebIdentityで権限を取得し、そのIAMを使用してさらにAssumeRoleをします。

いわゆるロールの連鎖を使用したアプローチになります

configure-aws-credentialsでもrole-chaining: trueを設定することで、ロール連鎖が可能です

GitHubアクション例

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        aws-region: us-east-2
        role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
        role-session-name: MySessionName
    - name: Configure other AWS Credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        aws-region: us-east-2
        role-to-assume: arn:aws:iam::987654321000:role/my-second-role
        role-session-name: MySessionName
        role-chaining: true

タグ付与の際には sts:TagSession の権限付与が必要になります。AssumeRoleを許可だけではできないため注意してください。

OIDC用のRoleにはポリシーを作成してアクションを許可。実際にアクションを行うRole側には信頼ポリシーにて許可を行ってください

OIDC Roleに設定するPolicy(GithubOIDCRole)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ],
            "Resource": "arn:aws:iam::XXXXXXXXXXXX:role/GithubABACRole"
        }
    ]
}

実際にアクションを行うRoleに設定するPolicy(GithubABACRole)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXXXX:role/GithubOIDCRole"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ],
            "Condition": {}
        }
    ]
}

実際に付与されるタグの例(Cloudtrailで確認)

    "requestParameters": {
        "roleArn": "arn:aws:iam::XXXXXXXXXXXX:role/GithubABACRole",
        "roleSessionName": "abac-test",
        "durationSeconds": 3600,
        "tags": [
            {
                "key": "GitHub",
                "value": "Actions"
            },
            {
                "key": "Repository",
                "value": "abac-test-repo"
            },
            {
                "key": "Workflow",
                "value": "Test Shipment"
            },
            {
                "key": "Action",
                "value": "__aws-actions_configure-aws-credentials_2"
            },
            {
                "key": "Actor",
                "value": "willco21"
            },
            {
                "key": "Commit",
                "value": "43326e48da8207167a3f75bda09xxxxxxxxxxxx"
            },
            {
                "key": "Branch",
                "value": "refs/pull/51/merge"
            }
        ]

実際の活用例

再掲ですが、付与されるタグは以下になります。

また、 Branchの値は実際にはGITHUB_REFなため、単純なブランチ名ではないことに注意が必要です
具体的には以下の記事を参考にしてください

Key Value
GitHub "Actions"
Repository GITHUB_REPOSITORY
Workflow GITHUB_WORKFLOW
Action GITHUB_ACTION
Actor GITHUB_ACTOR
Branch GITHUB_REF
Commit GITHUB_SHA

そのため基本的にはRepositoryとBranchを用いた以下のようなポリシー設定が考えられます

S3へのアップロード制御

一番よくある利用例だと思います。

Resourceのパスに /${aws:PrincipalTag/Branch}を使用することでそのブランチ用のPathだけにアクセスできるように設定できます

また、mainブランチのみ別のアクションを許可した場合などでも、Conditionを使用することで容易に制御が可能です

{
	"Version": "2012-10-17",
	"Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::abac-test-bucket/${aws:PrincipalTag/Branch}/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::only-main-branch/*"
            ]
            "Condition": {
				"StringEquals": {
					"aws:PrincipalTag/Branch": "main"
				}
			}
        }
    ]
}

リポジトリごとにバケットを分けているならば、以下のようなポリシーを1つ設定することで、1つのRoleで多くのリポジトリのworkflowでの操作を許可することも可能です(かなり汎用的なポリシーになるのでオススメはしません)

{
	"Version": "2012-10-17",
	"Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::${aws:PrincipalTag/Repository}/${aws:PrincipalTag/Branch}/*"
            ]
        }
    ]
}

aws:ResourceTagを用いたリソース操作の制御

aws:ResourceTagを用いることで、特定のタグの値を確認して該当するリソースのみにアクションを制御できます

workflowでEC2の操作をする場合において、自身のBranchのタグが追加リソースのみに制限することで、意図しないEC2への操作を防ぐことが可能です

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "arn:aws:ec2:*:*:instance/*",
            "Condition": {
                "StringEquals": {"aws:ResourceTag/Branch": "${aws:ResourceTag/Branch}"}
            }
        },
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeInstances",
            "Resource": "*"
        }
    ]
}

まとめ

Github ActionsからAWSにアクセスする際にもABACを用いた制御が可能なことがわかりました

設定されるタグの関係上、事前にアクションを実行するリソースの設計が必要にはなりますが、うまく活用することで大量のIAM RoleやPolicy管理からの解放ができると思います

また、シンプルにAssumeRoleWithWebIdentityでのタグ付与が早く実現してくれたらなと思います

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?