7
7
from aws_lambda_powertools .shared .constants import DATA_MASKING_STRING
8
8
from aws_lambda_powertools .utilities .data_masking .base import DataMasking
9
9
from aws_lambda_powertools .utilities .data_masking .provider import Provider
10
- from aws_lambda_powertools .utilities .data_masking .providers .aws_encryption_sdk import (
11
- AwsEncryptionSdkProvider ,
12
- )
13
- from aws_lambda_powertools .utilities .data_masking .providers .itsdangerous import (
14
- ItsDangerousProvider ,
15
- )
16
-
17
- AWS_SDK_KEY = "arn:aws:kms:us-west-2:683517028648:key/269301eb-81eb-4067-ac72-98e8e49bf2b3"
18
10
19
11
20
12
class MyEncryptionProvider (Provider ):
@@ -39,8 +31,6 @@ def decrypt(self, data: str) -> str:
39
31
40
32
data_maskers = [
41
33
DataMasking (),
42
- DataMasking (provider = ItsDangerousProvider ("mykey" )),
43
- DataMasking (provider = AwsEncryptionSdkProvider (keys = [AWS_SDK_KEY ])),
44
34
DataMasking (provider = MyEncryptionProvider (keys = "secret-key" )),
45
35
]
46
36
@@ -121,101 +111,137 @@ def decrypt(self, data: str) -> str:
121
111
@pytest .mark .parametrize ("data_masker" , data_maskers )
122
112
@pytest .mark .parametrize ("value, value_masked" , data_types_and_masks )
123
113
def test_mask_types (data_masker , value , value_masked ):
114
+ # GIVEN any data type
115
+
116
+ # WHEN mask is called with no fields argument
124
117
masked_string = data_masker .mask (value )
118
+
119
+ # THEN the result is the full input data masked
125
120
assert masked_string == value_masked
126
121
127
122
128
123
@pytest .mark .parametrize ("data_masker" , data_maskers )
129
124
def test_mask_with_fields (data_masker ):
125
+ # GIVEN the data type is a dictionary, or a json representation of a dictionary
126
+
127
+ # WHEN mask is called with a list of fields specified
130
128
masked_string = data_masker .mask (python_dict , dict_fields )
129
+ masked_json_string = data_masker .mask (json_dict , dict_fields )
130
+
131
+ # THEN the result is only the specified fields are masked
131
132
assert masked_string == masked_with_fields
132
- masked_string = data_masker .mask (json_dict , dict_fields )
133
- assert masked_string == masked_with_fields
133
+ assert masked_json_string == masked_with_fields
134
134
135
135
136
- @pytest .mark .parametrize ("data_masker" , data_maskers )
137
136
@pytest .mark .parametrize ("value" , data_types )
138
- def test_encrypt_decrypt (data_masker , value ):
139
- if data_masker == data_maskers [0 ]:
140
- with pytest .raises (NotImplementedError ):
141
- encrypted_data = data_masker .encrypt (value )
137
+ def test_encrypt_decrypt (value ):
138
+ # GIVEN an instantiation of DataMasking with a Provider
139
+ data_masker = DataMasking (provider = MyEncryptionProvider (keys = "secret-key" ))
142
140
143
- else :
144
- if data_masker == data_maskers [2 ]:
145
- # AWS Encryption SDK encrypt method only takes in bytes or strings
146
- value = bytes (str (value ), "utf-8" )
141
+ # WHEN encrypting and then decrypting the encrypted data
142
+ encrypted_data = data_masker .encrypt (value )
143
+ decrypted_data = data_masker .decrypt (encrypted_data )
147
144
148
- encrypted_data = data_masker .encrypt (value )
149
- decrypted_data = data_masker .decrypt (encrypted_data )
150
- assert decrypted_data == value
145
+ # THEN the result is the original input data
146
+ assert decrypted_data == value
151
147
152
148
153
- @pytest .mark .parametrize ("data_masker" , data_maskers )
154
149
@pytest .mark .parametrize ("value, fields" , zip (dictionaries , fields_to_mask ))
155
- def test_encrypt_decrypt_with_fields (data_masker , value , fields ):
156
- if data_masker == data_maskers [0 ]:
157
- with pytest .raises (NotImplementedError ):
158
- encrypted_data = data_masker .encrypt (value )
150
+ def test_encrypt_decrypt_with_fields (value , fields ):
151
+ # GIVEN an instantiation of DataMasking with a Provider
152
+ data_masker = DataMasking (provider = MyEncryptionProvider (keys = "secret-key" ))
153
+
154
+ # WHEN encrypting and then decrypting the encrypted data with a list of fields
155
+ encrypted_data = data_masker .encrypt (value , fields )
156
+ decrypted_data = data_masker .decrypt (encrypted_data , fields )
159
157
158
+ # THEN the result is the original input data
159
+ if value == json_dict :
160
+ assert decrypted_data == json .loads (value )
160
161
else :
161
- encrypted_data = data_masker .encrypt (value , fields )
162
- decrypted_data = data_masker .decrypt (encrypted_data , fields )
162
+ assert decrypted_data == value
163
+
164
+
165
+ def test_encrypt_not_implemented ():
166
+ # GIVEN DataMasking is not initialized with a Provider
167
+ data_masker = DataMasking ()
163
168
164
- if data_masker == data_maskers [2 ]:
165
- # AWS Encryption SDK decrypt method only returns bytes
166
- if value == json_blob :
167
- assert decrypted_data == aws_encrypted_json_blob
168
- else :
169
- assert decrypted_data == aws_encrypted_with_fields
169
+ # WHEN attempting to call the encrypt method on the data
170
170
171
- else :
172
- if value == json_dict :
173
- assert decrypted_data == json .loads (value )
174
- else :
175
- assert decrypted_data == value
171
+ # THEN the result is a NotImplementedError
172
+ with pytest .raises (NotImplementedError ):
173
+ data_masker .encrypt ("hello world" )
176
174
177
175
178
176
def test_decrypt_not_implemented ():
179
- """Test decrypting with no Provider"""
177
+ # GIVEN DataMasking is not initialized with a Provider
180
178
data_masker = DataMasking ()
181
- with pytest .raises (NotImplementedError ):
182
- data_masker .decrypt ("hello world" )
183
179
180
+ # WHEN attempting to call the decrypt method on the data
184
181
185
- def test_aws_encryption_sdk_with_context ():
186
- data_masker = DataMasking (provider = AwsEncryptionSdkProvider (keys = [AWS_SDK_KEY ]))
187
- encrypted_data = data_masker .encrypt (
188
- str (python_dict ), encryption_context = {"not really" : "a secret" , "but adds" : "some auth" }
189
- )
190
- decrypted_data = data_masker .decrypt (encrypted_data )
191
- assert decrypted_data == bytes (str (python_dict ), "utf-8" )
182
+ # THEN the result is a NotImplementedError
183
+ with pytest .raises (NotImplementedError ):
184
+ data_masker .decrypt ("hello world" )
192
185
193
186
194
187
def test_parsing_unsupported_data_type ():
188
+ # GIVEN an initialization of the DataMasking class
195
189
data_masker = DataMasking ()
190
+
191
+ # WHEN attempting to pass in a list of fields with input data that is not a dict
192
+
193
+ # THEN the result is a TypeError
196
194
with pytest .raises (TypeError ):
197
195
data_masker .mask (42 , ["this.field" ])
198
196
199
197
198
+ def test_parsing_nonexistent_fields ():
199
+ # GIVEN an initialization of the DataMasking class
200
+ data_masker = DataMasking ()
201
+ _python_dict = {
202
+ "3" : {
203
+ "1" : {"None" : "hello" , "four" : "world" },
204
+ "4" : {"33" : {"5" : "goodbye" , "e" : "world" }},
205
+ }
206
+ }
207
+
208
+ # WHEN attempting to pass in fields that do not exist in the input data
209
+
210
+ # THEN the result is a KeyError
211
+ with pytest .raises (KeyError ):
212
+ data_masker .mask (_python_dict , ["3.1.True" ])
213
+
214
+
200
215
def test_parsing_nonstring_fields ():
216
+ # GIVEN an initialization of the DataMasking class
201
217
data_masker = DataMasking ()
202
218
_python_dict = {
203
219
"3" : {
204
220
"1" : {"None" : "hello" , "four" : "world" },
205
221
"4" : {"33" : {"5" : "goodbye" , "e" : "world" }},
206
222
}
207
223
}
224
+
225
+ # WHEN attempting to pass in a list of fields that are not strings
208
226
masked = data_masker .mask (_python_dict , fields = [3.4 ])
227
+
228
+ # THEN the result is the value of the nested field should be masked as normal
209
229
assert masked == {"3" : {"1" : {"None" : "hello" , "four" : "world" }, "4" : DATA_MASKING_STRING }}
210
230
211
231
212
232
def test_parsing_nonstring_keys_and_fields ():
233
+ # GIVEN an initialization of the DataMasking class
213
234
data_masker = DataMasking ()
235
+
236
+ # WHEN the input data is a dictionary with integer keys
214
237
_python_dict = {
215
238
3 : {
216
239
"1" : {"None" : "hello" , "four" : "world" },
217
240
4 : {"33" : {"5" : "goodbye" , "e" : "world" }},
218
241
}
219
242
}
243
+
220
244
masked = data_masker .mask (_python_dict , fields = [3.4 ])
245
+
246
+ # THEN the result is the value of the nested field should be masked as normal
221
247
assert masked == {"3" : {"1" : {"None" : "hello" , "four" : "world" }, "4" : DATA_MASKING_STRING }}
0 commit comments