16
16
import attr
17
17
import boto3
18
18
import botocore .client
19
+ import botocore .config
19
20
from botocore .exceptions import ClientError
20
21
import botocore .session
21
22
22
23
from aws_encryption_sdk .exceptions import DecryptKeyError , EncryptKeyError , GenerateKeyError , UnknownRegionError
23
24
from aws_encryption_sdk .identifiers import USER_AGENT_SUFFIX
24
25
from aws_encryption_sdk .internal .str_ops import to_str
25
- from aws_encryption_sdk .internal .utils import extend_user_agent_suffix
26
26
from aws_encryption_sdk .key_providers .base import (
27
27
MasterKey , MasterKeyConfig , MasterKeyProvider , MasterKeyProviderConfig
28
28
)
33
33
_PROVIDER_ID = 'aws-kms'
34
34
35
35
36
+ def _region_from_key_id (key_id , default_region = None ):
37
+ """Determine the target region from a key ID, falling back to a default region if provided.
38
+
39
+ :param str key_id: AWS KMS key ID
40
+ :param str default_region: Region to use if no region found in key_id
41
+ :returns: region name
42
+ :rtype: str
43
+ :raises UnknownRegionError: if no region found in key_id and no default_region provided
44
+ """
45
+ try :
46
+ region_name = key_id .split (':' , 4 )[3 ]
47
+ if default_region is None :
48
+ default_region = region_name
49
+ except IndexError :
50
+ if default_region is None :
51
+ raise UnknownRegionError (
52
+ 'No default region found and no region determinable from key id: {}' .format (key_id )
53
+ )
54
+ region_name = default_region
55
+ return region_name
56
+
57
+
36
58
@attr .s (hash = True )
37
59
class KMSMasterKeyProviderConfig (MasterKeyProviderConfig ):
38
60
"""Configuration object for KMSMasterKeyProvider objects.
@@ -101,6 +123,7 @@ def __init__(self, **kwargs): # pylint: disable=unused-argument
101
123
102
124
def _process_config (self ):
103
125
"""Traverses the config and adds master keys and regional clients as needed."""
126
+ self ._user_agent_adding_config = botocore .config .Config (user_agent_extra = USER_AGENT_SUFFIX )
104
127
if self .config .key_ids :
105
128
self .add_master_keys_from_list (self .config .key_ids )
106
129
if self .config .region_names :
@@ -120,7 +143,7 @@ def add_regional_client(self, region_name):
120
143
self ._regional_clients [region_name ] = boto3 .session .Session (
121
144
region_name = region_name ,
122
145
botocore_session = self .config .botocore_session
123
- ).client ('kms' )
146
+ ).client ('kms' , config = self . _user_agent_adding_config )
124
147
125
148
def add_regional_clients_from_list (self , region_names ):
126
149
"""Adds multiple regional clients for the specified regions if they do not already exist.
@@ -135,16 +158,7 @@ def _client(self, key_id):
135
158
136
159
:param str key_id: KMS CMK ID
137
160
"""
138
- try :
139
- region_name = key_id .split (':' , 4 )[3 ]
140
- if self .default_region is None :
141
- self .default_region = region_name
142
- except IndexError :
143
- if self .default_region is None :
144
- raise UnknownRegionError (
145
- 'No default region found and no region determinable from key id: {}' .format (key_id )
146
- )
147
- region_name = self .default_region
161
+ region_name = _region_from_key_id (key_id , self .default_region )
148
162
self .add_regional_client (region_name )
149
163
return self ._regional_clients [region_name ]
150
164
@@ -174,14 +188,28 @@ class KMSMasterKeyConfig(MasterKeyConfig):
174
188
"""
175
189
176
190
provider_id = _PROVIDER_ID
177
- client = attr .ib (hash = True , validator = attr .validators .instance_of (botocore .client .BaseClient ))
191
+ client = attr .ib (
192
+ hash = True ,
193
+ validator = attr .validators .instance_of (botocore .client .BaseClient )
194
+ )
178
195
grant_tokens = attr .ib (
179
196
hash = True ,
180
197
default = attr .Factory (tuple ),
181
198
validator = attr .validators .instance_of (tuple ),
182
199
converter = tuple
183
200
)
184
201
202
+ @client .default
203
+ def client_default (self ):
204
+ """Create a client if one was not provided."""
205
+ try :
206
+ region_name = _region_from_key_id (to_str (self .key_id ))
207
+ kwargs = dict (region_name = region_name )
208
+ except UnknownRegionError :
209
+ kwargs = {}
210
+ botocore_config = botocore .config .Config (user_agent_extra = USER_AGENT_SUFFIX )
211
+ return boto3 .session .Session (** kwargs ).client ('kms' , config = botocore_config )
212
+
185
213
186
214
class KMSMasterKey (MasterKey ):
187
215
"""Master Key class for KMS CMKs.
@@ -200,10 +228,6 @@ class KMSMasterKey(MasterKey):
200
228
def __init__ (self , ** kwargs ): # pylint: disable=unused-argument
201
229
"""Performs transformations needed for KMS."""
202
230
self ._key_id = to_str (self .key_id ) # KMS client requires str, not bytes
203
- self .config .client .meta .config .user_agent_extra = extend_user_agent_suffix (
204
- user_agent = self .config .client .meta .config .user_agent_extra ,
205
- suffix = USER_AGENT_SUFFIX
206
- )
207
231
208
232
def _generate_data_key (self , algorithm , encryption_context = None ):
209
233
"""Generates data key and returns plaintext and ciphertext of key.
0 commit comments