From 381e7b165fdd18c7aebc7cfd1379d44468e87861 Mon Sep 17 00:00:00 2001 From: Alexander Campbell Date: Tue, 15 Oct 2019 21:57:16 +1100 Subject: [PATCH] Raise appropriate error when secret exists but has no value --- moto/secretsmanager/exceptions.py | 4 ++-- moto/secretsmanager/models.py | 20 ++++++++++++------- .../test_secretsmanager.py | 17 +++++++++++++++- tests/test_secretsmanager/test_server.py | 20 +++++++++++++++++++ 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/moto/secretsmanager/exceptions.py b/moto/secretsmanager/exceptions.py index fa81b6d8b..746368a6b 100644 --- a/moto/secretsmanager/exceptions.py +++ b/moto/secretsmanager/exceptions.py @@ -7,11 +7,11 @@ class SecretsManagerClientError(JsonRESTError): class ResourceNotFoundException(SecretsManagerClientError): - def __init__(self): + def __init__(self, message): self.code = 404 super(ResourceNotFoundException, self).__init__( "ResourceNotFoundException", - "Secrets Manager can't find the specified secret" + message, ) diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py index 63d847c49..f7cb855eb 100644 --- a/moto/secretsmanager/models.py +++ b/moto/secretsmanager/models.py @@ -46,7 +46,7 @@ class SecretsManagerBackend(BaseBackend): def get_secret_value(self, secret_id, version_id, version_stage): if not self._is_valid_identifier(secret_id): - raise ResourceNotFoundException() + raise ResourceNotFoundException("Secrets Manager can't find the specified secret") if not version_id and version_stage: # set version_id to match version_stage @@ -56,7 +56,7 @@ class SecretsManagerBackend(BaseBackend): version_id = ver_id break if not version_id: - raise ResourceNotFoundException() + raise ResourceNotFoundException("Secrets Manager can't find the specified secret") # TODO check this part if 'deleted_date' in self.secrets[secret_id]: @@ -84,6 +84,12 @@ class SecretsManagerBackend(BaseBackend): if 'secret_binary' in secret_version: response_data["SecretBinary"] = secret_version['secret_binary'] + if 'secret_string' not in secret_version and 'secret_binary' not in secret_version: + raise ResourceNotFoundException( + "Secrets Manager can’t find the specified secret value for staging label: %s" % + (version_stage or "AWSCURRENT") + ) + response = json.dumps(response_data) return response @@ -169,7 +175,7 @@ class SecretsManagerBackend(BaseBackend): def describe_secret(self, secret_id): if not self._is_valid_identifier(secret_id): - raise ResourceNotFoundException + raise ResourceNotFoundException("Secrets Manager can't find the specified secret") secret = self.secrets[secret_id] @@ -198,7 +204,7 @@ class SecretsManagerBackend(BaseBackend): rotation_days = 'AutomaticallyAfterDays' if not self._is_valid_identifier(secret_id): - raise ResourceNotFoundException + raise ResourceNotFoundException("Secrets Manager can't find the specified secret") if 'deleted_date' in self.secrets[secret_id]: raise InvalidRequestException( @@ -340,7 +346,7 @@ class SecretsManagerBackend(BaseBackend): def delete_secret(self, secret_id, recovery_window_in_days, force_delete_without_recovery): if not self._is_valid_identifier(secret_id): - raise ResourceNotFoundException + raise ResourceNotFoundException("Secrets Manager can't find the specified secret") if 'deleted_date' in self.secrets[secret_id]: raise InvalidRequestException( @@ -370,7 +376,7 @@ class SecretsManagerBackend(BaseBackend): secret = self.secrets.get(secret_id, None) if not secret: - raise ResourceNotFoundException + raise ResourceNotFoundException("Secrets Manager can't find the specified secret") arn = secret_arn(self.region, secret['secret_id']) name = secret['name'] @@ -380,7 +386,7 @@ class SecretsManagerBackend(BaseBackend): def restore_secret(self, secret_id): if not self._is_valid_identifier(secret_id): - raise ResourceNotFoundException + raise ResourceNotFoundException("Secrets Manager can't find the specified secret") self.secrets[secret_id].pop('deleted_date', None) diff --git a/tests/test_secretsmanager/test_secretsmanager.py b/tests/test_secretsmanager/test_secretsmanager.py index 62de93bab..b77fa70d0 100644 --- a/tests/test_secretsmanager/test_secretsmanager.py +++ b/tests/test_secretsmanager/test_secretsmanager.py @@ -8,7 +8,7 @@ import string import pytz from datetime import datetime import sure # noqa -from nose.tools import assert_raises +from nose.tools import assert_raises, assert_raises_regexp from six import b DEFAULT_SECRET_NAME = 'test-secret' @@ -65,6 +65,21 @@ def test_get_secret_value_that_is_marked_deleted(): result = conn.get_secret_value(SecretId='test-secret') +@mock_secretsmanager +def test_get_secret_that_has_no_value(): + conn = boto3.client('secretsmanager', region_name='us-west-2') + + create_secret = conn.create_secret(Name="java-util-test-password") + + with assert_raises_regexp( + ClientError, + r"An error occurred \(ResourceNotFoundException\) when calling the GetSecretValue " + r"operation: Secrets Manager can’t find the specified secret value for staging label: " + r"AWSCURRENT" + ): + result = conn.get_secret_value(SecretId='java-util-test-password') + + @mock_secretsmanager def test_create_secret(): conn = boto3.client('secretsmanager', region_name='us-east-1') diff --git a/tests/test_secretsmanager/test_server.py b/tests/test_secretsmanager/test_server.py index 23d823239..25fc1676b 100644 --- a/tests/test_secretsmanager/test_server.py +++ b/tests/test_secretsmanager/test_server.py @@ -73,6 +73,26 @@ def test_get_secret_that_does_not_match(): assert json_data['message'] == "Secrets Manager can't find the specified secret" assert json_data['__type'] == 'ResourceNotFoundException' +@mock_secretsmanager +def test_get_secret_that_has_no_value(): + backend = server.create_backend_app('secretsmanager') + test_client = backend.test_client() + + create_secret = test_client.post('/', + data={"Name": DEFAULT_SECRET_NAME}, + headers={ + "X-Amz-Target": "secretsmanager.CreateSecret"}, + ) + get_secret = test_client.post('/', + data={"SecretId": DEFAULT_SECRET_NAME}, + headers={ + "X-Amz-Target": "secretsmanager.GetSecretValue"}, + ) + + json_data = json.loads(get_secret.data.decode("utf-8")) + assert json_data['message'] == "Secrets Manager can’t find the specified secret value for staging label: AWSCURRENT" + assert json_data['__type'] == 'ResourceNotFoundException' + @mock_secretsmanager def test_create_secret():