Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

Commit 13ed487

Browse files
secretsmanager: add tag/untag resource handling for deleted secrets (#13662)
1 parent b9b3ca6 commit 13ed487

File tree

4 files changed

+113
-0
lines changed

4 files changed

+113
-0
lines changed

localstack-core/localstack/services/secretsmanager/provider.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,32 @@ def backend_update_secret(
614614
return json.dumps(resp)
615615

616616

617+
@patch(SecretsManagerBackend.tag_resource)
618+
def backend_tag_resource(fn, self, secret_id, tags):
619+
if secret_id not in self.secrets:
620+
raise SecretNotFoundException()
621+
622+
if self.secrets[secret_id].is_deleted():
623+
raise InvalidRequestException(
624+
"You can't perform this operation on the secret because it was marked for deletion."
625+
)
626+
627+
return fn(self, secret_id, tags)
628+
629+
630+
@patch(SecretsManagerBackend.untag_resource)
631+
def backend_untag_resource(fn, self, secret_id, tag_keys):
632+
if secret_id not in self.secrets:
633+
raise SecretNotFoundException()
634+
635+
if self.secrets[secret_id].is_deleted():
636+
raise InvalidRequestException(
637+
"You can't perform this operation on the secret because it was marked for deletion."
638+
)
639+
640+
return fn(self, secret_id, tag_keys)
641+
642+
617643
@patch(SecretsManagerResponse.update_secret, pass_target=False)
618644
def response_update_secret(self):
619645
secret_id = self._get_param("SecretId")

tests/aws/services/secretsmanager/test_secretsmanager.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,6 +2458,39 @@ def test_secret_tags(self, aws_client, create_secret, sm_snapshot, cleanups):
24582458
describe_secret_6 = aws_client.secretsmanager.describe_secret(SecretId=secret_arn)
24592459
sm_snapshot.match("describe_secret_6", describe_secret_6)
24602460

2461+
@markers.aws.validated
2462+
def test_tag_untag_resource_on_deleted_secret(self, aws_client, create_secret, sm_snapshot):
2463+
"""Test that tagging/untagging a secret marked for deletion raises InvalidRequestException."""
2464+
secret_name = short_uid()
2465+
response = create_secret(
2466+
Name=secret_name,
2467+
SecretString="test-secret-value",
2468+
Tags=[{"Key": "initial-tag", "Value": "initial-value"}],
2469+
)
2470+
2471+
sm_snapshot.add_transformers_list(
2472+
sm_snapshot.transform.secretsmanager_secret_id_arn(response, 0)
2473+
)
2474+
sm_snapshot.match("create_secret", response)
2475+
2476+
secret_arn = response["ARN"]
2477+
2478+
# Delete the secret (marks for deletion with recovery window)
2479+
delete_response = aws_client.secretsmanager.delete_secret(SecretId=secret_arn)
2480+
sm_snapshot.match("delete_secret", delete_response)
2481+
2482+
# Attempting to tag a deleted secret should raise InvalidRequestException
2483+
with pytest.raises(ClientError) as exc_tag:
2484+
aws_client.secretsmanager.tag_resource(
2485+
SecretId=secret_arn, Tags=[{"Key": "new-tag", "Value": "new-value"}]
2486+
)
2487+
sm_snapshot.match("tag_deleted_secret_error", exc_tag.value.response)
2488+
2489+
# Attempting to untag a deleted secret should raise InvalidRequestException
2490+
with pytest.raises(ClientError) as exc_untag:
2491+
aws_client.secretsmanager.untag_resource(SecretId=secret_arn, TagKeys=["initial-tag"])
2492+
sm_snapshot.match("untag_deleted_secret_error", exc_untag.value.response)
2493+
24612494
@markers.aws.validated
24622495
def test_get_secret_value_errors(self, aws_client, create_secret, sm_snapshot):
24632496
secret_name = short_uid()

tests/aws/services/secretsmanager/test_secretsmanager.snapshot.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4761,5 +4761,50 @@
47614761
}
47624762
}
47634763
}
4764+
},
4765+
"tests/aws/services/secretsmanager/test_secretsmanager.py::TestSecretsManager::test_tag_untag_resource_on_deleted_secret": {
4766+
"recorded-date": "29-01-2026, 22:02:37",
4767+
"recorded-content": {
4768+
"create_secret": {
4769+
"ARN": "arn:<partition>:secretsmanager:<region>:111111111111:secret:<SecretId-0idx><ArnPart-0idx>",
4770+
"Name": "<SecretId-0idx>",
4771+
"VersionId": "<version_uuid:1>",
4772+
"ResponseMetadata": {
4773+
"HTTPHeaders": {},
4774+
"HTTPStatusCode": 200
4775+
}
4776+
},
4777+
"delete_secret": {
4778+
"ARN": "arn:<partition>:secretsmanager:<region>:111111111111:secret:<SecretId-0idx><ArnPart-0idx>",
4779+
"DeletionDate": "datetime",
4780+
"Name": "<SecretId-0idx>",
4781+
"ResponseMetadata": {
4782+
"HTTPHeaders": {},
4783+
"HTTPStatusCode": 200
4784+
}
4785+
},
4786+
"tag_deleted_secret_error": {
4787+
"Error": {
4788+
"Code": "InvalidRequestException",
4789+
"Message": "You can't perform this operation on the secret because it was marked for deletion."
4790+
},
4791+
"Message": "You can't perform this operation on the secret because it was marked for deletion.",
4792+
"ResponseMetadata": {
4793+
"HTTPHeaders": {},
4794+
"HTTPStatusCode": 400
4795+
}
4796+
},
4797+
"untag_deleted_secret_error": {
4798+
"Error": {
4799+
"Code": "InvalidRequestException",
4800+
"Message": "You can't perform this operation on the secret because it was marked for deletion."
4801+
},
4802+
"Message": "You can't perform this operation on the secret because it was marked for deletion.",
4803+
"ResponseMetadata": {
4804+
"HTTPHeaders": {},
4805+
"HTTPStatusCode": 400
4806+
}
4807+
}
4808+
}
47644809
}
47654810
}

tests/aws/services/secretsmanager/test_secretsmanager.validation.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@
134134
"tests/aws/services/secretsmanager/test_secretsmanager.py::TestSecretsManager::test_secret_version_not_found": {
135135
"last_validated_date": "2024-06-13T08:04:35+00:00"
136136
},
137+
"tests/aws/services/secretsmanager/test_secretsmanager.py::TestSecretsManager::test_tag_untag_resource_on_deleted_secret": {
138+
"last_validated_date": "2026-01-29T22:02:38+00:00",
139+
"durations_in_seconds": {
140+
"setup": 0.79,
141+
"call": 1.51,
142+
"teardown": 0.23,
143+
"total": 2.53
144+
}
145+
},
137146
"tests/aws/services/secretsmanager/test_secretsmanager.py::TestSecretsManager::test_update_secret_description": {
138147
"last_validated_date": "2024-03-15T08:12:49+00:00"
139148
},

0 commit comments

Comments
 (0)