本日も乙

ただの自己満足な備忘録。

S3の暗号化についてまとめてみた(2018年6月版)

前回はS3バケットのデフォルト暗号化のパフォーマンス比較を紹介しました。 本当はこちらを先に紹介すべきでしたが、今回はS3の暗号化についてまとめてみました。

暗号化の種類

大きく分けてサーバ(Amazon S3)側とクライアント側に分かれます。

サーバ側の暗号化(Server Side Encryption: SSE)

サーバ(S3)に保管する際、つまりAWSのデータセンターにあるサーバのディスクに書き込まれる際にデータを暗号化します。データ格納時の暗号化とデータ取得時の復号をAWS側が管理してくれます。SSEの中でも三種類に分かれます。

  • S3で管理されたキーによる暗号化 (SSE-S3)
    • 暗号化キーの管理・ローテーション等をすべてAWSで管理してくれます
  • KMS で管理されたキーによる暗号化 (SSE-KMS)
    • 暗号化キーをKMSで管理します。KMSを利用することで、証跡(CloudTrail)を残せたり暗号化キーの権限を設定できたりします。ただし、KMSの利用には料金が発生しますし、S3操作が多いとKMSのリクエスト制限に達する可能性があります
  • ユーザが用意したキーによる暗号化 (SSE-C)
    • ユーザが用意した独自のキーで暗号化できます。自分で管理しなければならないデメリットはあるものの、鍵を自分で管理しなければならない要件では必要かと思います(どんな要件?)

クライアント側の暗号化(Client Side Encryption: CSE)

S3に格納する前にデータを暗号化します。暗号化に使用するキーはKMSやユーザが用意したものを利用できます。

デフォルト暗号化

従来では、S3バケットにファイルをアップロードする際は、暗号化オプションの指定が必要でした。また、暗号化していないファイルを拒否するバケットポリシーを設定する必要がありました。
デフォルト暗号化によって、アップロードする際の暗号化オプションの指定が不要になりました。また、バケットポリシーの設定が不要になります。
デフォルト暗号化で利用できる種類は SSE-S3 と SSE-KMS です。

AWS CLIで有効化するには以下のようにします。以下はSSE-S3による暗号化を有効化しています。

#!/bin/bash

bucket_name=$1

cat << EOF > ./config.json
{
  "Rules": [
    {
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "AES256"
      }
    }
  ]
}
EOF

aws s3api put-bucket-encryption --bucket ${bucket_name} --server-side-encryption-configuration file://config.json

デフォルト暗号化を無効化する場合は以下のように実行します。

$ aws s3api delete-bucket-encryption --bucket ${bucket_name}

デフォルト暗号化におけるAthenaのテーブル定義による注意点

最近のアップデートで暗号化設定したS3バケットに対してAthenaからクエリ実行できるようになりました。
しかし、暗号化の種類によってはAhenaのテーブルプロパティ(has_encrypted_data)の設定が必要になります。必要となるケースをリンク先より転載しました。

暗号化の種類 Athena: テーブルデータからのリード Athena: クエリ結果に対する読み書き テーブルプロパティ has_encrypted_data=true が必要か
SSE-S3 不要
SSE-KMS 不要
CSE-KMS 必要
CSE-C 不可 不可 -
SSE-C 不可 不可 -

サーバサイドによる暗号化ではSSE-C以外はAthenaテーブルへの変更も不要です。
既存テーブルに対して has_encrypted_data=true を有効化したい場合は ALTER TABLE SET TBLPROPERTIES文を実行してください。

既存S3オブジェクトの暗号化

デフォルト暗号化を設定する以前にS3オブジェクト(ファイル)が格納されている場合は暗号化されません。既存のファイルを暗号化するには以下のようにします。

$ aws s3 cp s3://${bucket_name} s3://${bucket_name} --recursive --sse

# 暗号化を無効化する場合
$ aws s3 cp s3://${bucket_name} s3://${bucket_name} --recursive

一つ一つのファイルに対してコピーしながら暗号化していくため、ファイル数に応じてCOPYリクエストが発生します。つまりは料金が発生します。もし膨大なファイル数に対して暗号化する際には、予めファイル数をCloudWatchのメトリクスで確認の上、いくらかかるのか試算されることをおすすめします。

最後に

S3の暗号化について紹介しました。暗号化に求められるセキュリティ要件に制約がなければ、SSE-S3によるデフォルト暗号化が最も無難でアプリケーション側の変更もなく、おすすめだと思います。

参考