S3 の暗号化 SSE-S3・SSE-KMS・SSE-C・クライアント側暗号化の違い ── 自分で持っている鍵で暗号化する
記事の「実践」を 1 項目ずつ進めるためのページです。AWS マネジメントコンソールで操作したら、右の一覧にチェックを入れてください。チェックはこのブラウザに保存されます。
前提条件
- リージョン:
ap-northeast-1(東京) - S3 の操作権限(バケットの暗号化設定の変更
s3:PutEncryptionConfigurationを含む)を持つ IAM ユーザーまたはロールでコンソールにログイン済みであること - AWS CloudShell が使えること
事前に作成しておくリソースはありません。このハンズオンで作成するリソースは以下のとおりです。
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| S3 汎用バケット | sse-lab-<任意の文字列> | 暗号化の方式を比べる(バケット名は世界で一意にする) |
| オブジェクト | ssec.txt / kms.txt / client.txt.enc | SSE-C・SSE-KMS・クライアント側の暗号化で保存したもの |
| 鍵ファイル(CloudShell 内) | ssec.key / client.pass | SSE-C の鍵と、クライアント側の暗号化のパスフレーズ |
手順 1: バケットを作り、SSE-C がブロックされていることを確かめる
AWS マネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。
上部の検索バーに S3 と入力し、「S3」を選択します。左側ナビゲーションの「汎用バケット」から「バケットを作成」をクリックし、バケット名に sse-lab-<任意の文字列> を入力します。その他の項目はデフォルトのままにして、「バケットを作成」をクリックします。
作成したバケットを開き、「プロパティ」タブの「デフォルトの暗号化」を確認します。暗号化タイプが「Amazon S3 マネージドキーを使用したサーバー側の暗号化 (SSE-S3)」になっており、「ブロックされた暗号化タイプ」に「お客様提供のキーによるサーバー側の暗号化 (SSE-C)」が表示されています。
手順 2: SSE-C でのアップロードが拒否されることを確かめる
コンソール上部の CloudShell アイコンから CloudShell を開き、次のコマンドを実行します。BUCKET には手順 1 で作ったバケット名を入れます。
BUCKET=sse-lab-<任意の文字列>
# SSE-C の鍵(256 ビット = 32 バイト)を作る
openssl rand 32 > ssec.key
echo "SSE-C で保存したファイル" > ssec.txt
aws s3 cp ssec.txt s3://$BUCKET/ssec.txt --sse-c AES256 --sse-c-key fileb://ssec.key
AccessDenied のエラーで拒否されることを確認します。エラーの後半には「because this bucket has blocked upload requests that specify Server Side Encryption with Customer provided keys (SSE-C)」と理由が表示されます。新しいバケットでは、SSE-C を指定した書き込みが既定でブロックされているためです。
手順 3: バケットで SSE-C を許可する
S3 コンソールに戻り、バケットの「プロパティ」タブの「デフォルトの暗号化」で「編集」をクリックします。
「デフォルトの暗号化を編集」の画面の「ブロックされる暗号化タイプ」で、「SSE-C (顧客提供のキーによるサーバー側の暗号化)」のチェックを外します。暗号化タイプは SSE-S3 のままにして、「変更の保存」をクリックします。
手順 4: SSE-C で保存し、鍵がないと取得できないことを確かめる
CloudShell に戻り、同じアップロードをもう一度実行します。今度は成功します。
aws s3 cp ssec.txt s3://$BUCKET/ssec.txt --sse-c AES256 --sse-c-key fileb://ssec.key
鍵を渡さずに取得すると、An error occurred (400) when calling the HeadObject operation: Bad Request のエラーで取得できません。
aws s3 cp s3://$BUCKET/ssec.txt -
同じ鍵を渡すと取得できます。
aws s3 cp s3://$BUCKET/ssec.txt - --sse-c AES256 --sse-c-key fileb://ssec.key
手順 5: SSE-KMS とクライアント側の暗号化でも保存する
SSE-KMS(AWS マネージドキー aws/s3)で保存します。
echo "SSE-KMS で保存したファイル" > kms.txt
aws s3 cp kms.txt s3://$BUCKET/kms.txt --sse aws:kms
クライアント側の暗号化は、ここでは S3 暗号化クライアントの代わりに openssl で手元のファイルを暗号化してから、普通にアップロードします。
openssl rand -base64 32 > client.pass
echo "クライアント側で暗号化したファイル" > client.txt
openssl enc -aes-256-cbc -pbkdf2 -salt -in client.txt -out client.txt.enc -pass file:./client.pass
aws s3 cp client.txt.enc s3://$BUCKET/client.txt.enc
S3 コンソールでバケットを開き、3 つのオブジェクトが並んでいることを確認します。
kms.txt を開き、「プロパティ」タブの「サーバー側の暗号化設定」で、暗号化タイプが SSE-KMS で、AWS KMS キーが表示されていることを確認します。
ssec.txt を開くと、「サーバー側の暗号化設定」は「不明なエラー」と表示され、暗号化の設定を読み取れません。その下の「チェックサム」には「SSE-C で暗号化されたオブジェクト」と表示され、AWS CLI・AWS SDK・REST API を使うよう案内されます。SSE-C はコンソールでは使えないため、コンソールからこのオブジェクトの中身を開くこともできません。
手順 6: クライアント側で暗号化したデータを確かめる
CloudShell に戻り、client.txt.enc をそのまま取得します。S3 から返ってくるのは暗号化済みのデータなので、中身は読めません。手元のパスフレーズで復号すると、元の文字列に戻ります。
aws s3 cp s3://$BUCKET/client.txt.enc - | head -c 64 | od -c | head -3
aws s3 cp s3://$BUCKET/client.txt.enc - | openssl enc -d -aes-256-cbc -pbkdf2 -pass file:./client.pass
S3 はこのオブジェクトにも既定の SSE-S3 をかけていますが、その下の中身はすでに手元で暗号化されています。パスフレーズは S3 にも AWS にも渡していません。
手順 7: SSE-C をブロックし直し、既存のオブジェクトは読めることを確かめる
S3 コンソールでバケットの「デフォルトの暗号化」の「編集」を開き、「SSE-C (顧客提供のキーによるサーバー側の暗号化)」に再びチェックを入れて「変更の保存」をクリックします。
CloudShell で、新しい SSE-C の書き込みと、既存のオブジェクトの取得を試します。
aws s3 cp ssec.txt s3://$BUCKET/ssec-2.txt --sse-c AES256 --sse-c-key fileb://ssec.key
aws s3 cp s3://$BUCKET/ssec.txt - --sse-c AES256 --sse-c-key fileb://ssec.key
新しい書き込みは AccessDenied で拒否され、すでに SSE-C で保存した ssec.txt は鍵を渡せば取得できることを確認します。