11
11
# ANY KIND, either express or implied. See the License for the specific
12
12
# language governing permissions and limitations under the License.
13
13
"""Resources required for Multi Keyrings."""
14
+ import itertools
15
+
14
16
import attr
15
17
from attr .validators import deep_iterable , instance_of , optional
16
18
17
- from aws_encryption_sdk .exceptions import EncryptKeyError
19
+ from aws_encryption_sdk .exceptions import EncryptKeyError , GenerateKeyError
18
20
from aws_encryption_sdk .keyring .base import DecryptionMaterials , EncryptedDataKey , EncryptionMaterials , Keyring
19
21
20
22
try : # Python 3.5.0 and 3.5.1 have incompatible typing modules
@@ -35,17 +37,19 @@ class MultiKeyring(Keyring):
35
37
"""
36
38
37
39
children = attr .ib (
38
- default = None ,
39
- validator = optional (deep_iterable (member_validator = instance_of (Keyring ), iterable_validator = instance_of (list ))),
40
+ default = attr .Factory (tuple ), validator = optional (deep_iterable (member_validator = instance_of (Keyring )))
40
41
)
41
42
generator = attr .ib (default = None , validator = optional (instance_of (Keyring )))
42
43
43
44
def __attrs_post_init__ (self ):
44
45
# type: () -> None
45
46
"""Prepares initial values not handled by attrs."""
46
- neither_generator_nor_children = self .generator is None and self .children is None
47
+ neither_generator_nor_children = self .generator is None and not self .children
47
48
if neither_generator_nor_children :
48
- raise TypeError ("At least one of generator or children should be provided" )
49
+ raise TypeError ("At least one of generator or children must be provided" )
50
+
51
+ _generator = (self .generator ,) if self .generator is not None else ()
52
+ self ._decryption_keyrings = itertools .chain (_generator , self .children )
49
53
50
54
def on_encrypt (self , encryption_materials ):
51
55
# type: (EncryptionMaterials) -> EncryptionMaterials
@@ -71,12 +75,11 @@ def on_encrypt(self, encryption_materials):
71
75
72
76
# Check if data key is generated
73
77
if not encryption_materials .data_encryption_key :
74
- raise EncryptKeyError ("Unable to generate data encryption key." )
78
+ raise GenerateKeyError ("Unable to generate data encryption key." )
75
79
76
80
# Call on_encrypt on all other keyrings
77
- if self .children is not None :
78
- for keyring in self .children :
79
- encryption_materials = keyring .on_encrypt (encryption_materials )
81
+ for keyring in self .children :
82
+ encryption_materials = keyring .on_encrypt (encryption_materials )
80
83
81
84
return encryption_materials
82
85
@@ -95,17 +98,10 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys):
95
98
if decryption_materials .data_encryption_key :
96
99
return decryption_materials
97
100
98
- # Call on_decrypt on generator keyring if it is provided
99
- if self . generator is not None :
100
- decryption_materials = self . generator .on_decrypt (decryption_materials , encrypted_data_keys )
101
+ # Call on_decrypt on all keyrings till decryption is successful
102
+ for keyring in self . _decryption_keyrings :
103
+ decryption_materials = keyring .on_decrypt (decryption_materials , encrypted_data_keys )
101
104
if decryption_materials .data_encryption_key :
102
105
return decryption_materials
103
106
104
- # Call on_decrypt on all keyrings till decryption is successful
105
- if self .children is not None :
106
- for keyring in self .children :
107
- decryption_materials = keyring .on_decrypt (decryption_materials , encrypted_data_keys )
108
- if decryption_materials .data_encryption_key :
109
- return decryption_materials
110
-
111
107
return decryption_materials
0 commit comments