Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions aws_lambda_powertools/utilities/parameters/secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,11 @@ def _get_multiple(self, names: list[str], **sdk_options) -> dict[str, Any]: # t
When the parameter provider fails to retrieve secrets
"""

# Merge filters: combine names with any additional filters from sdk_options
filters = sdk_options.get("Filters", [])
# Merge filters: combine names with any additional filters from sdk_options.
# A new list is created on purpose: mutating the caller's list would leak
# a stale name filter into every subsequent call that reuses it.
name_filter = {"Key": "name", "Values": names}

# Add name filter to existing filters
filters.append(name_filter)
sdk_options["Filters"] = filters
sdk_options["Filters"] = [*sdk_options.get("Filters", []), name_filter]

# Remove SecretIdList if present to avoid conflicts
sdk_options.pop("SecretIdList", None)
Expand Down
41 changes: 41 additions & 0 deletions tests/functional/parameters/_boto3/test_utilities_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3435,6 +3435,47 @@ def test_secrets_provider_get_multiple_basic(config):
stubber.deactivate()


def test_secrets_provider_get_multiple_does_not_mutate_caller_filters(config):
"""
Test SecretsProvider.get_multiple() does not mutate the caller's Filters list
"""
# GIVEN a SecretsProvider instance and a caller-owned Filters list
provider = parameters.SecretsProvider(boto_config=config)
caller_filters = [{"Key": "primary-region", "Values": ["us-east-1"]}]

stubber = stub.Stubber(provider.client)
first_expected_params = {
"Filters": [{"Key": "primary-region", "Values": ["us-east-1"]}, {"Key": "name", "Values": ["first-secret"]}],
}
second_expected_params = {
"Filters": [{"Key": "primary-region", "Values": ["us-east-1"]}, {"Key": "name", "Values": ["second-secret"]}],
}
stubber.add_response(
"batch_get_secret_value",
{"SecretValues": [{"Name": "first-secret", "SecretString": "1"}], "Errors": []},
first_expected_params,
)
stubber.add_response(
"batch_get_secret_value",
{"SecretValues": [{"Name": "second-secret", "SecretString": "2"}], "Errors": []},
second_expected_params,
)
stubber.activate()

try:
# WHEN calling get_multiple twice with the same Filters list
first = provider.get_multiple(["first-secret"], Filters=caller_filters)
second = provider.get_multiple(["second-secret"], Filters=caller_filters)

# THEN each call sends only its own name filter and the caller's list stays untouched
assert first == {"first-secret": "1"}
assert second == {"second-secret": "2"}
assert caller_filters == [{"Key": "primary-region", "Values": ["us-east-1"]}]
stubber.assert_no_pending_responses()
finally:
stubber.deactivate()


def test_secrets_provider_get_multiple_with_binary(config):
"""
Test SecretsProvider.get_multiple() with binary secrets
Expand Down