def test_kms_encrypt_call(self): """Validates basic kms call parameters""" ef_utils.kms_encrypt(self.mock_kms, self.service, self.env, self.secret) self.mock_kms.encrypt.assert_called_once_with( KeyId='alias/{}-{}'.format(self.env, self.service), Plaintext=self.secret.encode())
def test_kms_encrypt_call_subservice(self): """Validate KMS encryption call on a subservice, where periods should be converted to underscores due to alias name restrictions""" subservice = self.service + ".subservice" ef_utils.kms_encrypt(self.mock_kms, subservice, self.env, self.secret) self.mock_kms.encrypt.assert_called_once_with( KeyId='alias/{}-{}'.format(self.env, self.service + "_subservice"), Plaintext=self.secret.encode())
def main(): context = handle_args_and_set_context(sys.argv[1:]) profile = None if context.whereami == "ec2" else context.account_alias try: clients = ef_utils.create_aws_clients(EFConfig.DEFAULT_REGION, profile, "kms") except RuntimeError as error: ef_utils.fail( "Exception creating clients in region {} with profile {}".format( EFConfig.DEFAULT_REGION, profile), error) if context.secret_file: generate_secret_file(context.secret_file, context.match, context.service, context.env, clients) return if context.decrypt: decrypted = ef_utils.kms_decrypt(kms_client=clients['kms'], secret=context.decrypt) key_aliases = ef_utils.kms_key_alias(clients['kms'], decrypted.key_id) print("Decrypted Secret: {}; Key: {}".format(decrypted.plaintext, ', '.join(key_aliases))) return if context.plaintext: password = context.plaintext else: password = generate_secret(context.length) print("Generated Secret: {}".format(password)) encrypted_password = ef_utils.kms_encrypt(clients['kms'], context.service, context.env, password) print(format_secret(encrypted_password)) return
def generate_secret_file(file_path, pattern, service, environment, clients): """ Generate a parameter files with it's secrets encrypted in KMS Args: file_path (string): Path to the parameter file to be encrypted pattern (string): Pattern to do fuzzy string matching service (string): Service to use KMS key to encrypt file environment (string): Environment to encrypt values clients (dict): KMS AWS client that has been instantiated Returns: None Raises: IOError: If the file does not exist """ changed = False with open(file_path) as json_file: data = json.load(json_file, object_pairs_hook=OrderedDict) try: for key, value in data["params"][environment].items(): if pattern in key: if "aws:kms:decrypt" in value: print( "Found match, key {} but value is encrypted already; skipping..." .format(key)) else: print("Found match, encrypting key {}".format(key)) encrypted_password = ef_utils.kms_encrypt( clients['kms'], service, environment, value) data["params"][environment][key] = format_secret( encrypted_password) changed = True except KeyError: ef_utils.fail( "Error env: {} does not exist in parameters file".format( environment)) if changed: with open(file_path, "w") as encrypted_file: json.dump(data, encrypted_file, indent=2, separators=(',', ': ')) # Writing new line here so it conforms to WG14 N1256 5.1.1.1 (so github doesn't complain) encrypted_file.write("\n")
def test_kms_encrypt_fails_client_error(self): """Ensures that function fails a generic ClientError despite any special handling for specific error codes""" self.mock_kms.encrypt.side_effect = self.client_error with self.assertRaises(SystemExit): ef_utils.kms_encrypt(self.mock_kms, self.service, self.env, self.secret)
def test_kms_encrypt_returns_b64(self): """Validate that function returns a base64 encoded value""" encrypted_secret = ef_utils.kms_encrypt(self.mock_kms, self.service, self.env, self.secret) b64_return = base64.b64encode(self.bytes_return) self.assertEqual(b64_return, encrypted_secret)