いきなりまとめ
- リポジトリやブランチごとに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なため、単純なブランチ名ではないことに注意
-
refs/heads/{BRANCH_NAME}
/refs/pull/{ISSUE_NUMBER}/merge
などになる - https://dev.classmethod.jp/articles/how-to-get-a-ref-branch-within-a-workflow-execution-in-github-actions/#toc-
-
設定例
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"
}
}
}
]
}
前提
- 基本的なOIDCを用いたGithub ActionsでのAWSへのアクセス方法は以下のページを参考にしてください
リポジトリやブランチごとに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 inrole-session-name
. The session will be tagged with the
following tags: (Refer to GitHub's documentation forGITHUB_
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でのタグ付与が早く実現してくれたらなと思います