|
| 1 | +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. |
| 2 | +# SPDX-License-Identifier: Apache-2.0 |
| 3 | +""" |
| 4 | +This example demonstrates a basic put/get roundtrip using the S3 Encryption Client |
| 5 | +with a KMS Keyring. |
| 6 | +
|
| 7 | +The KMS Keyring uses a symmetric KMS key to generate and decrypt data keys. |
| 8 | +The S3 Encryption Client encrypts the object before uploading to S3 and decrypts |
| 9 | +it on download, so the data is protected at rest. |
| 10 | +
|
| 11 | +This example: |
| 12 | +1. Creates a KMS Keyring with the provided KMS key ID |
| 13 | +2. Wraps a boto3 S3 client with the S3 Encryption Client |
| 14 | +3. Creates an encryption context bound to the S3 bucket and key |
| 15 | +4. Puts an encrypted object to S3 |
| 16 | +5. Gets and decrypts the object from S3 |
| 17 | +6. Verifies the decrypted plaintext matches the original |
| 18 | +
|
| 19 | +Here is an example KMS Key Policy statement that would validate the |
| 20 | +Encryption Context used in this example:: |
| 21 | +
|
| 22 | + Sid: RestrictToEncryptionContextBucket |
| 23 | + Effect: Allow |
| 24 | + Principal: |
| 25 | + AWS: "arn:aws:iam::<account-id>:role/<role-name>" |
| 26 | + Action: |
| 27 | + - kms:GenerateDataKey |
| 28 | + - kms:Decrypt |
| 29 | + Resource: "*" |
| 30 | + Condition: |
| 31 | + StringEquals: |
| 32 | + "kms:EncryptionContext:aws-s3-bucket": "<bucket>" |
| 33 | +""" |
| 34 | + |
| 35 | +from s3_encryption import S3EncryptionClient, S3EncryptionClientConfig |
| 36 | +from s3_encryption.materials.kms_keyring import KmsKeyring |
| 37 | + |
| 38 | +EXAMPLE_DATA: bytes = b"Hello, S3 Encryption Client!" |
| 39 | + |
| 40 | + |
| 41 | +def kms_keyring_put_get(s3_client, kms_client, kms_key_id: str, bucket: str, key: str): |
| 42 | + """Demonstrate an encrypt/decrypt cycle using a KMS Keyring with S3. |
| 43 | +
|
| 44 | + Args: |
| 45 | + s3_client: boto3 S3 client. |
| 46 | + kms_client: boto3 KMS client. |
| 47 | + kms_key_id: KMS key ARN or alias to use for encryption/decryption. |
| 48 | + bucket: S3 bucket name. |
| 49 | + key: S3 object key. |
| 50 | + """ |
| 51 | + # 1. Create a KMS Keyring. |
| 52 | + keyring = KmsKeyring(kms_client=kms_client, kms_key_id=kms_key_id) |
| 53 | + |
| 54 | + # 2. Wrap the S3 client with the S3 Encryption Client. |
| 55 | + # The default commitment policy is REQUIRE_ENCRYPT_REQUIRE_DECRYPT, |
| 56 | + # which enforces key-committing algorithm suites on both encrypt and decrypt. |
| 57 | + config = S3EncryptionClientConfig(keyring=keyring) |
| 58 | + s3ec = S3EncryptionClient(wrapped_s3_client=s3_client, config=config) |
| 59 | + |
| 60 | + # 3. Create an encryption context. |
| 61 | + # The encryption context is a set of key-value pairs that are bound to the ciphertext. |
| 62 | + # Including the bucket and key ensures the ciphertext is tied to this specific S3 object. |
| 63 | + # This will also be visible to KMS when evaluating key policies. |
| 64 | + # See the example KMS Key Policy in this module's docstring. |
| 65 | + # The encryption context is optional, but strongly recommended. |
| 66 | + encryption_context = { |
| 67 | + "aws-s3-bucket": bucket, |
| 68 | + "aws-s3-key": key, |
| 69 | + } |
| 70 | + |
| 71 | + # 4. Put an encrypted object. |
| 72 | + s3ec.put_object(Bucket=bucket, Key=key, Body=EXAMPLE_DATA, EncryptionContext=encryption_context) |
| 73 | + |
| 74 | + # 5. Get and decrypt the object. |
| 75 | + # If you specified an encryption context during encryption, |
| 76 | + # you must provide the same encryption context during decryption. |
| 77 | + response = s3ec.get_object(Bucket=bucket, Key=key, EncryptionContext=encryption_context) |
| 78 | + plaintext = response["Body"].read() |
| 79 | + |
| 80 | + # 6. Optional Verify the decrypted plaintext matches the original. |
| 81 | + assert plaintext == EXAMPLE_DATA, "Decrypted plaintext does not match original data" |
0 commit comments