Skip to content

Commit 773ad87

Browse files
authored
Merge pull request #50 from mattsb42-aws/more-examples
add wrapped and most recent provider examples and tests
2 parents aa910e7 + a56a19d commit 773ad87

5 files changed

+382
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
"""Example showing use of MostRecentProvider backed by a MetaStore using an AWS KMS CMP,
14+
with EncryptedTable.
15+
"""
16+
import boto3
17+
from boto3.dynamodb.types import Binary
18+
from dynamodb_encryption_sdk.encrypted.table import EncryptedTable
19+
from dynamodb_encryption_sdk.identifiers import CryptoAction
20+
from dynamodb_encryption_sdk.material_providers.aws_kms import AwsKmsCryptographicMaterialsProvider
21+
from dynamodb_encryption_sdk.material_providers.most_recent import MostRecentProvider
22+
from dynamodb_encryption_sdk.material_providers.store.meta import MetaStore
23+
from dynamodb_encryption_sdk.structures import AttributeActions
24+
25+
26+
def encrypt_item(table_name, aws_cmk_id, meta_table_name, material_name):
27+
"""Demonstrate use of EncryptedTable to transparently encrypt an item."""
28+
index_key = {
29+
'partition_attribute': 'is this',
30+
'sort_attribute': 55
31+
}
32+
plaintext_item = {
33+
'example': 'data',
34+
'some numbers': 99,
35+
'and some binary': Binary(b'\x00\x01\x02'),
36+
'leave me': 'alone' # We want to ignore this attribute
37+
}
38+
# Collect all of the attributes that will be encrypted (used later).
39+
encrypted_attributes = set(plaintext_item.keys())
40+
encrypted_attributes.remove('leave me')
41+
# Collect all of the attributes that will not be encrypted (used later).
42+
unencrypted_attributes = set(index_key.keys())
43+
unencrypted_attributes.add('leave me')
44+
# Add the index pairs to the item.
45+
plaintext_item.update(index_key)
46+
47+
# Create a normal table resource for the meta store.
48+
meta_table = boto3.resource('dynamodb').Table(meta_table_name)
49+
# Create a crypto materials provider for the meta store using the specified AWS KMS key.
50+
aws_kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=aws_cmk_id)
51+
# Create a meta store using the AWS KMS crypto materials provider.
52+
meta_store = MetaStore(
53+
table=meta_table,
54+
materials_provider=aws_kms_cmp
55+
)
56+
# Create a most recent provider using the meta store.
57+
most_recent_cmp = MostRecentProvider(
58+
provider_store=meta_store,
59+
material_name=material_name,
60+
version_ttl=600.0 # Check for a new material version every five minutes.
61+
)
62+
# Create a normal table resource.
63+
table = boto3.resource('dynamodb').Table(table_name)
64+
# Create attribute actions that tells the encrypted table to encrypt all attributes except one.
65+
actions = AttributeActions(
66+
default_action=CryptoAction.ENCRYPT_AND_SIGN,
67+
attribute_actions={
68+
'leave me': CryptoAction.DO_NOTHING
69+
}
70+
)
71+
# Use these objects to create an encrypted table resource.
72+
encrypted_table = EncryptedTable(
73+
table=table,
74+
materials_provider=most_recent_cmp,
75+
attribute_actions=actions
76+
)
77+
78+
# Put the item to the table, using the encrypted table resource to transparently encrypt it.
79+
encrypted_table.put_item(Item=plaintext_item)
80+
81+
# Get the encrypted item using the standard table resource.
82+
encrypted_item = table.get_item(Key=index_key)['Item']
83+
84+
# Get the item using the encrypted table resource, transparently decyrpting it.
85+
decrypted_item = encrypted_table.get_item(Key=index_key)['Item']
86+
87+
# Verify that all of the attributes are different in the encrypted item
88+
for name in encrypted_attributes:
89+
assert encrypted_item[name] != plaintext_item[name]
90+
assert decrypted_item[name] == plaintext_item[name]
91+
92+
# Verify that all of the attributes that should not be encrypted were not.
93+
for name in unencrypted_attributes:
94+
assert decrypted_item[name] == encrypted_item[name] == plaintext_item[name]
95+
96+
# Clean up the item
97+
encrypted_table.delete_item(Key=index_key)
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
"""Example showing use of a RSA wrapped CMP with EncryptedTable."""
14+
import boto3
15+
from boto3.dynamodb.types import Binary
16+
from dynamodb_encryption_sdk.delegated_keys.jce import JceNameLocalDelegatedKey
17+
from dynamodb_encryption_sdk.encrypted.table import EncryptedTable
18+
from dynamodb_encryption_sdk.identifiers import CryptoAction, EncryptionKeyType, KeyEncodingType
19+
from dynamodb_encryption_sdk.material_providers.wrapped import WrappedCryptographicMaterialsProvider
20+
from dynamodb_encryption_sdk.structures import AttributeActions
21+
22+
23+
def encrypt_item(table_name, rsa_wrapping_private_key_bytes, rsa_signing_private_key_bytes):
24+
"""Demonstrate use of EncryptedTable to transparently encrypt an item."""
25+
index_key = {
26+
'partition_attribute': 'is this',
27+
'sort_attribute': 55
28+
}
29+
plaintext_item = {
30+
'example': 'data',
31+
'some numbers': 99,
32+
'and some binary': Binary(b'\x00\x01\x02'),
33+
'leave me': 'alone' # We want to ignore this attribute
34+
}
35+
# Collect all of the attributes that will be encrypted (used later).
36+
encrypted_attributes = set(plaintext_item.keys())
37+
encrypted_attributes.remove('leave me')
38+
# Collect all of the attributes that will not be encrypted (used later).
39+
unencrypted_attributes = set(index_key.keys())
40+
unencrypted_attributes.add('leave me')
41+
# Add the index pairs to the item.
42+
plaintext_item.update(index_key)
43+
44+
# Create a normal table resource.
45+
table = boto3.resource('dynamodb').Table(table_name)
46+
# Create a crypto materials provider using the provided wrapping and signing keys.
47+
# We show private keys used here, but public keys could be used as well, allowing
48+
# only wrapping or signature verification.
49+
wrapping_key = JceNameLocalDelegatedKey(
50+
key=rsa_wrapping_private_key_bytes,
51+
algorithm='RSA',
52+
key_type=EncryptionKeyType.PRIVATE,
53+
key_encoding=KeyEncodingType.DER
54+
)
55+
signing_key = JceNameLocalDelegatedKey(
56+
key=rsa_signing_private_key_bytes,
57+
algorithm='SHA512withRSA',
58+
key_type=EncryptionKeyType.PRIVATE,
59+
key_encoding=KeyEncodingType.DER
60+
)
61+
wrapped_cmp = WrappedCryptographicMaterialsProvider(
62+
wrapping_key=wrapping_key,
63+
unwrapping_key=wrapping_key,
64+
signing_key=signing_key
65+
)
66+
# Create attribute actions that tells the encrypted table to encrypt all attributes except one.
67+
actions = AttributeActions(
68+
default_action=CryptoAction.ENCRYPT_AND_SIGN,
69+
attribute_actions={
70+
'leave me': CryptoAction.DO_NOTHING
71+
}
72+
)
73+
# Use these objects to create an encrypted table resource.
74+
encrypted_table = EncryptedTable(
75+
table=table,
76+
materials_provider=wrapped_cmp,
77+
attribute_actions=actions
78+
)
79+
80+
# Put the item to the table, using the encrypted table resource to transparently encrypt it.
81+
encrypted_table.put_item(Item=plaintext_item)
82+
83+
# Get the encrypted item using the standard table resource.
84+
encrypted_item = table.get_item(Key=index_key)['Item']
85+
86+
# Get the item using the encrypted table resource, transparently decyrpting it.
87+
decrypted_item = encrypted_table.get_item(Key=index_key)['Item']
88+
89+
# Verify that all of the attributes are different in the encrypted item
90+
for name in encrypted_attributes:
91+
assert encrypted_item[name] != plaintext_item[name]
92+
assert decrypted_item[name] == plaintext_item[name]
93+
94+
# Verify that all of the attributes that should not be encrypted were not.
95+
for name in unencrypted_attributes:
96+
assert decrypted_item[name] == encrypted_item[name] == plaintext_item[name]
97+
98+
# Clean up the item
99+
encrypted_table.delete_item(Key=index_key)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
"""Example showing use of a symmetric wrapped CMP with EncryptedTable."""
14+
import boto3
15+
from boto3.dynamodb.types import Binary
16+
from dynamodb_encryption_sdk.delegated_keys.jce import JceNameLocalDelegatedKey
17+
from dynamodb_encryption_sdk.encrypted.table import EncryptedTable
18+
from dynamodb_encryption_sdk.identifiers import CryptoAction, EncryptionKeyType, KeyEncodingType
19+
from dynamodb_encryption_sdk.material_providers.wrapped import WrappedCryptographicMaterialsProvider
20+
from dynamodb_encryption_sdk.structures import AttributeActions
21+
22+
23+
def encrypt_item(table_name, aes_wrapping_key_bytes, hmac_signing_key_bytes):
24+
"""Demonstrate use of EncryptedTable to transparently encrypt an item."""
25+
index_key = {
26+
'partition_attribute': 'is this',
27+
'sort_attribute': 55
28+
}
29+
plaintext_item = {
30+
'example': 'data',
31+
'some numbers': 99,
32+
'and some binary': Binary(b'\x00\x01\x02'),
33+
'leave me': 'alone' # We want to ignore this attribute
34+
}
35+
# Collect all of the attributes that will be encrypted (used later).
36+
encrypted_attributes = set(plaintext_item.keys())
37+
encrypted_attributes.remove('leave me')
38+
# Collect all of the attributes that will not be encrypted (used later).
39+
unencrypted_attributes = set(index_key.keys())
40+
unencrypted_attributes.add('leave me')
41+
# Add the index pairs to the item.
42+
plaintext_item.update(index_key)
43+
44+
# Create a normal table resource.
45+
table = boto3.resource('dynamodb').Table(table_name)
46+
# Create a crypto materials provider using the provided wrapping and signing keys.
47+
wrapping_key = JceNameLocalDelegatedKey(
48+
key=aes_wrapping_key_bytes,
49+
algorithm='AES',
50+
key_type=EncryptionKeyType.SYMMETRIC,
51+
key_encoding=KeyEncodingType.RAW
52+
)
53+
signing_key = JceNameLocalDelegatedKey(
54+
key=hmac_signing_key_bytes,
55+
algorithm='HmacSHA512',
56+
key_type=EncryptionKeyType.SYMMETRIC,
57+
key_encoding=KeyEncodingType.RAW
58+
)
59+
wrapped_cmp = WrappedCryptographicMaterialsProvider(
60+
wrapping_key=wrapping_key,
61+
unwrapping_key=wrapping_key,
62+
signing_key=signing_key
63+
)
64+
# Create attribute actions that tells the encrypted table to encrypt all attributes except one.
65+
actions = AttributeActions(
66+
default_action=CryptoAction.ENCRYPT_AND_SIGN,
67+
attribute_actions={
68+
'leave me': CryptoAction.DO_NOTHING
69+
}
70+
)
71+
# Use these objects to create an encrypted table resource.
72+
encrypted_table = EncryptedTable(
73+
table=table,
74+
materials_provider=wrapped_cmp,
75+
attribute_actions=actions
76+
)
77+
78+
# Put the item to the table, using the encrypted table resource to transparently encrypt it.
79+
encrypted_table.put_item(Item=plaintext_item)
80+
81+
# Get the encrypted item using the standard table resource.
82+
encrypted_item = table.get_item(Key=index_key)['Item']
83+
84+
# Get the item using the encrypted table resource, transparently decyrpting it.
85+
decrypted_item = encrypted_table.get_item(Key=index_key)['Item']
86+
87+
# Verify that all of the attributes are different in the encrypted item
88+
for name in encrypted_attributes:
89+
assert encrypted_item[name] != plaintext_item[name]
90+
assert decrypted_item[name] == plaintext_item[name]
91+
92+
# Verify that all of the attributes that should not be encrypted were not.
93+
for name in unencrypted_attributes:
94+
assert decrypted_item[name] == encrypted_item[name] == plaintext_item[name]
95+
96+
# Clean up the item
97+
encrypted_table.delete_item(Key=index_key)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
"""Test most recent provider examples."""
14+
import os
15+
import sys
16+
sys.path.extend([ # noqa
17+
os.sep.join([os.path.dirname(__file__), '..', '..', 'test', 'integration']),
18+
os.sep.join([os.path.dirname(__file__), '..', 'src'])
19+
])
20+
import uuid
21+
22+
import boto3
23+
import pytest
24+
25+
from dynamodb_encryption_sdk.material_providers.store.meta import MetaStore
26+
import most_recent_provider_encrypted_table # noqa
27+
from integration_test_utils import cmk_arn, ddb_table_name # noqa pylint: disable=unused-import
28+
29+
pytestmark = [pytest.mark.examples]
30+
31+
32+
def test_most_recent_encrypted_table(ddb_table_name, cmk_arn):
33+
# define random new names for material and metastore table
34+
meta_table_name = 'meta-table-{}'.format(uuid.uuid4())
35+
material_name = 'material-{}'.format(uuid.uuid4())
36+
37+
# create the metastore table
38+
client = boto3.client('dynamodb')
39+
MetaStore.create_table(client, meta_table_name, 10, 10)
40+
waiter = client.get_waiter('table_exists')
41+
waiter.wait(TableName=meta_table_name)
42+
43+
# run the actual test
44+
most_recent_provider_encrypted_table.encrypt_item(ddb_table_name, cmk_arn, meta_table_name, material_name)
45+
46+
# clean up the meta store table
47+
client.delete_table(TableName=meta_table_name)
48+
waiter = client.get_waiter('table_not_exists')
49+
waiter.wait(TableName=meta_table_name)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
"""Test ``wrapped_*_encrypted_*`` examples."""
14+
import os
15+
import sys
16+
sys.path.extend([ # noqa
17+
os.sep.join([os.path.dirname(__file__), '..', '..', 'test', 'integration']),
18+
os.sep.join([os.path.dirname(__file__), '..', 'src'])
19+
])
20+
21+
import pytest
22+
23+
from dynamodb_encryption_sdk.delegated_keys.jce import JceNameLocalDelegatedKey
24+
import wrapped_rsa_encrypted_table # noqa
25+
import wrapped_symmetric_encrypted_table # noqa
26+
from integration_test_utils import ddb_table_name # noqa pylint: disable=unused-import
27+
28+
pytestmark = [pytest.mark.examples]
29+
30+
31+
def test_wrapped_rsa_encrypted_table(ddb_table_name):
32+
wrapping_key_bytes = JceNameLocalDelegatedKey.generate('RSA', 4096).key
33+
signing_key_bytes = JceNameLocalDelegatedKey.generate('SHA512withRSA', 4096).key
34+
wrapped_rsa_encrypted_table.encrypt_item(ddb_table_name, wrapping_key_bytes, signing_key_bytes)
35+
36+
37+
def test_wrapped_symmetric_encrypted_table(ddb_table_name):
38+
wrapping_key_bytes = JceNameLocalDelegatedKey.generate('AES', 256).key
39+
signing_key_bytes = JceNameLocalDelegatedKey.generate('HmacSHA512', 256).key
40+
wrapped_symmetric_encrypted_table.encrypt_item(ddb_table_name, wrapping_key_bytes, signing_key_bytes)

0 commit comments

Comments
 (0)