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の使用を防ぐだけで、他の対策をしていなければ何も意味はないので、セキュリティ等を見直す機会としたいです。
参考リンク












