Example code for the DynamoDB Encryption Client for Python
Note
Our client-side encryption library was renamed to AWS Database Encryption SDK. The following topic provides information on versions 1.x—2.x of the DynamoDB Encryption Client for Java and versions 1.x—3.x of the DynamoDB Encryption Client for Python. For more information, see AWS Database Encryption SDK for DynamoDB version support.
The following examples show you how to use the DynamoDB Encryption Client for Python to protect DynamoDB data in
your application. You can find more examples (and contribute your own) in the examples
Use the EncryptedTable client helper class
The following example shows you how to use the Direct KMS Provider with the EncryptedTable
client
helper class. This example uses the same cryptographic materials provider as the Use the item encryptor example that follows. However, it uses the
EncryptedTable
class instead of interacting directly with the lower-level item encryptor.
By comparing these examples, you can see the work that the client helper class does for you. This includes creating the DynamoDB encryption context and making sure the primary key attributes are always signed, but never encrypted. To create the encryption context and discover the primary key, the client helper classes call the DynamoDB DescribeTable operation. To run this code, you must have permission to call this operation.
See the complete code sample: aws_kms_encrypted_table.py
- Step 1: Create the table
-
Start by creating an instance of a standard DynamoDB table with the table name.
table_name='test-table' table = boto3.resource('dynamodb').Table(
table_name
) - Step 2: Create a cryptographic materials provider
-
Create an instance of the cryptographic materials provider (CMP) that you selected.
This example uses the Direct KMS Provider, but you can use any compatible CMP. To create a Direct KMS Provider, specify an AWS KMS key. This example uses the Amazon Resource Name (ARN) of the AWS KMS key, but you can use any valid key identifier.
kms_key_id='arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab' kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=
kms_key_id
) - Step 3: Create the attribute actions object
-
Attribute actions tell the item encryptor which actions to perform on each attribute of the item. The
AttributeActions
object in this example encrypts and signs all items except for thetest
attribute, which is ignored.Do not specify attribute actions for the primary key attributes when you use a client helper class. The
EncryptedTable
class signs, but never encrypts, the primary key attributes.actions = AttributeActions( default_action=CryptoAction.ENCRYPT_AND_SIGN, attribute_actions={'test': CryptoAction.DO_NOTHING} )
- Step 4: Create the encrypted table
-
Create the encrypted table using the standard table, the Direct KMS Provider, and the attribute actions. This step completes the configuration.
encrypted_table = EncryptedTable( table=table, materials_provider=kms_cmp, attribute_actions=actions )
- Step 5: Put the plaintext item in the table
-
When you call the
put_item
method on theencrypted_table
, your table items are transparently encrypted, signed, and added to your DynamoDB table.First, define the table item.
plaintext_item = { 'partition_attribute': 'value1', 'sort_attribute': 55 'example': 'data', 'numbers': 99, 'binary': Binary(b'\x00\x01\x02'), 'test': 'test-value' }
Then, put it in the table.
encrypted_table.put_item(Item=plaintext_item)
To get the item from the DynamoDB table in its encrypted form, call the get_item
method on the table
object. To get the decrypted item, call the
get_item
method on the encrypted_table
object.
Use the item encryptor
This example shows you how to interact directly with the item encryptor in the DynamoDB Encryption Client when encrypting table items, instead of using the client helper classes that interact with the item encryptor for you.
When you use this technique, you create the DynamoDB encryption context and configuration
object (CryptoConfig
) manually. Also, you encrypt the items in one call and put
them in your DynamoDB table in a separate call. This allows you to customize your
put_item
calls and use the DynamoDB Encryption Client to encrypt and sign structured data that is
never sent to DynamoDB.
This example uses the Direct KMS Provider, but you can use any compatible CMP.
See the complete code sample: aws_kms_encrypted_item.py
- Step 1: Create the table
-
Start by creating an instance of a standard DynamoDB table resource with the table name.
table_name='test-table' table = boto3.resource('dynamodb').Table(
table_name
) - Step 2: Create a cryptographic materials provider
-
Create an instance of the cryptographic materials provider (CMP) that you selected.
This example uses the Direct KMS Provider, but you can use any compatible CMP. To create a Direct KMS Provider, specify an AWS KMS key. This example uses the Amazon Resource Name (ARN) of the AWS KMS key, but you can use any valid key identifier.
kms_key_id='arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab' kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=
kms_key_id
) - Step 3: Use the TableInfo helper class
-
To get information about the table from DynamoDB, create an instance of the TableInfo helper class. When you work directly with the item encryptor, you need to create a
TableInfo
instance and call its methods. The client helper classes do this for you.The
refresh_indexed_attributes
method ofTableInfo
uses the DescribeTable DynamoDB operation to get real-time, accurate information about the table. This includes its primary key and its local and global secondary indexes. The caller needs to have permission to callDescribeTable
.table_info = TableInfo(name=
table_name
) table_info.refresh_indexed_attributes(table.meta.client) - Step 4: Create the DynamoDB encryption context
-
The DynamoDB encryption context contains information about the table structure and how it is encrypted and signed. This example creates a DynamoDB encryption context explicitly, because it interacts with the item encryptor. The client helper classes create the DynamoDB encryption context for you.
To get the partition key and sort key, you can use the properties of the TableInfo helper class.
index_key = { 'partition_attribute': 'value1', 'sort_attribute': 55 } encryption_context = EncryptionContext( table_name=
table_name
, partition_key_name=table_info.primary_index.partition, sort_key_name=table_info.primary_index.sort, attributes=dict_to_ddb(index_key) ) - Step 5: Create the attribute actions object
-
Attribute actions tell the item encryptor which actions to perform on each attribute of the item. The
AttributeActions
object in this example encrypts and signs all items except for the primary key attributes, which are signed, but not encrypted, and thetest
attribute, which is ignored.When you interact directly with the item encryptor and your default action is
ENCRYPT_AND_SIGN
, you must specify an alternative action for the primary key. You can use theset_index_keys
method, which usesSIGN_ONLY
for the primary key, or it usesDO_NOTHING
if it's the default action.To specify the primary key, this example uses the index keys in the TableInfo object, which is populated by a call to DynamoDB. This technique is safer than hard-coding primary key names.
actions = AttributeActions( default_action=CryptoAction.ENCRYPT_AND_SIGN, attribute_actions={'test': CryptoAction.DO_NOTHING} ) actions.set_index_keys(*table_info.protected_index_keys())
- Step 6: Create the configuration for the item
-
To configure the DynamoDB Encryption Client, use the objects that you just created in a CryptoConfig
configuration for the table item. The client helper classes create the CryptoConfig for you. crypto_config = CryptoConfig( materials_provider=kms_cmp, encryption_context=encryption_context, attribute_actions=actions )
- Step 7: Encrypt the item
-
This step encrypts and signs the item, but it doesn't put it in the DynamoDB table.
When you use a client helper class, your items are transparently encrypted and signed, and then added to your DynamoDB table when you call the
put_item
method of the helper class. When you use the item encryptor directly, the encrypt and put actions are independent.First, create a plaintext item.
plaintext_item = { 'partition_attribute': 'value1', 'sort_key': 55, 'example': 'data', 'numbers': 99, 'binary': Binary(b'\x00\x01\x02'), 'test': 'test-value' }
Then, encrypt and sign it. The
encrypt_python_item
method requires theCryptoConfig
configuration object.encrypted_item = encrypt_python_item(plaintext_item, crypto_config)
- Step 8: Put the item in the table
-
This step puts the encrypted and signed item in the DynamoDB table.
table.put_item(Item=encrypted_item)
To view the encrypted item, call the get_item
method on the original
table
object, instead of the encrypted_table
object. It gets the
item from the DynamoDB table without verifying and decrypting it.
encrypted_item = table.get_item(Key=partition_key)['Item']
The following image shows part of an example encrypted and signed table item.
The encrypted attribute values are binary data. The names and values of the primary key
attributes (partition_attribute
and sort_attribute
) and the
test
attribute remain in plaintext. The output also shows the attribute that
contains the signature (*amzn-ddb-map-sig*
) and the materials description attribute
(*amzn-ddb-map-desc*
).