def client_cycle_single_item_check(materials_provider, initial_actions, initial_item, table_name, region_name=None): check_attribute_actions = initial_actions.copy() check_attribute_actions.set_index_keys(*list(TEST_KEY.keys())) item = initial_item.copy() item.update(TEST_KEY) ddb_item = dict_to_ddb(item) ddb_key = dict_to_ddb(TEST_KEY) kwargs = {} if region_name is not None: kwargs["region_name"] = region_name client = boto3.client("dynamodb", **kwargs) e_client = EncryptedClient(client=client, materials_provider=materials_provider, attribute_actions=initial_actions) _put_result = e_client.put_item(TableName=table_name, Item=ddb_item) # noqa encrypted_result = client.get_item(TableName=table_name, Key=ddb_key, ConsistentRead=True) check_encrypted_item(item, ddb_to_dict(encrypted_result["Item"]), check_attribute_actions) decrypted_result = e_client.get_item(TableName=table_name, Key=ddb_key, ConsistentRead=True) assert ddb_to_dict(decrypted_result["Item"]) == item e_client.delete_item(TableName=table_name, Key=ddb_key) del item del check_attribute_actions
def encrypt_item(table_name, aws_cmk_id): """Demonstrate use of EncryptedClient to transparently encrypt an item.""" index_key = {"partition_attribute": {"S": "is this"}, "sort_attribute": {"N": "55"}} plaintext_item = { "example": {"S": "data"}, "some numbers": {"N": "99"}, "and some binary": {"B": b"\x00\x01\x02"}, "leave me": {"S": "alone"}, # We want to ignore this attribute } # Collect all of the attributes that will be encrypted (used later). encrypted_attributes = set(plaintext_item.keys()) encrypted_attributes.remove("leave me") # Collect all of the attributes that will not be encrypted (used later). unencrypted_attributes = set(index_key.keys()) unencrypted_attributes.add("leave me") # Add the index pairs 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={"leave me": CryptoAction.DO_NOTHING} ) # 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"] # Get the item using the encrypted client, transparently decyrpting it. decrypted_item = encrypted_client.get_item(TableName=table_name, Key=index_key)["Item"] # Verify that all of the attributes are different in the encrypted item for name in encrypted_attributes: assert encrypted_item[name] != plaintext_item[name] assert decrypted_item[name] == plaintext_item[name] # Verify that all of the attributes that should not be encrypted were not. for name in unencrypted_attributes: assert decrypted_item[name] == encrypted_item[name] == plaintext_item[name] # Clean up the item encrypted_client.delete_item(TableName=table_name, Key=index_key)
def encrypt_item(table_name, cmk_mrk_arn_first_region, cmk_mrk_arn_second_region): """Demonstrate use of Multi-Region Keys with DynamoDB Encryption Client. This example encrypts an item with a Multi-Region Key in one region and decrypts it in another region. It assumes that you have a Dynamo DB Global table in two regions, as well as a KMS Multi-Region Key replicated to these regions. """ index_key = { "partition_attribute": { "S": "is this" }, "sort_attribute": { "N": "55" } } plaintext_item = { "example": { "S": "data" }, "some numbers": { "N": "99" }, "and some binary": { "B": b"\x00\x01\x02" }, "leave me": { "S": "alone" }, # We want to ignore this attribute } # Collect all of the attributes that will be encrypted (used later). encrypted_attributes = set(plaintext_item.keys()) encrypted_attributes.remove("leave me") # Collect all of the attributes that will not be encrypted (used later). unencrypted_attributes = set(index_key.keys()) unencrypted_attributes.add("leave me") # Add the index pairs to the item. plaintext_item.update(index_key) # Create attribute actions that tells the encrypted client to encrypt all attributes except one. actions = AttributeActions( default_action=CryptoAction.ENCRYPT_AND_SIGN, attribute_actions={"leave me": CryptoAction.DO_NOTHING}) # Create a DDB client and KMS crypto materials provider in the first region using the specified AWS KMS key. split_arn = cmk_mrk_arn_first_region.split(":") encryption_region = split_arn[3] ddb_client = boto3.client("dynamodb", region_name=encryption_region) encryption_cmp = AwsKmsCryptographicMaterialsProvider( key_id=cmk_mrk_arn_first_region) # Use these objects to create an encrypted client. encryption_client = EncryptedClient(client=ddb_client, materials_provider=encryption_cmp, attribute_actions=actions) # Put the item to the table, using the encrypted client to transparently encrypt it. encryption_client.put_item(TableName=table_name, Item=plaintext_item) # Create a DDB client and KMS crypto materials provider in the second region split_arn = cmk_mrk_arn_second_region.split(":") decryption_region = split_arn[3] decryption_cmp = AwsKmsCryptographicMaterialsProvider( key_id=cmk_mrk_arn_second_region) ddb_client = boto3.client("dynamodb", region_name=decryption_region) # Use these objects to create an encrypted client. decryption_client = EncryptedClient(client=ddb_client, materials_provider=decryption_cmp, attribute_actions=actions) # DDB Global Table replication takes some time. Sleep for a moment to give the item a chance to replicate to the # second region time.sleep(1) # Get the item from the second region, transparently decrypting it. This allows you to avoid a cross-region KMS # call to the first region if your application is running in the second region decrypted_item = decryption_client.get_item(TableName=table_name, Key=index_key)["Item"] # Verify that the decryption successfully retrieved the original plaintext for name in encrypted_attributes: assert plaintext_item[name] == decrypted_item[name] # Clean up the item encryption_client.delete_item(TableName=table_name, Key=index_key)