-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathtest_providers_base_master_key.py
314 lines (259 loc) · 12.6 KB
/
test_providers_base_master_key.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Test suite for aws_encryption_sdk.key_providers.base.MasterKey"""
import attr
import pytest
import six
from mock import MagicMock, patch, sentinel
from aws_encryption_sdk.exceptions import ConfigMismatchError, IncorrectMasterKeyError, InvalidKeyIdError
from aws_encryption_sdk.internal.defaults import ALGORITHM
from aws_encryption_sdk.key_providers.base import MasterKey, MasterKeyConfig, MasterKeyProvider
from aws_encryption_sdk.structures import MasterKeyInfo
from .test_values import VALUES
pytestmark = [pytest.mark.unit, pytest.mark.local]
@attr.s(hash=True)
class MockMasterKeyConfig(MasterKeyConfig):
provider_id = VALUES["provider_id"]
mock_generated_data_key = attr.ib()
mock_encrypted_data_key = attr.ib()
mock_decrypted_data_key = attr.ib()
class MockMasterKey(MasterKey):
_config_class = MockMasterKeyConfig
provider_id = VALUES["provider_id"]
def _generate_data_key(self, algorithm, encryption_context):
return self.config.mock_generated_data_key
def _encrypt_data_key(self, data_key, algorithm, encryption_context):
return self.config.mock_encrypted_data_key
def _decrypt_data_key(self, encrypted_data_key, algorithm, encryption_context):
return self.config.mock_decrypted_data_key
def test_master_key_provider_id_config_enforcement():
class FakeConfig(object):
key_id = b"a key"
class FakeMasterKey(MockMasterKey):
_config_class = FakeConfig
with pytest.raises(TypeError) as excinfo:
FakeMasterKey()
excinfo.match(r'MasterKey config classes must have a "provider_id" attribute defined.')
class TestMasterKey(object):
@pytest.fixture(autouse=True)
def apply_fixture(self):
self.mock_data_key_len_check_patcher = patch("aws_encryption_sdk.internal.utils.source_data_key_length_check")
self.mock_data_key_len_check = self.mock_data_key_len_check_patcher.start()
def tearDown(self):
self.mock_data_key_len_check_patcher.stop()
def test_parent(self):
assert issubclass(MasterKey, MasterKeyProvider)
def test_provider_id_enforcement(self):
class TestMasterKey(MasterKey):
def _generate_data_key(self, algorithm, encryption_context):
pass
def _encrypt_data_key(self, data_key, algorithm, encryption_context):
pass
def _decrypt_data_key(self, encrypted_data_key, algorithm, encryption_context):
pass
with pytest.raises(TypeError) as excinfo:
TestMasterKey()
excinfo.match("Can't instantiate abstract class TestMasterKey *")
def test_generate_data_key_enforcement(self):
class TestMasterKey(MasterKey):
provider_id = None
def _encrypt_data_key(self, data_key, algorithm, encryption_context):
pass
def _decrypt_data_key(self, encrypted_data_key, algorithm, encryption_context):
pass
with pytest.raises(TypeError) as excinfo:
TestMasterKey()
excinfo.match("Can't instantiate abstract class TestMasterKey *")
def test_encrypt_data_key_enforcement(self):
class TestMasterKey(MasterKey):
provider_id = None
def _generate_data_key(self, algorithm, encryption_context):
pass
def _decrypt_data_key(self, encrypted_data_key, algorithm, encryption_context):
pass
with pytest.raises(TypeError) as excinfo:
TestMasterKey()
excinfo.match("Can't instantiate abstract class TestMasterKey *")
def test_decrypt_data_key_enforcement(self):
class TestMasterKey(MasterKey):
provider_id = None
def _generate_data_key(self, algorithm, encryption_context):
pass
def _encrypt_data_key(self, data_key, algorithm, encryption_context):
pass
with pytest.raises(TypeError) as excinfo:
TestMasterKey()
excinfo.match("Can't instantiate abstract class TestMasterKey *")
def test_new(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
assert mock_master_key.key_id is VALUES["key_info"]
assert mock_master_key.key_provider.provider_id == VALUES["provider_id"]
assert mock_master_key.key_provider.key_info is VALUES["key_info"]
def test_new_conf_mismatch(self):
mock_config = MagicMock()
mock_config.__class__ = MockMasterKeyConfig
mock_config.provider_id = sentinel.mismatched_provider_id
with pytest.raises(ConfigMismatchError) as excinfo:
MockMasterKey(config=mock_config)
excinfo.match("Config provider_id does not match MasterKey provider_id: *")
def test_owns_data_key_owned(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
mock_data_key = MagicMock()
mock_data_key.key_provider = mock_master_key.key_provider
assert mock_master_key.owns_data_key(data_key=mock_data_key)
def test_owns_data_key_not_owned(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
mock_data_key = MagicMock()
mock_data_key.key_provider = sentinel.key_provider
assert not mock_master_key.owns_data_key(data_key=mock_data_key)
def test_key_index(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
assert mock_master_key._encrypt_key_index == {VALUES["key_info"]: mock_master_key}
assert mock_master_key._decrypt_key_index == {}
def test_members(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
assert mock_master_key._members == [mock_master_key]
def test_master_keys_for_encryption(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
test_primary, test = mock_master_key.master_keys_for_encryption(
encryption_context=sentinel.encryption_context,
plaintext_rostream=sentinel.plaintext_rostream,
plaintext_length=sentinel.plaintext_length,
)
assert test_primary is mock_master_key
assert test == [mock_master_key]
def test_new_master_key_valid(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
test = mock_master_key._new_master_key(VALUES["key_info"])
assert test is mock_master_key
def test_new_master_key_invalid(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
with pytest.raises(InvalidKeyIdError) as excinfo:
mock_master_key._new_master_key(sentinel.another_key_id)
excinfo.match("MasterKeys can only provide themselves. *")
def test_key_check_valid(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
mock_data_key = MagicMock()
mock_data_key.key_provider = MasterKeyInfo(VALUES["provider_id"], VALUES["key_info"])
mock_master_key._key_check(mock_data_key)
def test_key_check_invalid(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
mock_data_key = MagicMock()
mock_data_key.key_provider = sentinel.another_key_provider
with pytest.raises(IncorrectMasterKeyError) as excinfo:
mock_master_key._key_check(mock_data_key)
excinfo.match("Provided data key provider *")
def test_generate_data_key(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
mock_master_key._generate_data_key = MagicMock(return_value=sentinel.new_raw_data_key)
test = mock_master_key.generate_data_key(algorithm=ALGORITHM, encryption_context=VALUES["encryption_context"])
mock_master_key._generate_data_key.assert_called_once_with(
algorithm=ALGORITHM, encryption_context=VALUES["encryption_context"]
)
self.mock_data_key_len_check.assert_called_once_with(
source_data_key=sentinel.new_raw_data_key, algorithm=ALGORITHM
)
assert test is sentinel.new_raw_data_key
def test_encrypt_data_key(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
mock_master_key._key_check = MagicMock()
mock_master_key._encrypt_data_key = MagicMock()
mock_master_key.encrypt_data_key(
data_key=sentinel.data_key, algorithm=ALGORITHM, encryption_context=VALUES["encryption_context"]
)
mock_master_key._encrypt_data_key.assert_called_once_with(
data_key=sentinel.data_key, algorithm=ALGORITHM, encryption_context=VALUES["encryption_context"]
)
def test_decrypt_data_key(self):
mock_master_key = MockMasterKey(
key_id=VALUES["key_info"],
mock_generated_data_key=sentinel.generated_data_key,
mock_encrypted_data_key=sentinel.encrypted_data_key,
mock_decrypted_data_key=sentinel.decrypted_data_key,
)
mock_master_key._key_check = MagicMock()
mock_master_key._decrypt_data_key = MagicMock(return_value=sentinel.raw_decrypted_data_key)
mock_master_key.decrypt_data_key(
encrypted_data_key=sentinel.encrypted_data_key,
algorithm=ALGORITHM,
encryption_context=VALUES["encryption_context"],
)
self.mock_data_key_len_check.assert_called_once_with(
source_data_key=sentinel.raw_decrypted_data_key, algorithm=ALGORITHM
)
mock_master_key._key_check.assert_called_once_with(sentinel.encrypted_data_key)
mock_master_key._decrypt_data_key.assert_called_once_with(
encrypted_data_key=sentinel.encrypted_data_key,
algorithm=ALGORITHM,
encryption_context=VALUES["encryption_context"],
)