AWS Organizations で S3 オブジェクトの SSE-C 暗号化を組織全体で無効化する
クラウド事業本部の梶原@福岡オフィスです。
AWS Organizations を使用して、組織全体の S3 オブジェクトで SSE-C(お客様提供の暗号化キー)の使用を無効化する方法をご紹介します。
無効化を実装するにあたり、リソースコントロールポリシーの記述が少し癖がありますので、導入しやすいようにCloudFormation のテンプレートでリソースコントロールポリシーの作成を提供しています。
また、RCPの組織への適用は影響範囲が大きいので、AWSコンソールでの手動での適用は避け、AWS CLI等で適用方法をご案内しています。
なぜ SSE-C をブロックする必要があるのか
先日、AWSのセキュリティブログにて、以下のエントリーが案内されておりました。
悪意のある人物によってSSE-C を使用した多数の S3CopyObject操作によってオブジェクトが上書きされ、新しい暗号化キーで顧客データを再暗号化する
この操作を防ぐための対策になります。
- 短期的な資格情報を実装する
- データ復旧手順を実装する
- 予期しないアクセスパターンがないか AWS リソースを監視する
- アプリケーションで要求されない限り、SSE-C の使用をブロックします。
を実装する必要がありますが、4の部分の対応法をご案内します
またSSE-Cの利用については
- SSE-C の課題
- 暗号化キーの管理・保管の負担
- キー紛失時のデータ復旧不可
- キーのローテーションなど運用管理の複雑さ
などの課題があり、SSE-Cでなくとも、SSE-S3, SSE-KMSでの暗号化のワークアラウンドがありますので、この際、SSE-Cの使用はブロックするという選択肢は十分ありかなと思いました。
SSE-C をブロックする方法
AWS Organizations のリソースコントロールポリシー(RCP)を使用して、組織全体で SSE-C の使用を制限します。
実装方法
以下のように RCP を作成するCloudFormationテンプレートを記載します:template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
BucketName:
Type: String
Description: "S3 bucket name prefix (optional)"
Default: ""
Conditions:
HasBucketName: !Not [!Equals [!Ref BucketName, ""]]
Resources:
SSECPolicy:
Type: AWS::Organizations::Policy
Properties:
Name: "S3-SSEC-Policy"
Description: "Deny S3 PutObject operations with customer-provided encryption"
Type: "RESOURCE_CONTROL_POLICY"
Content:
Fn::Sub:
- |
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "RestrictSSECObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "${ResourceValue}",
"Condition": {
"Null": {
"s3:x-amz-server-side-encryption-customer-algorithm": "false"
}
}
}]
}
- ResourceValue: !If
- HasBucketName
- !Sub "arn:aws:s3:::${BucketName}*"
- "*"
ポリシーの解説
このポリシーは以下のように SSE-C をブロックします:
-
対象操作
s3:PutObject
アクションをブロック- SSE-C が指定されている場合にのみ拒否
-
ブロックの条件
s3:x-amz-server-side-encryption-customer-algorithm
が存在する場合- これは SSE-C が使用される際に設定されるヘッダー
-
適用範囲の制御
- 全バケット内のオブジェクト: パラメータなしでデプロイ
- 特定バケット内のオブジェクト: プレフィックスを指定してデプロイ
組織へのポリシー適用手順
管理アカウントにログインし、CloudShell等で実施します
1. リソースコントリールポリシーの作成
特定のバケットだけブロックしたい場合は、テンプレートのBucketName(Prefix)を設定してください
aws cloudformation deploy \
--template-file template.yaml \
--stack-name ssec-policy-stack
2. リソースコントリールポリシーの有効化
r-xxxx は有効な組織ID(Root)に置き換えてください
aws organizations enable-policy-type \
--root-id r-xxxx \
--policy-type RESOURCE_CONTROL_POLICY
3. リソースコントリールポリシーIDの取得
リソースコントリールポリシーより作成したS3-SSEC-PolicyのIDを取得します。
"Id" で記載されている箇所になります
aws organizations list-policies --filter RESOURCE_CONTROL_POLICY
{
"Policies": [
{
"Id": "p-xxxx",
"Arn": "arn:aws:organizations::123456789012:policy/o-xxx/resource_control_policy/p-XXXXX",
"Name": "S3-SSEC-Policy",
"Description": "Deny S3 PutObject operations with customer-provided encryption",
"Type": "RESOURCE_CONTROL_POLICY",
"AwsManaged": false
}
}
4. リソースコントリールポリシーのアタッチ
r-xxxx は組織ID(Root)に置き換えてください
ou-xxx は適用したい組織IDに置き換えた下さい
# 組織全体に適用
aws organizations attach-policy \
--policy-id p-xxxx \
--target-id r-xxxx
# または特定のOUに適用
aws organizations attach-policy \
--policy-id p-xxxx \
--target-id ou-xxxx
4. リソースコントリールポリシーのアタッチ確認
アタッチされているか確認します。
RCPFullAWSAccessは全リソースへのアクセスをデフォルトで許可しているポリシーになります
$ aws organizations list-policies-for-target --target-id ou-xxx --filter RESOURCE_CONTROL_POLICY
{
"Policies": [
{
"Id": "p-xxxx",
"Arn": "arn:aws:organizations::123456789012:policy/o-xxxxx/resource_control_policy/p-xxxx",
"Name": "S3-SSEC-Policy",
"Description": "Deny S3 PutObject operations with customer-provided encryption",
"Type": "RESOURCE_CONTROL_POLICY",
"AwsManaged": false
},
{
"Id": "p-RCPFullAWSAccess",
"Arn": "arn:aws:organizations::aws:policy/resource_control_policy/p-RCPFullAWSAccess",
"Name": "RCPFullAWSAccess",
"Description": "Allows access to every resource",
"Type": "RESOURCE_CONTROL_POLICY",
"AwsManaged": true
}
]
}
動作確認手順
適用した組織内のアカウントで、適用したポリシーが意図した動作をするか確認します
1. SSE-C を使用したアップロード試行
# テスト用ファイルの作成
echo "test content" > test.txt
# 暗号化キーの生成(32バイトのランダムキー)
openssl rand 32 > sse-c-key
# SSE-C を使用したアップロード試行
aws s3 cp test.txt s3://my-bucket-hoge-fuga/test.txt \
--sse-c AES256 \
--sse-c-key fileb://sse-c-key
# 期待される結果:
# upload failed: ./test.txt to s3://xxxxxx/test.txt An error occurred (AccessDenied) when calling the PutObject operation: User: axxxx is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::xxxx/test.txt" with an explicit deny in a resource control policy
2. 通常のアップロード確認
# SSE-S3 を使用したアップロード
aws s3 cp test.txt s3://my-bucket-hoge-fuga/test-s3.txt \
--sse AES256
# SSE-KMS を使用したアップロード
aws s3 cp test.txt s3://my-bucket-hoge-fuga/test-kms.txt \
--sse aws:kms \
--sse-kms-key-id arn:aws:kmsxxxxxxxxxx
導入時の注意点
-
既存のオブジェクトへの影響
- 既存の SSE-C 暗号化オブジェクトは影響を受けません
- 読み取りは通常通り可能です
- 新規のアップロードと更新のみがブロックされます
-
代替の暗号化方式の検討
- SSE-S3: AWS マネージドキーによる暗号化
- SSE-KMS: AWS KMS で管理された暗号化キーによる暗号化
-
移行のステップ
- 既存の SSE-C 利用者への通知
- アプリケーションの設定変更
- 段階的な導入の検討
まとめ
AWS Organizations のリソースコントロールポリシーを使用し、組織に対してSSE-Cの使用をブロックしてみました。あらためてですが、SSE-Cの使用を防ぐだけで、他の対策をしていなければ何も意味はないので、セキュリティ等を見直す機会としたいです。
参考リンク