S3が暗号化されている実感がわかないので、復号できない場合の挙動を確かめてみた

S3の暗号化って、マネージドに勝手にやってくれて超便利!でも、内部で復号も自動でやってくれるから暗号化されてる実感が無い…。

そうだ!復号できない場合の挙動を見てみれば、これは確かに暗号化されているって安心できるかも!

と、いうわけで暗号化されたS3のオブジェクトが復号できないパターンの挙動を確かめてみました。

前提となる知識

KMS(Key Management Service)

AWS KMSは、暗号化キーの作成と管理を容易にするマネージド型サービスです。 S3のサーバーサイド暗号化に使用します。

KMS自体については、弊社ブログでとてもわかりやすく解説しているので、詳細はこちらを御覧ください。

参考:10分でわかる!Key Management Serviceの仕組み #cmdevio | DevelopersIO

S3のサーバーサイド暗号化

S3はサーバーサイドの暗号化が可能です。

参考:サーバー側の暗号化を使用したデータの保護 - Amazon Simple Storage Service

S3でデフォルト暗号化の設定をすることで、ファイル格納時に特に意識すること無くオブジェクトの暗号化が可能です。

参考Amazon S3がファイル格納時のデフォルト暗号化に対応しました | DevelopersIO

マネージドにやってくれるのはとてもありがたいのですが、マネージドにやってくれるが故に、暗号化している意識も、復号している意識もありません。

と、いうわけで本当に暗号化されてるんかいな?と、いうことを知るため、暗号化したS3のオブジェクトが復号できない場合、どういう挙動になるのか試してみました。

構成

KMS(CMK)を利用してS3のデフォルト暗号化を設定し、復号できない場合の挙動を調べてみます。

デフォルト暗号化を設定したS3の構築

KMS(CMK)の構築

カスタマー管理型のキーのページを開いて、新しいキーを作成します。

適当なエイリアス(例:s3-kms-test)を入力して、キーマテリアルオリジンにKMSを選択して、次へ進みます。

タグは付けなくても良いので、そのまま次に進みます。

今回は検証なので、キーの削除ができるようにチェックを外して次へ進みます。

今回作成するキーを利用する、UserまたはRoleを選択して次へ進みます。

最後に確認画面が表示されるので、問題なければ完了ボタンを押します。

これでKMS(CMK)の構築ができました。

S3の構築

適当なバケット名をつけて、KMSを作ったのと同じリージョンを選択します。今回は、Oregonリージョンを使用します。

デフォルト暗号化にチェックを入れて、AWS-KMSを選択します。先程作成したKMSを選択して次へ進みます。

パブリックアクセスする必要はないので全てブロックして次へ進みます。

確認画面が表示されるので内容に問題がなければバケットを作成します。

これでS3の構築ができました。

ファイルをアップロードしてみる

とりあえずファイルアップロードしてみます。

アップロードしたファイルの詳細を見ると、KMSで暗号化されていそうなことがわかります。

CLIでも、APIレベルコマンド(s3api)を利用すると、KMSで暗号化されていることがわかります。

$ aws s3api head-object \
  --bucket <<BUCKET_NAME>> \
  --key hello_world.html
{
    "AcceptRanges": "bytes",
    "LastModified": "Tue, 30 Jul 2019 06:52:00 GMT",
    "ContentLength": 13,
    "ETag": "\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"",
    "ContentType": "text/html",
    "ServerSideEncryption": "aws:kms",
    "Metadata": {},
    "SSEKMSKeyId": "arn:aws:kms:us-west-2:XXXXXXXXXXXX:key/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

KMSの権限が無いRoleでアクセスしてみる

それでは次にKMSで復号ができない状況を見ていきましょう。

まずはKMSの権限が無いRoleでのアクセスしてみます。

概要画面までは同様にアクセスすることができます。

しかし、ファイルのダウンロードをしようとすると、Access Deniedエラーになります。 KMSへの権限が無く、復号する権限が無いので、アクセス不能になっていることがわかります。

CLIでも確認すると、同様にAccess Deniedエラーになることがわかります。

$ aws s3api get-object \
  --bucket <<BUCKET_NAME>> \
  --key hello_world.html \
  outfile
An error occurred (AccessDenied) when calling the GetObject operation: Access Denied

KMSそのものを消してみる

次は暗号化に使ったKMSを削除してみます。これを本番環境でやらかしてしまうと復号できなくなるので、絶対にやらないようにしましょう。

概要画面までは同様にアクセスすることができます。

しかし、ファイルのダウンロードをしようとすると、KMS.KMSInvalidStateExceptionになります。 復号のためのKMSが存在しないことで、アクセス不能になっていることがわかります。

CLIでも一応確認すると、同様にKMS.KMSInvalidStateExceptionになることがわかります。

$ aws s3api get-object \
  --bucket <<BUCKET_NAME>> \
  --key hello_world.html \
  outfile
An error occurred (KMS.KMSInvalidStateException) when calling the GetObject operation: arn:aws:kms:us-west-2:XXXXXXXXXXXX:key/xxxxxxxxxxxxxxxxxxxxxxxxxx is pending deletion.

【番外編】静的ウェブサイトホスティングしてみる

サーバーサイドで暗号化したS3を、静的ウェブサイトホスティング(Static Website Hosting)で公開すると、どうなるのでしょうか?

S3の静的ウェブサイトホスティングについて知りたい方は、弊社ブログを御覧ください。
参考:AWS再入門 Amazon S3編 | DevelopersIO

公開してアクセスすると、400エラーになります。

暗号化しているということは、公開情報ではなく秘匿情報であると考えられるので、静的ウェブサイトホスティングで使用できないことは妥当な挙動だと思います。

おわりに

マネージドに暗号化することができるS3はとても便利です。
復号できない場合の挙動について考えてみることで、よりS3の暗号化について理解することができました。
自分で暗号化するのはめんどくさいので、今後もマネージドなサービスをフル活用していきたいと思います。