Created
October 1, 2020 10:28
-
-
Save ritesh/efa756d8ba78d94055022360af6e2b13 to your computer and use it in GitHub Desktop.
DynamoDB Client Side encryption using the DDB Encryption SDK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"). You | |
# may not use this file except in compliance with the License. A copy of | |
# the License is located at | |
# | |
# http://aws.amazon.com/apache2.0/ | |
# | |
# or in the "license" file accompanying this file. This file is | |
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | |
# ANY KIND, either express or implied. See the License for the specific | |
# language governing permissions and limitations under the License. | |
from dynamodb_encryption_sdk.encrypted import CryptoConfig | |
from dynamodb_encryption_sdk.encrypted.client import EncryptedClient | |
from dynamodb_encryption_sdk.identifiers import CryptoAction | |
from dynamodb_encryption_sdk.encrypted import CryptoConfig | |
from dynamodb_encryption_sdk.material_providers.aws_kms import AwsKmsCryptographicMaterialsProvider | |
from dynamodb_encryption_sdk.structures import AttributeActions | |
import boto3 | |
from boto3.dynamodb.types import Binary | |
import uuid | |
from datetime import datetime | |
def encrypt_item(table_name, aws_cmk_id, index_key, plaintext_item, ignored_attributes): | |
"""Demonstrate use of EncryptedClient to transparently encrypt an item.""" | |
# Collect all of the attributes that will be encrypted (used later). | |
encrypted_attributes = set(plaintext_item.keys()) | |
# Collect all of the attributes that will not be encrypted (used later). | |
# Here, we leave out the index keys as we can't use them if they are encrypted client side! | |
unencrypted_attributes = set(index_key.keys()) | |
for attrib in ignored_attributes: | |
encrypted_attributes.remove(attrib) | |
unencrypted_attributes.add(attrib) | |
# Add the index pairs back to the item. | |
plaintext_item.update(index_key) | |
# Create a normal client. | |
client = boto3.client("dynamodb") | |
# Create a crypto materials provider using the specified AWS KMS key. | |
aws_kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=aws_cmk_id) | |
# Create attribute actions that tells the encrypted client to encrypt all attributes except one. | |
actions = AttributeActions( | |
default_action=CryptoAction.ENCRYPT_AND_SIGN, attribute_actions={x: CryptoAction.DO_NOTHING for x in unencrypted_attributes} | |
) | |
# Use these objects to create an encrypted client. | |
encrypted_client = EncryptedClient(client=client, materials_provider=aws_kms_cmp, attribute_actions=actions) | |
# Put the item to the table, using the encrypted client to transparently encrypt it. | |
encrypted_client.put_item(TableName=table_name, Item=plaintext_item) | |
# Get the encrypted item using the standard client. | |
encrypted_item = client.get_item(TableName=table_name, Key=index_key)["Item"] | |
return encrypted_item | |
def decrypt_item(table_name, aws_cmk_id, index_key, ignored_attributes): | |
"""Demonstrate use of EncryptedClient to transparently decrypt an item.""" | |
unencrypted_attributes = set(index_key.keys()) | |
for attrib in ignored_attributes: | |
unencrypted_attributes.add(attrib) | |
actions = AttributeActions ( | |
default_action = CryptoAction.ENCRYPT_AND_SIGN, attribute_actions={x: CryptoAction.DO_NOTHING for x in unencrypted_attributes} | |
) | |
aws_kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=aws_cmk_id) | |
client = boto3.client("dynamodb") | |
encrypted_client = EncryptedClient(client=client, materials_provider=aws_kms_cmp, attribute_actions = actions) | |
decrypted_item = encrypted_client.get_item(TableName=table_name, Key=index_key)["Item"] | |
return decrypted_item | |
if __name__ == '__main__': | |
index_key = {"CustomerID": {"S": uuid.uuid4().hex }} | |
plaintext_item = { | |
"DateOfLastContact": {"S": datetime.now().isoformat()}, | |
"ChatToken": {"S": "datadatadatadata"}, | |
"OtherMetadata": {"N": "99"}, | |
"BinaryField": {"B": b"\x00\x01\x02"}, | |
"leave me": {"S": "alone"}, # We want to ignore this attribute | |
} | |
# We will not encrypt or sign these attributes, everythign else gets encrypted and signed | |
ignored_attributes = ["leave me", "OtherMetadata"] | |
#Outputs from stack | |
table_name = "YOUR_TEST_DYNAMODB_TABLE_NAME" | |
aws_cmk_id = "AWS CMK ID FOR TESTING" | |
encrypted_item = encrypt_item(table_name, aws_cmk_id, index_key, plaintext_item, ignored_attributes) | |
print("encrypted item is {}".format(encrypted_item)) | |
decrypted_item = decrypt_item(table_name, aws_cmk_id, index_key, ignored_attributes) | |
print ("decrypted: is {}".format(decrypted_item)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment