Update get_secret_value to properly check versions and stages match (#5238)

This commit is contained in:
Bryan Schrock 2022-06-18 06:20:14 -05:00 committed by GitHub
parent 58edb5b840
commit 836a2e6538
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 1 deletions

View File

@ -30,6 +30,15 @@ class SecretHasNoValueException(SecretsManagerClientError):
)
class SecretStageVersionMismatchException(SecretsManagerClientError):
def __init__(self):
self.code = 404
super().__init__(
"InvalidRequestException",
message="You provided a VersionStage that is not associated to the provided VersionId.",
)
class ClientError(SecretsManagerClientError):
def __init__(self, message):
super().__init__("InvalidParameterValue", message)

View File

@ -13,6 +13,7 @@ from .exceptions import (
InvalidParameterException,
ResourceExistsException,
ResourceNotFoundException,
SecretStageVersionMismatchException,
InvalidRequestException,
ClientError,
)
@ -226,6 +227,14 @@ class SecretsManagerBackend(BaseBackend):
if not self._is_valid_identifier(secret_id):
raise SecretNotFoundException()
if version_id and version_stage:
versions_dict = self.secrets[secret_id].versions
if (
version_id in versions_dict
and version_stage not in versions_dict[version_id]["version_stages"]
):
raise SecretStageVersionMismatchException()
if not version_id and version_stage:
# set version_id to match version_stage
versions_dict = self.secrets[secret_id].versions

View File

@ -153,6 +153,33 @@ def test_get_secret_version_that_does_not_exist():
) == cm.value.response["Error"]["Message"]
@mock_secretsmanager
def test_get_secret_version_stage_mismatch():
conn = boto3.client("secretsmanager", region_name="us-west-2")
result = conn.create_secret(Name="test-secret", SecretString="secret")
secret_arn = result["ARN"]
rotated_secret = conn.rotate_secret(
SecretId=secret_arn, RotationRules={"AutomaticallyAfterDays": 42}
)
desc_secret = conn.describe_secret(SecretId=secret_arn)
versions_to_stages = desc_secret["VersionIdsToStages"]
version_for_test = rotated_secret["VersionId"]
stages_for_version = versions_to_stages[version_for_test]
assert "AWSPENDING" not in stages_for_version
with pytest.raises(ClientError) as cm:
conn.get_secret_value(
SecretId=secret_arn, VersionId=version_for_test, VersionStage="AWSPENDING"
)
assert (
"You provided a VersionStage that is not associated to the provided VersionId."
) == cm.value.response["Error"]["Message"]
@mock_secretsmanager
def test_create_secret():
conn = boto3.client("secretsmanager", region_name="us-east-1")

View File

@ -618,7 +618,7 @@ def test_put_secret_value_can_get_first_version_if_put_twice():
data={
"SecretId": DEFAULT_SECRET_NAME,
"VersionId": first_secret_version_id,
"VersionStage": "AWSCURRENT",
"VersionStage": "AWSPREVIOUS",
},
headers={"X-Amz-Target": "secretsmanager.GetSecretValue"},
)