LoginSignup
17
15

More than 3 years have passed since last update.

S3サーバサイドの暗号化とはなにか

Posted at

概要

  • S3のオブジェクトの暗号化といっても、サーバサイド暗号化にはいくつか種類がある。
  • ただ、どんな違いがあるのかよくわかっていない。
  • 試してみた。

対象

  • S3バケットのオブジェクトに暗号化をする要件があるが、いまいちサーバサイド暗号化の種類の理解不足なので、ちょっとかじりたい。という方。

暗号化の種類

SSE-S3

  • AmazonS3がデータ暗号化キーとマスター暗号化キーを管理
  • 暗号化の使用に追加料金はかかりません

SSE-KMS

  • AWSマネージド型キーまたは、カスタマー管理型のキーがありKMSでキーを管理
  • AWS Key Management Service の料金が適用

SSE-C

  • ユーザーが暗号化キーを管理

暗号化してみる

バケットを作成

  • 非サーバサイド暗号化バケット
  • SSE-S3でサーバサイド暗号化を行うバケット
  • SSE-KMS(AWSマネージド型キー)でサーバサイド暗号化を行うバケット
  • SSE-KMS(カスタマー管理型のキー)でサーバサイド暗号化を行うバケット

作成するテンプレート

template.yaml
AWSTemplateFormatVersion: '2010-09-09'

Resources:
  NonEncryptedBucket:
    Type: AWS::S3::Bucket
  EncryptedBucketBySSES3:
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: AES256
  EncryptedBucketBySSEKMS:
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: aws:kms

  KmsKey:
    Type: AWS::KMS::Key
    Properties:
      Description: 'Key created with S3ServerSideEncryptionDemo template.'
      KeyPolicy:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal: "*"
          Action: "kms:*"
          Resource: "*"
  EncryptedBucketByCustomerSSEKMS:
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            KMSMasterKeyID: !Ref KmsKey
            SSEAlgorithm: aws:kms

Outputs:
  NonEncryptedBucket:
    Value: !Ref NonEncryptedBucket
  EncryptedBucketBySSES3:
    Value: !Ref EncryptedBucketBySSES3
  EncryptedBucketBySSEKMS:
    Value: !Ref EncryptedBucketBySSEKMS
  EncryptedBucketByCustomerSSEKMS:
    Value: !Ref EncryptedBucketByCustomerSSEKMS

バケット作成

aws cloudformation create-stack \
    --stack-name s3-server-side-encryption-demo \
    --template-body file://template.yaml

バケットにファイルをアップロード

非暗号化バケット

NON_ENCRYPTED_BUCKET=$(aws cloudformation describe-stacks \
    --stack-name s3-server-side-encryption-demo \
    --query 'Stacks[].Outputs[?OutputKey==`NonEncryptedBucket`].OutputValue' \
    --output text)
aws s3api put-object \
    --bucket ${NON_ENCRYPTED_BUCKET} \
    --key sample.png \
    --body sample.png
  # {
  #     "ETag": "\"b420fe104fb7b48b5dcd12de92c444b8\""
  # }

SSE-S3暗号化バケット

暗号化をしないバケットへのアップロードと異なり、レスポンスからサーバサイド暗号化にAES256を使っていることが確認できます。

SSE_S3_ENCRYTED_BUCKET=$(aws cloudformation describe-stacks \
    --stack-name s3-server-side-encryption-demo \
    --query 'Stacks[].Outputs[?OutputKey==`EncryptedBucketBySSES3`].OutputValue' \
    --output text)
aws s3api put-object \
    --bucket ${SSE_S3_ENCRYTED_BUCKET} \
    --key sample.png \
    --body sample.png
  # {
  #     "ETag": "\"b420fe104fb7b48b5dcd12de92c444b8\"",
  #     "ServerSideEncryption": "AES256"
  # }

SSE-KMS暗号化バケット

このケースも、レスポンスからサーバサイド暗号化にKMSのキーを使っていることが確認できます。
KMSのキーを使っている場合、キーIDも確認できます。

SSE_KMS_ENCRYTED_BUCKET=$(aws cloudformation describe-stacks \
    --stack-name s3-server-side-encryption-demo \
    --query 'Stacks[].Outputs[?OutputKey==`EncryptedBucketBySSEKMS`].OutputValue' \
    --output text)
aws s3api put-object \
    --bucket ${SSE_KMS_ENCRYTED_BUCKET} \
    --key sample.png \
    --body sample.png
  # {
  #     "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:1234567890xx:key/8fa790e9-10f6-4d6c-bca1-d9cb5af6e899",
  #     "ETag": "\"8ef45fd3802ab4bb8a8071d2d8d59294\"",
  #     "ServerSideEncryption": "aws:kms"
  # }

KMSに作成したキーを利用しSSE-KMS暗号化バケット

ユーザ自身が作成したKMSのキーの場合も同様です。

CUSTOMER_SSE_KMS_ENCRYTED_BUCKET=$(aws cloudformation describe-stacks \
    --stack-name s3-server-side-encryption-demo \
    --query 'Stacks[].Outputs[?OutputKey==`EncryptedBucketByCustomerSSEKMS`].OutputValue' \
    --output text)
aws s3api put-object \
    --bucket ${CUSTOMER_SSE_KMS_ENCRYTED_BUCKET} \
    --key sample.png \
    --body sample.png
  # {
  #     "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:1234567890xx:key/a52093d0-b506-4861-87dc-c5cda681c92e",
  #     "ETag": "\"1e6befc82805e250db067fd5c648452f\"",
  #     "ServerSideEncryption": "aws:kms"
  # }

SSE-KMSの確認

SSE-KMSでサーバサイド暗号化したオブジェクトには、SSEKMSKeyIdが一緒にレスポンスが返ってくることが確認できることは上で述べました。
SSEKMSKeyIdからKMSのどのキーで暗号化が行われたのかを確認することで、このキーが「AWSマネージド型キー」なのか「カスタマー管理型のキー」なのか確認してみましょう。

SSE-KMS暗号化バケットで使用されたキー

SSEKMS_KEY_ID=$(aws s3api head-object \
    --bucket ${SSE_KMS_ENCRYTED_BUCKET} \
    --key sample.png \
    --query 'SSEKMSKeyId' \
    --output text)
aws kms describe-key --key-id ${SSEKMS_KEY_ID}
  # {
  #     "KeyMetadata": {
  #         "Origin": "AWS_KMS",
  #         "KeyId": "8fa790e9-10f6-4d6c-bca1-d9cb5af6e899",
  #         "Description": "Default master key that protects my S3 objects when no other key is defined",
  #         "KeyManager": "AWS",
  #         "Enabled": true,
  #         "KeyUsage": "ENCRYPT_DECRYPT",
  #         "KeyState": "Enabled",
  #         "CreationDate": "2018-09-05T06:35:48.668000+00:00",
  #         "Arn": "arn:aws:kms:ap-northeast-1:1234567890xx:key/8fa790e9-10f6-4d6c-bca1-d9cb5af6e899",
  #         "AWSAccountId": "1234567890xx"
  #     }
  # }

KeyManager : AWS となっていることから、AWSマネージド型キーを使っていることが確認できます。

KMSに作成したキーを利用しSSE-KMS暗号化バケットで使用されたキー

CUSTOMER_SSEKMS_KEY_ID=$(aws s3api head-object \
    --bucket ${CUSTOMER_SSE_KMS_ENCRYTED_BUCKET} \
    --key sample.png \
    --query 'SSEKMSKeyId' \
    --output text)
aws kms describe-key --key-id ${CUSTOMER_SSEKMS_KEY_ID}
  # {
  #     "KeyMetadata": {
  #         "Origin": "AWS_KMS",
  #         "KeyId": "a52093d0-b506-4861-87dc-c5cda681c92e",
  #         "Description": "Key created with S3ServerSideEncryptionDemo template.",
  #         "KeyManager": "CUSTOMER",
  #         "Enabled": true,
  #         "KeyUsage": "ENCRYPT_DECRYPT",
  #         "KeyState": "Enabled",
  #         "CreationDate": "2019-11-15T13:51:24.941000+00:00",
  #         "Arn": "arn:aws:kms:ap-northeast-1:1234567890xx:key/a52093d0-b506-4861-87dc-c5cda681c92e",
  #         "AWSAccountId": "1234567890xx"
  #     }
  # }

KeyManager : CUSTOMER となっていることから、カスタマー管理型のキーを使っていることが確認できます。

これはテンプレートの AWS::KMS::Key で作成されたキーです。

通常、KMSによる暗号化を指示した場合、デフォルトでは、KMS(AWS Key Management Service)のAWSマネージド型のキーを利用し暗号化を行うが、ユーザ自身がKMSで鍵を作成し、サーバサイド暗号化のキーに利用することが出来ることも確認できました。

非暗号化バケットにサーバサイド暗号化を指定してファイルをアップロード

上記では、バケット自体にサーバサイド暗号化の設定をしているバケットに対して、ファイルをアップロードする動作検証を行いました。
他に、サーバサイド暗号化の設定をしていないバケットに対して、ファイルのアップロード時にサーバサイド暗号化の指定をすることも可能です。

サーバサイド暗号化にSSE-S3を指定してアップロード

aws s3api put-object \
    --bucket ${NON_ENCRYPTED_BUCKET} \
    --key sample_by_SSE-S3.png \
    --body sample.png \
    --server-side-encryption AES256
  # {
  #     "ETag": "\"b420fe104fb7b48b5dcd12de92c444b8\"",
  #     "ServerSideEncryption": "AES256"
  # }

サーバサイド暗号化にSSE-KMSを指定してアップロード

aws s3api put-object \
    --bucket ${NON_ENCRYPTED_BUCKET} \
    --key sample_by_SSE-KMS.png \
    --body sample.png \
    --server-side-encryption aws:kms
  # {
  #     "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:1234567890xx:key/8fa790e9-10f6-4d6c-bca1-d9cb5af6e899",
  #     "ETag": "\"cebd51529c2fcd566e1724e763047c23\"",
  #     "ServerSideEncryption": "aws:kms"
  # }

サーバサイド暗号化にKMSに作成したキーでSSE-KMS暗号化を指定してアップロード

aws s3api put-object \
    --bucket ${NON_ENCRYPTED_BUCKET} \
    --key sample_by_CustomerSSE-KMS.png \
    --body sample.png \
    --server-side-encryption aws:kms \
    --ssekms-key-id ${CUSTOMER_SSEKMS_KEY_ID}
  # {
  #     "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:1234567890xx:key/a52093d0-b506-4861-87dc-c5cda681c92e",
  #     "ETag": "\"e9a3aa7b8af5dd8522edd316c64b46f3\"",
  #     "ServerSideEncryption": "aws:kms"
  # }

ユーザが生成したキーを指定してアップロード(SSE-C)

また、暗号化キーをユーザ自身で管理し暗号化することも可能です。

SSE_CUSTOMER_KEY=$(cat /dev/urandom | base64 -i | fold -w 32 | head -n 1)
echo ${SSE_CUSTOMER_KEY}
  # bKNQl8YfSwa7eKpxSpuamVc+90MQ5BHC

aws s3api put-object \
    --bucket ${NON_ENCRYPTED_BUCKET} \
    --key sample_by_SSE-C.png \
    --body sample.png \
    --sse-customer-algorithm AES256 \
    --sse-customer-key ${SSE_CUSTOMER_KEY}
  # {
  #     "SSECustomerKeyMD5": "rgDjryTvO47GvZmftTvtPw==",
  #     "SSECustomerAlgorithm": "AES256",
  #     "ETag": "\"66aae60ae1a0dd574cf119b899be7463\""
  # }

SSM-Cで暗号化したファイルのダウンロード

暗号化キーをユーザ自身で管理する場合、バケットからオブジェクトを取得する際に、他のサーバサード暗号化の取得方法と異なります。

aws s3api head-object \
    --bucket ${NON_ENCRYPTED_BUCKET} \
    --key sample_by_SSE-C.png
  # 
  # An error occurred (400) when calling the HeadObject operation: Bad Request

オブジェクトを取得する場合は、鍵を指定してあげる必要があるので、注意が必要です。

aws s3api head-object \
    --bucket ${NON_ENCRYPTED_BUCKET} \
    --key sample_by_SSE-C.png \
    --sse-customer-algorithm AES256 \
    --sse-customer-key ${SSE_CUSTOMER_KEY}
  # {
  #     "AcceptRanges": "bytes",
  #     "ContentType": "binary/octet-stream",
  #     "LastModified": "2019-11-15T14:30:41+00:00",
  #     "ContentLength": 178061,
  #     "SSECustomerAlgorithm": "AES256",
  #     "ETag": "\"66aae60ae1a0dd574cf119b899be7463\"",
  #     "SSECustomerKeyMD5": "rgDjryTvO47GvZmftTvtPw==",
  #     "Metadata": {}
  # }

さいごに

一般的にはSSM-S3でサーバサイドの暗号化は事足りるものだと思います(コスト的にも)。
ただ利用シーンや要件によっては、検証したサーバサイド暗号化が必要になるのかと思います。
その際の、参考になれば。

検証したテンプレートのリポジトリは S3ServerSideEncryptionDemo になります。

17
15
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
17
15