【AWS】Resource Control Policies (RCPs) が追加されました
はじめに
2024/11/14 に Orgnizations のポリシーとして新たに Resource Control Policies (RCPs) が追加されました。すべてのリージョンで利用可能です。
Organizations 内のリソースに予防的コントロールを強制するものになります。例えば、「Organizations のすべての AWS アカウントにおいて、組織外のプリンシパルが S3 バケットにアクセスすることを禁止する」という要件を簡単に満たすことができるようになります。
リリース時点での対象リソースは Amazon S3, STS, KMS, SQS, Secrest Manager です。
前提条件
- Organizations のすべての機能が有効化されていること(一括請求のみは NG)
注意点
- Organizations の管理アカウントには適用されない
- 委任管理者アカウントも適用されないと記載があるが、すべての委任管理者アカウントが対象なのかは不明。(意図せず RCPs が適用されないケースが発生しそう)
- その他の適用対象外は以下を参照
- AWS が推奨する RCPs の適用方法は、Root にすぐに適用するのではなく、アカウントレベル→ OU レベル(下位から)→ 適用したいレベル
- root もしくは OU 単位にアタッチできる RCPs は SCP 同様 5 まで
- 5120 文字までなので必要に応じてスペースを省く
- Resource control policies: 5120 characters
-
NotPrincipal
とNotAction
は利用不可 - (注意点ではないが)
*
と?
が Action 要素のどこでも利用可能- SCP では
ec2:Describe*
のように最後に利用するのは可能だったが、ec2:*Describe
のような指定は不可能だった
- SCP では
サンプルポリシー
以下ドキュメントにサンプルポリシーの記載があります。
ドキュメントにも記載がありますが、AWS が推奨するもしくはベストプラクティスの設定という訳ではないので注意してください。
- AWS サービス間の混乱した代理問題の予防
リクエストのコンテキストに aws:SourceAccount
が存在し、AWS サービスからの呼び出し時に "aws:SourceOrgID
が my-org-id
ではない場合に s3, sqs, secrestmanager の全リソースに対するアクションを拒否する。
例えば、CloudTrail の証跡を作成する際に S3 バケットのバケットポリシーで Principal cloudtrail.amazonaws.com
を許可すると思います。しかし、AWS アカウントで利用する CloudTrail はすべて上記の Principal になるため、S3 バケットの ARN が分かってしまうと全然関係のない AWS アカウントから S3 バケットに対して CloudTrail ログを出力することができてしまいます。それを防ぐために SourceAccount や SourceOrgID を利用して自分が管理しているアカウントからのみ出力できるようポリシーを設けることが必要になります。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RCPEnforceConfusedDeputyProtection",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:*",
"sqs:*",
"secretsmanager:*"
],
"Resource": "*",
"Condition": {
"StringNotEqualsIfExists": {
"aws:SourceOrgID": "my-org-id"
},
"Bool": {
"aws:PrincipalIsAWSService": "true"
},
"Null": {
"aws:SourceAccount": "false"
}
}
}
]
}
- HTTPS 接続の強制
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnforceSecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": [
"sts:*",
"s3:*",
"sqs:*",
"secretsmanager:*",
"kms:*"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:SecureTransport": "false"
}
}
}
]
}
- TLS バージョンと KMS 暗号化の強制
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnforceS3TlsVersion",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "*",
"Condition:": {
"NumericLessThan": {
"s3:TlsVersion": [
"1.2"
]
}
}
},
{
"Sid": "EnforceKMSEncryption",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "*",
"Condition": {
"Null": {
"s3:x-amz-server-side-encryption-aws-kms-key-id": "true"
}
}
}
]
}
また、Control Tower のコントロールにも 9 種類追加されています。
(実装 = Resource control policy (RCP) で絞り込み)
試してみる
企業の IP アドレスのみ通過させる制御をすべてのバケットに入れる想定で、CloudShell の IP アドレスからのみアクセスを許可する RCPs を適用して挙動を確認してみます。
rcp-test-20241115 というバケットを 33xxxxxxxxxx アカウントに作成し、以下のバケットポリシーを付与します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::36xxxxxxxxxx:role/Admin"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::rcp-test-20241115/*"
}
]
}
36xxxxxxxxxx アカウントから上記バケットのオブジェクトを取得できることを確認します。
$ curl http://checkip.amazonaws.com/
35.75.7.30
$ aws s3api get-object --bucket rcp-test-20241115 --key test test
{
"AcceptRanges": "bytes",
"LastModified": "2024-11-15T05:19:38+00:00",
"ContentLength": 5,
"ETag": "\"d8e8fca2dc0f896fd7cb4cb0031ba249\"",
"ContentType": "binary/octet-stream",
"ServerSideEncryption": "AES256",
"Metadata": {}
}
$ cat test
test
33xxxxxxxxxx アカウントが所属する Organizations の管理アカウントで RCPs を有効化します。
RCPs を有効化すると RCPFullAWSAccess
がデフォルトで Root、すべての OU、すべての AWS アカウントにアタッチされます。そうしないとリクエストの許可/拒否の評価ルールによりすべて Deny 扱いされてしまうからですね。
33xxxxxxxxxx アカウントは Root -> Sandbox OU に配置しているので、RCPs を確認すると以下のように Root、Sandbox、直接アタッチの計 3 つが表示されています。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "*",
"Resource": "*"
}
]
}
33xxxxxxxxxx アカウントに以下の RCPs を適用します。
(AWS サービスからのアクセスもできなくなるので、実際は PrincipalIsAWSService を利用して除外するなど必要です。)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "52.11.105.11/32"
}
}
}
]
}
36xxxxxxxxxx アカウントから再び GetObejct を試すと Access Denied になりました。
$ curl http://checkip.amazonaws.com/
35.75.7.30
$ aws s3api get-object --bucket rcp-test-20241115 --key test test
An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
33xxxxxxxxxx アカウントからの挙動は変わりません。
$ curl http://checkip.amazonaws.com/
52.11.105.11
$ aws s3api get-object --bucket rcp-test-20241115 --key test test
{
"AcceptRanges": "bytes",
"LastModified": "2024-11-15T05:19:38+00:00",
"ContentLength": 5,
"ETag": "\"d8e8fca2dc0f896fd7cb4cb0031ba249\"",
"ContentType": "binary/octet-stream",
"ServerSideEncryption": "AES256",
"Metadata": {}
}
$ cat test
test
ポリシーをデタッチすると 36xxxxxxxxxx のアカウントから再びアクセスできました。
$ curl http://checkip.amazonaws.com/
35.75.7.30
$ aws s3api get-object --bucket rcp-test-20241115 --key test test
{
"AcceptRanges": "bytes",
"LastModified": "2024-11-15T05:19:38+00:00",
"ContentLength": 5,
"ETag": "\"d8e8fca2dc0f896fd7cb4cb0031ba249\"",
"ContentType": "binary/octet-stream",
"ServerSideEncryption": "AES256",
"Metadata": {}
}
FAQ
- Q.サービスリンクロールは RCPs で制御される?
- A. No.
-
The exception is when principals are service-linked roles because RCPs do not apply to calls made by service-linked roles
- Q. サポート外のサービスの Action を記載するとどうなる?
- A. ポリシーが保存できない
- A. ポリシーが保存できない
Discussion