Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix tag operations in secretsmanager #7547

Merged
merged 2 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 9 additions & 5 deletions moto/secretsmanager/list_secrets/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,23 @@ def description_filter(secret: "FakeSecret", descriptions: List[str]) -> bool:


def tag_key(secret: "FakeSecret", tag_keys: List[str]) -> bool:
if not secret.tags:
return False
return _matcher(tag_keys, [tag["Key"] for tag in secret.tags])


def tag_value(secret: "FakeSecret", tag_values: List[str]) -> bool:
if not secret.tags:
return False
return _matcher(tag_values, [tag["Value"] for tag in secret.tags])


def filter_all(secret: "FakeSecret", values: List[str]) -> bool:
attributes = (
[secret.name, secret.description]
+ [tag["Key"] for tag in secret.tags]
+ [tag["Value"] for tag in secret.tags]
)
attributes = [secret.name, secret.description]
if secret.tags:
attributes += [tag["Key"] for tag in secret.tags] + [
tag["Value"] for tag in secret.tags
]

return _matcher(values, attributes) # type: ignore

Expand Down
31 changes: 12 additions & 19 deletions moto/secretsmanager/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
self.secret_string = secret_string
self.secret_binary = secret_binary
self.description = description
self.tags = tags or []
self.tags = tags or None
self.kms_key_id = kms_key_id
self.version_stages = version_stages
self.last_changed_date = last_changed_date
Expand Down Expand Up @@ -158,7 +158,7 @@
last_changed_date: Optional[int] = None,
) -> None:
self.description = description
self.tags = tags or []
self.tags = tags or None
if last_changed_date is not None:
self.last_changed_date = last_changed_date

Expand Down Expand Up @@ -236,7 +236,7 @@
"DeletedDate": self.deleted_date,
"CreatedDate": self.created_date,
}
if self.tags:
if self.tags is not None:
dct["Tags"] = self.tags
if self.description:
dct["Description"] = self.description
Expand Down Expand Up @@ -942,20 +942,13 @@
secret = self.secrets[secret_id]
if isinstance(secret, ReplicaSecret):
raise OperationNotPermittedOnReplica
old_tags = secret.tags

old_tags = {tag["Key"]: tag for tag in secret.tags or []}

for tag in tags:
existing_key_name = next(
(
old_key
for old_key in old_tags
if old_key.get("Key") == tag.get("Key")
),
None,
)
if existing_key_name:
old_tags.remove(existing_key_name)
old_tags.append(tag)
old_tags[tag["Key"]] = tag

secret.tags = list(old_tags.values())

def untag_resource(self, secret_id: str, tag_keys: List[str]) -> None:
if secret_id not in self.secrets:
Expand All @@ -964,11 +957,11 @@
secret = self.secrets[secret_id]
if isinstance(secret, ReplicaSecret):
raise OperationNotPermittedOnReplica
tags = secret.tags

for tag in tags:
if tag["Key"] in tag_keys:
tags.remove(tag)
if secret.tags is None:
return

Check warning on line 962 in moto/secretsmanager/models.py

View check run for this annotation

Codecov / codecov/patch

moto/secretsmanager/models.py#L962

Added line #L962 was not covered by tests

secret.tags = [tag for tag in secret.tags if tag["Key"] not in tag_keys]

def update_secret_version_stage(
self,
Expand Down
12 changes: 12 additions & 0 deletions tests/test_secretsmanager/test_secretsmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,10 @@ def test_tag_resource(pass_arn):
conn = boto3.client("secretsmanager", region_name="us-west-2")
created_secret = conn.create_secret(Name="test-secret", SecretString="foosecret")
secret_id = created_secret["ARN"] if pass_arn else "test-secret"

response = conn.describe_secret(SecretId=secret_id)
assert "Tags" not in response

conn.tag_resource(
SecretId=secret_id, Tags=[{"Key": "FirstTag", "Value": "SomeValue"}]
)
Expand Down Expand Up @@ -1678,6 +1682,14 @@ def test_untag_resource(pass_arn):
== cm.value.response["Error"]["Message"]
)

conn.tag_resource(
SecretId=secret_id, Tags=[{"Key": "FirstTag", "Value": "SomeValue"}]
)
conn.untag_resource(SecretId=secret_id, TagKeys=["FirstTag", "SecondTag"])
response = conn.describe_secret(SecretId=secret_id)
assert "Tags" in response
assert response["Tags"] == []


@mock_aws
def test_secret_versions_to_stages_attribute_discrepancy():
Expand Down