S3 でオブジェクトの暗号化を検討する場合,大きく2種類ある.
- サーバサイド暗号化
- 暗号化/複合を AWS 側に任せる
- サーバー側の暗号化を使用したデータの保護 - Amazon Simple Storage Service
- クライアントサイド暗号化
AWS 認定試験にも関係するし,知識としては知っていたけど,実際に試したことがなかったので AWS SDK for Ruby を使って動作確認をしてみた.
前提
適当なログファイルを用意した.
$ cat sample.log 1 2 3 4 5
暗号化なし
ドキュメントの通りに実装すればオブジェクトをアップロードすることができる.
require 'aws-sdk' require 'pp' s3 = Aws::S3::Client.new File.open('./sample.log') do |file| s3.put_object( bucket: 'xxx', key: 'sample.log', body: file ) end
サーバサイド暗号化 : AES256
put_object()
のパラメータとして server_side_encryption: 'AES256'
を指定するだけで良い.
require 'aws-sdk' require 'pp' s3 = Aws::S3::Client.new File.open('./sample.log') do |file| s3.put_object( bucket: 'xxx', key: 'sample2.log', body: file, server_side_encryption: 'AES256' ) end pp s3.head_object( bucket: 'xxx', key: 'sample2.log', )
head_object()
でメタデータを確認したら,server_side_encryption
の値が AES256 になっていた.
#<struct Aws::S3::Types::HeadObjectOutput (中略) server_side_encryption="AES256", (中略) parts_count=nil>
管理コンソールから確認することもできる.さらに AES256 の場合,自由に暗号化 ON/OFF を切り替えることができる.サーバサイド暗号化のメリットと言えるかもしれない.
サーバサイド暗号化 : KMS
put_object()
のパラメータとして server_side_encryption: 'aws:kms'
を指定する.
require 'aws-sdk' require 'pp' s3 = Aws::S3::Client.new File.open('./sample.log') do |file| s3.put_object( bucket: 'xxx', key: 'sample3.log', body: file, server_side_encryption: 'aws:kms' ) end pp s3.head_object( bucket: 'xxx', key: 'sample3.log', )
head_object()
でメタデータを確認したら,server_side_encryption
の値が aws:kms になっていた.また事前に KMS でキーを生成しなくても,自動的に KMS で S3 用のマスターキーが生成されていた.
#<struct Aws::S3::Types::HeadObjectOutput (中略) server_side_encryption="aws:kms", ssekms_key_id="arn:aws:kms:ap-northeast-1:111111111111:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", (中略) parts_count=nil>
管理コンソールから確認することもできる.ただし,KMS の場合,暗号化 ON/OFF を切り替えることはできなかった.
クライアントサイド暗号化 : 独自キー
クライアントサイド暗号化を行う場合は Aws::S3::Client
ではなく Aws::S3::Encryption::Client
でクライアントを生成する必要がある.とは言え,実装はほとんど変わらず,クライアントの初期化で encryption_key
を指定するぐらい.
require 'aws-sdk' require 'pp' require 'openssl' s3_encryption = Aws::S3::Encryption::Client.new( encryption_key: OpenSSL::PKey::RSA.new(1024) ) File.open('./sample.log') do |file| s3_encryption.put_object( bucket: 'xxx', key: 'sample4.log', body: file ) end
クライアントで暗号化をしているため,オブジェクトを取得する場合も Aws::S3::Encryption::Client
を使う必要がある.Aws::S3::Client
を使ってしまうと暗号化されたまま取得されてしまう.
require 'aws-sdk' require 'pp' require 'openssl' s3_encryption = Aws::S3::Encryption::Client.new( encryption_key: OpenSSL::PKey::RSA.new(1024) ) # "1\n2\n3\n4\n5" pp s3_encryption.get_object( bucket: 'xxx', key: 'sample4.log', ).body.read s3 = Aws::S3::Client.new # "@\xEF-]@\xE5\xC7\u0015\x8DH'S\xB08\xCFB" pp s3.get_object( bucket: 'xxx', key: 'sample4.log', ).body.read
クライアントサイド暗号化 : KMS
KMS を使ってクライアントサイド暗号化をする例はうまく動かなかった.もう少し調査しないと...!
オマケ : Gitter
ドキュメントを読んでたら Gitter と連携してることに気付いた.Issue を立てるほどじゃないけど,サクッと聞きたいこともあるし,Gitter のカジュアルさは相性が良さそう!