16
16
import base64
17
17
import copy
18
18
import itertools
19
- import logging
20
19
import os
21
20
from collections import defaultdict
22
21
from decimal import Decimal
23
22
24
23
import boto3
25
24
import pytest
26
- import six
27
25
from boto3 .dynamodb .types import Binary
26
+ from botocore .exceptions import NoRegionError
28
27
from moto import mock_dynamodb2
29
28
30
29
from dynamodb_encryption_sdk .delegated_keys .jce import JceNameLocalDelegatedKey
34
33
from dynamodb_encryption_sdk .encrypted .table import EncryptedTable
35
34
from dynamodb_encryption_sdk .identifiers import CryptoAction
36
35
from dynamodb_encryption_sdk .internal .identifiers import ReservedAttributes
36
+ from dynamodb_encryption_sdk .material_providers .most_recent import MostRecentProvider
37
37
from dynamodb_encryption_sdk .material_providers .static import StaticCryptographicMaterialsProvider
38
38
from dynamodb_encryption_sdk .material_providers .store .meta import MetaStore
39
39
from dynamodb_encryption_sdk .material_providers .wrapped import WrappedCryptographicMaterialsProvider
44
44
RUNNING_IN_TRAVIS = "TRAVIS" in os .environ
45
45
_DELEGATED_KEY_CACHE = defaultdict (lambda : defaultdict (dict ))
46
46
TEST_TABLE_NAME = "my_table"
47
+ TEST_REGION_NAME = "us-west-2"
47
48
TEST_INDEX = {
48
49
"partition_attribute" : {"type" : "S" , "value" : "test_value" },
49
50
"sort_attribute" : {"type" : "N" , "value" : Decimal ("99.233" )},
50
51
}
51
- SECONARY_INDEX = {
52
+ SECONDARY_INDEX = {
52
53
"secondary_index_1" : {"type" : "B" , "value" : Binary (b"\x00 \x01 \x02 " )},
53
54
"secondary_index_2" : {"type" : "S" , "value" : "another_value" },
54
55
}
76
77
77
78
@pytest .fixture
78
79
def example_table ():
79
- mock_dynamodb2 ().start ()
80
- ddb = boto3 .client ("dynamodb" , region_name = "us-west-2" )
80
+ mock_dynamodb2 ().start (reset = False )
81
+ ddb = boto3 .client ("dynamodb" , region_name = TEST_REGION_NAME )
81
82
ddb .create_table (
82
83
TableName = TEST_TABLE_NAME ,
83
84
KeySchema = [
@@ -95,9 +96,9 @@ def example_table():
95
96
96
97
97
98
@pytest .fixture
98
- def table_with_local_seconary_indexes ():
99
- mock_dynamodb2 ().start ()
100
- ddb = boto3 .client ("dynamodb" , region_name = "us-west-2" )
99
+ def table_with_local_secondary_indexes ():
100
+ mock_dynamodb2 ().start (reset = False )
101
+ ddb = boto3 .client ("dynamodb" , region_name = TEST_REGION_NAME )
101
102
ddb .create_table (
102
103
TableName = TEST_TABLE_NAME ,
103
104
KeySchema = [
@@ -118,7 +119,7 @@ def table_with_local_seconary_indexes():
118
119
],
119
120
AttributeDefinitions = [
120
121
{"AttributeName" : name , "AttributeType" : value ["type" ]}
121
- for name , value in list (TEST_INDEX .items ()) + list (SECONARY_INDEX .items ())
122
+ for name , value in list (TEST_INDEX .items ()) + list (SECONDARY_INDEX .items ())
122
123
],
123
124
ProvisionedThroughput = {"ReadCapacityUnits" : 100 , "WriteCapacityUnits" : 100 },
124
125
)
@@ -128,9 +129,9 @@ def table_with_local_seconary_indexes():
128
129
129
130
130
131
@pytest .fixture
131
- def table_with_global_seconary_indexes ():
132
- mock_dynamodb2 ().start ()
133
- ddb = boto3 .client ("dynamodb" , region_name = "us-west-2" )
132
+ def table_with_global_secondary_indexes ():
133
+ mock_dynamodb2 ().start (reset = False )
134
+ ddb = boto3 .client ("dynamodb" , region_name = TEST_REGION_NAME )
134
135
ddb .create_table (
135
136
TableName = TEST_TABLE_NAME ,
136
137
KeySchema = [
@@ -153,7 +154,7 @@ def table_with_global_seconary_indexes():
153
154
],
154
155
AttributeDefinitions = [
155
156
{"AttributeName" : name , "AttributeType" : value ["type" ]}
156
- for name , value in list (TEST_INDEX .items ()) + list (SECONARY_INDEX .items ())
157
+ for name , value in list (TEST_INDEX .items ()) + list (SECONDARY_INDEX .items ())
157
158
],
158
159
ProvisionedThroughput = {"ReadCapacityUnits" : 100 , "WriteCapacityUnits" : 100 },
159
160
)
@@ -650,22 +651,100 @@ def client_cycle_batch_items_check_paginators(
650
651
651
652
652
653
def build_metastore ():
653
- client = boto3 .client ("dynamodb" , region_name = "us-west-2" )
654
+ client = boto3 .client ("dynamodb" , region_name = TEST_REGION_NAME )
654
655
table_name = base64 .urlsafe_b64encode (os .urandom (32 )).decode ("utf-8" ).replace ("=" , "." )
655
656
656
657
MetaStore .create_table (client , table_name , 1 , 1 )
657
658
waiter = client .get_waiter ("table_exists" )
658
659
waiter .wait (TableName = table_name )
659
660
660
- table = boto3 .resource ("dynamodb" , region_name = "us-west-2" ).Table (table_name )
661
- yield MetaStore (table , build_static_jce_cmp ("AES" , 256 , "HmacSHA256" , 256 ))
661
+ table = boto3 .resource ("dynamodb" , region_name = TEST_REGION_NAME ).Table (table_name )
662
+ return MetaStore (table , build_static_jce_cmp ("AES" , 256 , "HmacSHA256" , 256 )), table_name
662
663
664
+
665
+ def delete_metastore (table_name ):
666
+ client = boto3 .client ("dynamodb" , region_name = TEST_REGION_NAME )
663
667
client .delete_table (TableName = table_name )
664
- waiter = client .get_waiter ("table_not_exists" )
665
- waiter .wait (TableName = table_name )
668
+ # It sometimes takes a long time to delete a table.
669
+ # If hanging, asynchronously deleting tables becomes an issue,
670
+ # come back to this.
671
+ # Otherwise, let's just let them take care of themselves.
672
+ # waiter = client.get_waiter("table_not_exists")
673
+ # waiter.wait(TableName=table_name)
666
674
667
675
668
676
@pytest .fixture
669
677
def mock_metastore ():
670
678
with mock_dynamodb2 ():
671
- yield next (build_metastore ())
679
+ metastore , table_name = build_metastore ()
680
+ yield metastore
681
+ delete_metastore (table_name )
682
+
683
+
684
+ def _count_entries (records , * messages ):
685
+ count = 0
686
+
687
+ for record in records :
688
+ if all ((message in record .getMessage () for message in messages )):
689
+ count += 1
690
+
691
+ return count
692
+
693
+
694
+ def _count_puts (records , table_name ):
695
+ return _count_entries (records , '"TableName": "{}"' .format (table_name ), "OperationModel(name=PutItem)" )
696
+
697
+
698
+ def _count_gets (records , table_name ):
699
+ return _count_entries (records , '"TableName": "{}"' .format (table_name ), "OperationModel(name=GetItem)" )
700
+
701
+
702
+ def check_metastore_cache_use_encrypt (metastore , table_name , log_capture ):
703
+ try :
704
+ table = boto3 .resource ("dynamodb" ).Table (table_name )
705
+ except NoRegionError :
706
+ table = boto3 .resource ("dynamodb" , region_name = TEST_REGION_NAME ).Table (table_name )
707
+
708
+ most_recent_provider = MostRecentProvider (provider_store = metastore , material_name = "test" , version_ttl = 600.0 )
709
+ e_table = EncryptedTable (table = table , materials_provider = most_recent_provider )
710
+
711
+ item = diverse_item ()
712
+ item .update (TEST_KEY )
713
+ e_table .put_item (Item = item )
714
+ e_table .put_item (Item = item )
715
+ e_table .put_item (Item = item )
716
+ e_table .put_item (Item = item )
717
+
718
+ try :
719
+ primary_puts = _count_puts (log_capture .records , e_table .name )
720
+ metastore_puts = _count_puts (log_capture .records , metastore ._table .name )
721
+
722
+ assert primary_puts == 4
723
+ assert metastore_puts == 1
724
+
725
+ e_table .get_item (Key = TEST_KEY )
726
+ e_table .get_item (Key = TEST_KEY )
727
+ e_table .get_item (Key = TEST_KEY )
728
+
729
+ primary_gets = _count_gets (log_capture .records , e_table .name )
730
+ metastore_gets = _count_gets (log_capture .records , metastore ._table .name )
731
+ metastore_puts = _count_puts (log_capture .records , metastore ._table .name )
732
+
733
+ assert primary_gets == 3
734
+ assert metastore_gets == 0
735
+ assert metastore_puts == 1
736
+
737
+ most_recent_provider .refresh ()
738
+
739
+ e_table .get_item (Key = TEST_KEY )
740
+ e_table .get_item (Key = TEST_KEY )
741
+ e_table .get_item (Key = TEST_KEY )
742
+
743
+ primary_gets = _count_gets (log_capture .records , e_table .name )
744
+ metastore_gets = _count_gets (log_capture .records , metastore ._table .name )
745
+
746
+ assert primary_gets == 6
747
+ assert metastore_gets == 1
748
+
749
+ finally :
750
+ e_table .delete_item (Key = TEST_KEY )
0 commit comments