0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

S3バケットアクセスの落とし穴 〜SSE-KMS暗号化バケットへの外部アカウントアクセスでちょっとハマった話〜

0
Posted at

はじめに

外部アカウント(別のAWSアカウント)からS3バケットにアクセスする構成は、クロスアカウント連携でよくあるパターンです。
バケットポリシー、アクセス元のIAMロールで許可を出していれば問題なくアクセスできると思いきや、バケットがカスタマー管理型SSE-KMSで暗号化されている場合は、それだけでは403 Access Deniedになるという落とし穴があります。(私はハマりました。。。)

こんなことがありました...
今までのS3運用ではSSE-S3を利用しバケットの暗号化を行っていましたが、突如セキュリティチームより「今後はS3にはSSE-KMSを利用しなさい」というお達しが。
当時ちょうど外部アクセスされるS3バケットの作成を予定しており、いつも通りS3バケットを作成し、暗号化はプロジェクトで利用している既存のKMSで使っているのKMSキーを設定し疎通確認をおこなったところ繋がらん。。という事態になりました。
※KMSを新規作成した時ならほぼ確実に気づけます。

結論

SSE-S3 で暗号化されたバケットは、バケットポリシー/IAMの許可だけで外部アカウントからアクセスできる。
SSE-KMS で暗号化されたバケットは、バケットポリシーに加えて KMSキーポリシー側にも外部アカウントへの許可 が必要。

つまり「暗号化方式によって、必要な許可設定の数が変わる」というのがポイントです。

なぜ違いが生まれるのか

暗号化方式 鍵の管理者 暗号化/復号の主体 必要な許可
SSE-S3 AWS(マネージド) S3サービス内部で完結 バケットポリシー/IAMのみ
SSE-KMS KMSカスタマー管理キー KMSが鍵を使って暗号化/復号 バケットポリシー/IAM + KMSキーポリシー

SSE-S3はAWSが内部で鍵を管理しており、ユーザー側からは鍵の存在を意識する必要がありません。そのため、S3オブジェクトへのアクセス可否はバケットポリシーやIAMポリシーだけで決まります。

一方SSE-KMSは、暗号化・復号のたびにKMSキーへのアクセスが発生します。S3はオブジェクトを返す前に裏側でKMSの kms:Decrypt(アップロード時は kms:GenerateDataKey)を呼び出しており、呼び出し元(外部アカウントのIAMロール等)がそのKMSキーに対する権限を持っていなければ拒否されます。バケットポリシーで許可していても、KMSキー側の許可がなければアクセスは失敗します。

つまり、SSE-KMSの場合は 「バケットポリシー」と「KMSキーポリシー」の両方の許可を満たす必要がある という点が最大の落とし穴です。

※AWSマネージド型KMSキーはKMSキーポリシーの編集ができないため外部からのアクセスはできません。

SSE-S3とSSE-KMS、それぞれのメリット・デメリット

「じゃあクロスアカウントで面倒なSSE-KMSなんて使わずSSE-S3でいいのでは?」と思うかもしれませんが、それぞれにメリット・デメリットがあるため、要件に応じて選ぶ必要があります。

SSE-S3

メリット

  • 設定が不要で、デフォルトでも有効になっている(追加コストもなし)
  • 鍵の管理を一切意識しなくてよく、運用がシンプル
  • クロスアカウントアクセスもバケットポリシー/IAMだけで完結する(今回の落とし穴がそもそも発生しない)

デメリット

  • 鍵の利用ログ(誰がいつ復号したか)を個別に追跡できない。CloudTrailでKMSのAPI呼び出しログを見る、といった監査ができない
  • 鍵のローテーションや無効化など、鍵自体の制御がユーザー側にできない
  • 鍵単位でのアクセス制御(特定のロールだけ復号を許可、など)ができない。アクセス制御の粒度はバケット/オブジェクト単位に限られる

SSE-KMS

メリット

  • 鍵単位でアクセス制御できる(同じバケットでも、鍵ポリシーを使って復号できる人/ロールを細かく制限できる)
  • CloudTrailで kms:Decrypt / kms:GenerateDataKey の呼び出しが記録されるため、誰がいつ鍵を使ったかを監査できる
  • カスタマー管理キーであれば、鍵のローテーション、無効化、削除のスケジューリングなど鍵のライフサイクルを自分で制御できる
  • コンプライアンス要件(鍵の管理主体を自社にする必要がある、など)に対応しやすい

デメリット

  • KMSのAPIコール(暗号化・復号のたび)に対して課金が発生する(リクエスト数に応じた従量課金)
  • カスタマー管理キーは1ヶ月あたりの固定費がかかる(AWS管理キー aws/s3 は無料だが、前述の通りキーポリシーを編集できないためクロスアカウント共有には使えない)
  • クロスアカウントやクロスサービル連携の際に、バケットポリシーとKMSキーポリシーの両方を設定する必要があり、設定漏れによる AccessDenied が起きやすい(まさに本記事の落とし穴)
  • KMSのAPIリクエスト制限(スロットリング)があるため、大量のオブジェクトに高頻度でアクセスするワークロードでは考慮が必要

どっちがいいの?

  • 鍵の利用監査や、鍵単位でのアクセス制御が不要 → SSE-S3 でシンプルに済ませる
  • 監査要件がある、鍵のライフサイクルを自社で管理したい、特定のロールだけに復号を許可したい → SSE-KMS

実際に起きる症状

  • バケットポリシーで外部アカウント(または特定のIAMロール)に s3:GetObject を許可した
  • 外部アカウント側でもそのバケットへの s3:GetObject をIAMポリシーで許可した

この状態でファイルアップロードなどの操作を行うとエラーになります。(エラーメッセージを見ればわかりますね)
例:

[root@ip-10-0-0-1 tmp]# aws s3 cp ./test.txt s3://s3-bucket
upload failed: ./test.txt to s3://s3-bucket/test.txt An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:sts::xxxxxxxxxxxxxx:assumed-role/ec2-role/i-0d26084946ed30b03 is not authorized to perform: kms:GenerateDataKey on resource:arn:aws:kms:ap-northeast-1:xxxxxxxxxxxxxx:key/xxxxxxxxxx because no identity-based policy allows the kms:GenerateDataKey action
[root@ip-ip-10-0-0-1 tmp]#

解決策

KMS操作を許可する外部アカウントのポリシーとS3に設定しているKMSキーポリシーにステートメントを追加します。

外部アカウントのポリシー:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3Access",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::YOUR_BUCKET_NAME",
        "arn:aws:s3:::YOUR_BUCKET_NAME/*"
      ]
    },
 ------この部分のポリシーが追加で必要です------
    {
      "Sid": "AllowKMSForSSEKMS",
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "kms:GenerateDataKey"
      ],
      "Resource": "arn:aws:kms:ap-northeast-1:ACCOUNT_A_ID:key/KMS_KEY_ID"
    }
------------------------------------------
  ]
}
KMSキーポリシー:
{
  "Id": "key-consolepolicy-3",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxxxx:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow access for Key Administrators",
      "Effect": "Allow",
      "Principal": {
        "AWS": 
          "arn:aws:iam::xxxxxxxxxxxxxx:role/Administrator-Role"
      },
      "Action": [
        "kms:Create*",
        "kms:Describe*",
        "kms:Enable*",
        "kms:List*",
        "kms:Put*",
        "kms:Update*",
        "kms:Revoke*",
        "kms:Disable*",
        "kms:Get*",
        "kms:Delete*",
        "kms:TagResource",
        "kms:UntagResource",
        "kms:ScheduleKeyDeletion",
        "kms:CancelKeyDeletion",
        "kms:RotateKeyOnDemand"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Allow use of the key",
      "Effect": "Allow",
      "Principal": {
        "AWS":
          "arn:aws:iam::xxxxxxxxxxxxxx:role/Administrator-Role"
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Allow attachment of persistent resources",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::xxxxxxxxxxxxxx:role/Administrator-Role",
------この部分のポリシーが追加で必要です------
          "外部アカウントのロールArn"
-------------------------------------------
        ]
      },
      "Action": [
        "kms:CreateGrant",
        "kms:ListGrants",
        "kms:RevokeGrant"
      ],
      "Resource": "*",
      "Condition": {
        "Bool": {
          "kms:GrantIsForAWSResource": "true"
        }
      }
    }
  ]
}

※外部アカウントのキーユーザはコンソールからは見つからないため以下の画面から直接ポリシーを修正する必要が在ります。
image.png

まとめ

  • SSE-S3とSSE-KMSでは、外部アカウントへのアクセス許可に必要な設定箇所が異なる
  • SSE-KMSはバケットポリシーだけでなく、KMSキーポリシー側の許可も必須
  • AWS管理キー(aws/s3)はキーポリシーを編集できないため、クロスアカウント共有が必要な場合はカスタマー管理キーを使う

以上です!最後まで読んでいただきありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?