From b31f31d21448379f2f48342bae725923a957790f Mon Sep 17 00:00:00 2001 From: mwas Date: Sat, 23 Nov 2019 09:29:30 +0300 Subject: [PATCH 1/5] fixing fetch secret manager via arn --- moto/secretsmanager/models.py | 10 +++++++++- tests/test_secretsmanager/test_secretsmanager.py | 12 ++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py index 6f9a00b0e..7bd38259a 100644 --- a/moto/secretsmanager/models.py +++ b/moto/secretsmanager/models.py @@ -44,7 +44,15 @@ class SecretsManagerBackend(BaseBackend): return (dt - epoch).total_seconds() def get_secret_value(self, secret_id, version_id, version_stage): - + # can fetch by both arn and by name + # but we are storing via name + # so we need to change the arn to name + # if it starts with arn then the secret id is arn + if secret_id.startswith("arn:aws:secretsmanager:%s" % self.region): + # split the arn by colon + # then get the last value which is the name appended with a random string + # then remove the random string + secret_id = '-'.join(secret_id.split(':')[-1].split('-')[:-1]) if not self._is_valid_identifier(secret_id): raise SecretNotFoundException() diff --git a/tests/test_secretsmanager/test_secretsmanager.py b/tests/test_secretsmanager/test_secretsmanager.py index a7c7a6862..cc64dc874 100644 --- a/tests/test_secretsmanager/test_secretsmanager.py +++ b/tests/test_secretsmanager/test_secretsmanager.py @@ -26,6 +26,18 @@ def test_get_secret_value(): assert result["SecretString"] == "foosecret" +@mock_secretsmanager +def test_get_secret_value_by_arn(): + conn = boto3.client("secretsmanager", region_name="us-west-2") + + secret_value = "test_get_secret_value_by_arn" + result = conn.create_secret( + Name="java-util-test-password", SecretString=secret_value + ) + result = conn.get_secret_value(SecretId=result["ARN"]) + assert result["SecretString"] == secret_value + + @mock_secretsmanager def test_get_secret_value_binary(): conn = boto3.client("secretsmanager", region_name="us-west-2") From 5274ffa5e0bff5d9c8bbf3a16e8f01a02d6e7aad Mon Sep 17 00:00:00 2001 From: mwas Date: Sat, 23 Nov 2019 10:12:31 +0300 Subject: [PATCH 2/5] fix both get and describe with arn and name --- moto/secretsmanager/models.py | 13 +++---------- moto/secretsmanager/utils.py | 13 +++++++++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py index 7bd38259a..b22ca9bf8 100644 --- a/moto/secretsmanager/models.py +++ b/moto/secretsmanager/models.py @@ -17,7 +17,7 @@ from .exceptions import ( InvalidRequestException, ClientError, ) -from .utils import random_password, secret_arn +from .utils import random_password, secret_arn, get_secret_name_from_arn class SecretsManager(BaseModel): @@ -44,15 +44,7 @@ class SecretsManagerBackend(BaseBackend): return (dt - epoch).total_seconds() def get_secret_value(self, secret_id, version_id, version_stage): - # can fetch by both arn and by name - # but we are storing via name - # so we need to change the arn to name - # if it starts with arn then the secret id is arn - if secret_id.startswith("arn:aws:secretsmanager:%s" % self.region): - # split the arn by colon - # then get the last value which is the name appended with a random string - # then remove the random string - secret_id = '-'.join(secret_id.split(':')[-1].split('-')[:-1]) + secret_id = get_secret_name_from_arn(secret_id) if not self._is_valid_identifier(secret_id): raise SecretNotFoundException() @@ -204,6 +196,7 @@ class SecretsManagerBackend(BaseBackend): return response def describe_secret(self, secret_id): + secret_id = get_secret_name_from_arn(secret_id) if not self._is_valid_identifier(secret_id): raise SecretNotFoundException() diff --git a/moto/secretsmanager/utils.py b/moto/secretsmanager/utils.py index 44385270c..cc2d6ce8a 100644 --- a/moto/secretsmanager/utils.py +++ b/moto/secretsmanager/utils.py @@ -72,6 +72,19 @@ def secret_arn(region, secret_id): ) +def get_secret_name_from_arn(secret_id): + # can fetch by both arn and by name + # but we are storing via name + # so we need to change the arn to name + # if it starts with arn then the secret id is arn + if secret_id.startswith("arn:aws:secretsmanager:"): + # split the arn by colon + # then get the last value which is the name appended with a random string + # then remove the random string + secret_id = '-'.join(secret_id.split(':')[-1].split('-')[:-1]) + return secret_id + + def _exclude_characters(password, exclude_characters): for c in exclude_characters: if c in string.punctuation: From 9decb8674dbee8a1f07f54534b410f3b37de9eb3 Mon Sep 17 00:00:00 2001 From: mwas Date: Sat, 23 Nov 2019 10:18:06 +0300 Subject: [PATCH 3/5] adding tests for describe secret with arn --- tests/test_secretsmanager/test_secretsmanager.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_secretsmanager/test_secretsmanager.py b/tests/test_secretsmanager/test_secretsmanager.py index cc64dc874..4d880604d 100644 --- a/tests/test_secretsmanager/test_secretsmanager.py +++ b/tests/test_secretsmanager/test_secretsmanager.py @@ -373,6 +373,18 @@ def test_describe_secret(): assert secret_description_2["ARN"] != "" # Test arn not empty +@mock_secretsmanager +def test_describe_secret_with_arn(): + conn = boto3.client("secretsmanager", region_name="us-west-2") + results = conn.create_secret(Name="test-secret", SecretString="foosecret") + + secret_description = conn.describe_secret(SecretId=results['ARN']) + + assert secret_description # Returned dict is not empty + assert secret_description["Name"] == ("test-secret") + assert secret_description["ARN"] != results['ARN'] + + @mock_secretsmanager def test_describe_secret_that_does_not_exist(): conn = boto3.client("secretsmanager", region_name="us-west-2") From 66c9d15ca84794d118ac49d45c1959cbfc4a7af4 Mon Sep 17 00:00:00 2001 From: mwas Date: Sat, 23 Nov 2019 12:37:30 +0300 Subject: [PATCH 4/5] fixing fetching secret id with both arn and name --- moto/secretsmanager/models.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py index b22ca9bf8..fd49892d1 100644 --- a/moto/secretsmanager/models.py +++ b/moto/secretsmanager/models.py @@ -25,11 +25,25 @@ class SecretsManager(BaseModel): self.region = region_name +class SecretsStore(dict): + def __setitem__(self, key, value): + new_key = get_secret_name_from_arn(key) + super(SecretsStore, self).__setitem__(new_key, value) + + def __getitem__(self, key): + new_key = get_secret_name_from_arn(key) + return super(SecretsStore, self).__getitem__(new_key) + + def __contains__(self, key): + new_key = get_secret_name_from_arn(key) + return dict.__contains__(self, new_key) + + class SecretsManagerBackend(BaseBackend): def __init__(self, region_name=None, **kwargs): super(SecretsManagerBackend, self).__init__() self.region = region_name - self.secrets = {} + self.secrets = SecretsStore() def reset(self): region_name = self.region @@ -44,7 +58,6 @@ class SecretsManagerBackend(BaseBackend): return (dt - epoch).total_seconds() def get_secret_value(self, secret_id, version_id, version_stage): - secret_id = get_secret_name_from_arn(secret_id) if not self._is_valid_identifier(secret_id): raise SecretNotFoundException() @@ -196,7 +209,6 @@ class SecretsManagerBackend(BaseBackend): return response def describe_secret(self, secret_id): - secret_id = get_secret_name_from_arn(secret_id) if not self._is_valid_identifier(secret_id): raise SecretNotFoundException() From 0e825a5048f8d28f6872690146529481e9543166 Mon Sep 17 00:00:00 2001 From: mwas Date: Sat, 23 Nov 2019 13:02:00 +0300 Subject: [PATCH 5/5] lint --- moto/secretsmanager/utils.py | 2 +- tests/test_secretsmanager/test_secretsmanager.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/moto/secretsmanager/utils.py b/moto/secretsmanager/utils.py index cc2d6ce8a..73275ee05 100644 --- a/moto/secretsmanager/utils.py +++ b/moto/secretsmanager/utils.py @@ -81,7 +81,7 @@ def get_secret_name_from_arn(secret_id): # split the arn by colon # then get the last value which is the name appended with a random string # then remove the random string - secret_id = '-'.join(secret_id.split(':')[-1].split('-')[:-1]) + secret_id = "-".join(secret_id.split(":")[-1].split("-")[:-1]) return secret_id diff --git a/tests/test_secretsmanager/test_secretsmanager.py b/tests/test_secretsmanager/test_secretsmanager.py index 4d880604d..3b8c74e81 100644 --- a/tests/test_secretsmanager/test_secretsmanager.py +++ b/tests/test_secretsmanager/test_secretsmanager.py @@ -378,11 +378,11 @@ def test_describe_secret_with_arn(): conn = boto3.client("secretsmanager", region_name="us-west-2") results = conn.create_secret(Name="test-secret", SecretString="foosecret") - secret_description = conn.describe_secret(SecretId=results['ARN']) + secret_description = conn.describe_secret(SecretId=results["ARN"]) assert secret_description # Returned dict is not empty assert secret_description["Name"] == ("test-secret") - assert secret_description["ARN"] != results['ARN'] + assert secret_description["ARN"] != results["ARN"] @mock_secretsmanager