#2366 - SecretsManager - put_secret_value should support binary values

This commit is contained in:
Bert Blommers 2019-08-23 10:57:15 +01:00
parent d4aa55760c
commit e8d60435fe
3 changed files with 66 additions and 4 deletions

View File

@ -154,9 +154,9 @@ class SecretsManagerBackend(BaseBackend):
return version_id
def put_secret_value(self, secret_id, secret_string, version_stages):
def put_secret_value(self, secret_id, secret_string, secret_binary, version_stages):
version_id = self._add_secret(secret_id, secret_string, version_stages=version_stages)
version_id = self._add_secret(secret_id, secret_string, secret_binary, version_stages=version_stages)
response = json.dumps({
'ARN': secret_arn(self.region, secret_id),

View File

@ -1,6 +1,7 @@
from __future__ import unicode_literals
from moto.core.responses import BaseResponse
from moto.secretsmanager.exceptions import InvalidRequestException
from .models import secretsmanager_backends
@ -71,10 +72,14 @@ class SecretsManagerResponse(BaseResponse):
def put_secret_value(self):
secret_id = self._get_param('SecretId', if_none='')
secret_string = self._get_param('SecretString', if_none='')
secret_string = self._get_param('SecretString')
secret_binary = self._get_param('SecretBinary')
if not secret_binary and not secret_string:
raise InvalidRequestException('You must provide either SecretString or SecretBinary.')
version_stages = self._get_param('VersionStages', if_none=['AWSCURRENT'])
return secretsmanager_backends[self.region].put_secret_value(
secret_id=secret_id,
secret_binary=secret_binary,
secret_string=secret_string,
version_stages=version_stages,
)

View File

@ -5,9 +5,9 @@ import boto3
from moto import mock_secretsmanager
from botocore.exceptions import ClientError
import string
import unittest
import pytz
from datetime import datetime
import sure # noqa
from nose.tools import assert_raises
from six import b
@ -23,6 +23,7 @@ def test_get_secret_value():
result = conn.get_secret_value(SecretId='java-util-test-password')
assert result['SecretString'] == 'foosecret'
@mock_secretsmanager
def test_get_secret_value_binary():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -32,6 +33,7 @@ def test_get_secret_value_binary():
result = conn.get_secret_value(SecretId='java-util-test-password')
assert result['SecretBinary'] == b('foosecret')
@mock_secretsmanager
def test_get_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -39,6 +41,7 @@ def test_get_secret_that_does_not_exist():
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-exist')
@mock_secretsmanager
def test_get_secret_that_does_not_match():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -72,6 +75,7 @@ def test_create_secret():
secret = conn.get_secret_value(SecretId='test-secret')
assert secret['SecretString'] == 'foosecret'
@mock_secretsmanager
def test_create_secret_with_tags():
conn = boto3.client('secretsmanager', region_name='us-east-1')
@ -216,6 +220,7 @@ def test_get_random_exclude_lowercase():
ExcludeLowercase=True)
assert any(c.islower() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_uppercase():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -224,6 +229,7 @@ def test_get_random_exclude_uppercase():
ExcludeUppercase=True)
assert any(c.isupper() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_characters_and_symbols():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -232,6 +238,7 @@ def test_get_random_exclude_characters_and_symbols():
ExcludeCharacters='xyzDje@?!.')
assert any(c in 'xyzDje@?!.' for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_numbers():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -240,6 +247,7 @@ def test_get_random_exclude_numbers():
ExcludeNumbers=True)
assert any(c.isdigit() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_punctuation():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -249,6 +257,7 @@ def test_get_random_exclude_punctuation():
assert any(c in string.punctuation
for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_include_space_false():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -256,6 +265,7 @@ def test_get_random_include_space_false():
random_password = conn.get_random_password(PasswordLength=300)
assert any(c.isspace() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_include_space_true():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -264,6 +274,7 @@ def test_get_random_include_space_true():
IncludeSpace=True)
assert any(c.isspace() for c in random_password['RandomPassword']) == True
@mock_secretsmanager
def test_get_random_require_each_included_type():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -275,6 +286,7 @@ def test_get_random_require_each_included_type():
assert any(c in string.ascii_uppercase for c in random_password['RandomPassword']) == True
assert any(c in string.digits for c in random_password['RandomPassword']) == True
@mock_secretsmanager
def test_get_random_too_short_password():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -282,6 +294,7 @@ def test_get_random_too_short_password():
with assert_raises(ClientError):
random_password = conn.get_random_password(PasswordLength=3)
@mock_secretsmanager
def test_get_random_too_long_password():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -289,6 +302,7 @@ def test_get_random_too_long_password():
with assert_raises(Exception):
random_password = conn.get_random_password(PasswordLength=5555)
@mock_secretsmanager
def test_describe_secret():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -307,6 +321,7 @@ def test_describe_secret():
assert secret_description_2['Name'] == ('test-secret-2')
assert secret_description_2['ARN'] != '' # Test arn not empty
@mock_secretsmanager
def test_describe_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -314,6 +329,7 @@ def test_describe_secret_that_does_not_exist():
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-exist')
@mock_secretsmanager
def test_describe_secret_that_does_not_match():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -500,6 +516,7 @@ def test_rotate_secret_rotation_period_zero():
# test_server actually handles this error.
assert True
@mock_secretsmanager
def test_rotate_secret_rotation_period_too_long():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -511,6 +528,7 @@ def test_rotate_secret_rotation_period_too_long():
result = conn.rotate_secret(SecretId=DEFAULT_SECRET_NAME,
RotationRules=rotation_rules)
@mock_secretsmanager
def test_put_secret_value_puts_new_secret():
conn = boto3.client('secretsmanager', region_name='us-west-2')
@ -526,6 +544,45 @@ def test_put_secret_value_puts_new_secret():
assert get_secret_value_dict
assert get_secret_value_dict['SecretString'] == 'foosecret'
@mock_secretsmanager
def test_put_secret_binary_value_puts_new_secret():
conn = boto3.client('secretsmanager', region_name='us-west-2')
put_secret_value_dict = conn.put_secret_value(SecretId=DEFAULT_SECRET_NAME,
SecretBinary=b('foosecret'),
VersionStages=['AWSCURRENT'])
version_id = put_secret_value_dict['VersionId']
get_secret_value_dict = conn.get_secret_value(SecretId=DEFAULT_SECRET_NAME,
VersionId=version_id,
VersionStage='AWSCURRENT')
assert get_secret_value_dict
assert get_secret_value_dict['SecretBinary'] == b('foosecret')
@mock_secretsmanager
def test_create_and_put_secret_binary_value_puts_new_secret():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b("foosecret"))
conn.put_secret_value(SecretId=DEFAULT_SECRET_NAME, SecretBinary=b('foosecret_update'))
latest_secret = conn.get_secret_value(SecretId=DEFAULT_SECRET_NAME)
assert latest_secret
assert latest_secret['SecretBinary'] == b('foosecret_update')
@mock_secretsmanager
def test_put_secret_binary_requires_either_string_or_binary():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError) as ire:
conn.put_secret_value(SecretId=DEFAULT_SECRET_NAME)
ire.exception.response['Error']['Code'].should.equal('InvalidRequestException')
ire.exception.response['Error']['Message'].should.equal('You must provide either SecretString or SecretBinary.')
@mock_secretsmanager
def test_put_secret_value_can_get_first_version_if_put_twice():
conn = boto3.client('secretsmanager', region_name='us-west-2')