AWSのAppRunnerというサービスで、アクセス制限されたプライベートなECRリポジトリからイメージ(リソース)を取得する際に、うまくいかず苦戦しました。
今回はECRを例として、ユーザー・ロール・サービス単位でアクセスを制限する方法をまとめたいと思います。(S3のバケットポリシーなどにも応用できる内容となっています。)
ターゲット
- リソースベースのポリシーについて学びたい
- リソース(ECR,S3など)へのアクセス制限をユーザーやサービス、ロール単位で設定したい
基本的な設定方法
まずは、ECRにアクセス制限を設定する時の基本的なポリシーを確認します。
ポリシーの要素の Deny + NotPrincipal または Allow + Principal で条件を指定することができます。
ユーザーを制限する
ルートユーザー、User1、User2の3つ以外を拒否するポリシーです。(root以外の各ユーザーへの許可は別途必要となります。)
AWSでARNを指定することで、ユーザーのアクセス制限を設定できます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyExample1",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::<アカウントID>:user/User1",
"arn:aws:iam::<アカウントID>:user/User2",
"arn:aws:iam::<アカウントID>:user/root"
]
},
"Action": "ecr:*"
}
]
}
サービスを制限する
以下の例はCodeBuildを許可するポリシーです。
Serviceでサービスの識別子を指定することで、サービスを制限します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowService",
"Effect": "Allow",
"Principal": {
"Service": [
"codebuild.amazonaws.com"
]
},
"Action": "ecr:*"
}
]
}
特殊な設定が必要なパターン
ロールを制限する (セッションIDが固定できる場合)
Role1以外を拒否するポリシーです。
ユーザーと同じく、AWSでARNを指定することでロールのアクセス制限を設定できます。
ロールのARNとロールを委任した時のセッションIDを含めたARNの両方を設定する必要があることに気を付けてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyExample2",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::<アカウントID>:role/Role1",
"arn:aws:sts::<アカウントID>:assumed-role/Role1/<セッションID>",
"arn:aws:iam::<アカウントID>:user/root"
]
},
"Action": "ecr:*"
}
]
}
ロールを制限する (セッションIDが変わる場合)
AWS CLIなどからユーザーにロールを委任する場合などは、セッションIDを指定することが出来ますので、ポリシーで予め定義できます。しかし、サービスにロールを委任するようなケースでは、セッション毎にIDが変わる場合があります。
今までの例で使用していたPrincipalやNotPrincipalではワイルドカード(?や*)は使用できません。
代わりに、ワイルドカードが使用できるConditionの文字列条件演算子を用いてロールID1を指定します。
以下の例は、ロールIDがAROAxxxxxxxxxxxxxxxxx
であるロールを委任したセッション以外を拒否するポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyExample3",
"Effect": "Deny",
"Principal": "*",
"Action": "ecr:*",
"Condition": {
"StringNotLike": {
"aws:userid": "AROAxxxxxxxxxxxxxxxxx:*"
}
}
}
]
}
実用例
明示的な拒否(Deny)を用いた例
Denyのステートメントで、NotPrincipalとConditionの両方を用いてユーザーとロールを制限します。
以下の例は、User1
,User2
,AROAxxxxxxxxxxxxxxxxN:*
,AROAxxxxxxxxxxxxxxxx5:*
のいずれにも一致しない場合は拒否するポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyExample4",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::<アカウントID>:user/User1",
"arn:aws:iam::<アカウントID>:user/User2",
"arn:aws:iam::<アカウントID>:user/root"
]
},
"Action": "ecr:*",
"Condition": {
"ForAnyValue:StringNotLike": {
"aws:userid": [
"AROAxxxxxxxxxxxxxxxxN:*",
"AROAxxxxxxxxxxxxxxxx5:*"
]
}
}
}
]
}
複雑なので、少し詳しく説明します。
同一のステートメント内において、異なる要素の条件はANDで評価され、同一要素内はORで評価されます。
まずはNotPrincipalについてです。
NotPrincipalは否定であり、User1とUser2が同一要素(AWS)に指定されているので、
NOT (User1
OR User2
)
となります。
次にConditionについてです。
Condition内のForAnyValue:StringNotLikeは否定であり、二つの文字列が同一要素(aws:userid)に指定されているので、
NOT (AROAxxxxxxxxxxxxxxxxN:*
OR AROAxxxxxxxxxxxxxxxx5:*
)
となります。
二つの条件は、それぞれ異なる要素に指定されているためANDとなるため、最終的な条件式は以下です。
{NOT (User1
OR User2
)} AND {NOT (AROAxxxxxxxxxxxxxxxxN:*
OR AROAxxxxxxxxxxxxxxxx5:*
)}
= NOT (User1
OR User2
OR AROAxxxxxxxxxxxxxxxxN:*
OR AROAxxxxxxxxxxxxxxxx5:*
)
この条件Trueの場合に拒否(Deny)となるため、User1
,User2
,AROAxxxxxxxxxxxxxxxxN:*
,AROAxxxxxxxxxxxxxxxx5:*
のいずれにも一致しない場合は拒否するポリシーとなります。
明示的な許可(Allow)を用いた例
Allowのステートメントを2つ用いてユーザーとロールを制限します。
以下の例は、User1
,User2
,AROAxxxxxxxxxxxxxxxxN:*
,AROAxxxxxxxxxxxxxxxx5:*
を許可するポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowUsers",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<アカウントID>:user/User1",
"arn:aws:iam::<アカウントID>:user/User2"
]
},
"Action": "ecr:*"
},
{
"Sid": "AllowRoles",
"Effect": "Allow",
"Principal": "*",
"Action": "ecr:*",
"Condition": {
"ForAnyValue:StringLike": {
"aws:userid": [
"AROAxxxxxxxxxxxxxxxxN:*",
"AROAxxxxxxxxxxxxxxxx5:*"
]
}
}
}
]
}
上記では、ユーザーとロールを別のAllowステートメントとして定義しています。
理由は、同一ステートメントに異なる要素で条件を指定するとANDで評価されてしまい、意図しない条件となってしまうためです。
異なるステートメントの条件はORで判定されるため、
User1
,User2
,AROAxxxxxxxxxxxxxxxxN:*
,AROAxxxxxxxxxxxxxxxx5:*
のいずれかを許可するポリシーとなっています。
さいごに
AppRunnerに設定したサービスロールをECR側で許可する方法でつまずいた経験から、ポリシーについて調べたことをまとめてみました。
今回例としてあげたポリシーはECRでしたが、S3のバケットポリシーなどにも応用が可能です。
サービスやロールに対する設定はAppRunnerだけでなく、CloudWatch,CodeBuild,CloudTrailなどを使用する場合にも参考にして頂ければ幸いです。
参考サイト
AWS CLI Command Reference - get-user
AWS CLI Command Reference - get-role
AWS公式ドキュメント - IAM 識別子
AWS公式ドキュメント - IAM JSON ポリシーの要素: 条件演算子
AWS公式ドキュメント - IAM JSON ポリシーの要素: Condition
AWS公式ドキュメント - ロールの用語と概念
AWS CLI を使用して IAM ロールを引き受ける方法を教えてください。
[アップデート] サービスプリンシパルを含む IAM ポリシーの管理を簡素化する AWS グローバル条件キーが追加されました
特定の IAM ロールのみアクセスできる S3 バケットを実装する際に検討したあれこれ
非VPC LambdaでIP制限されたS3バケットにアクセスしたい
[AWS] S3バケットポリシーで、特定のIAMロールだけがバケットにアクセス出来るようにする。