diff --git a/moto/ssm/models.py b/moto/ssm/models.py index 1a18a512b..ef28d06a9 100644 --- a/moto/ssm/models.py +++ b/moto/ssm/models.py @@ -1606,22 +1606,26 @@ class SimpleSystemManagerBackend(BaseBackend): else: continue elif key.startswith("tag:"): - what = key[4:] or None - for tag in parameter.tags: - if tag["Key"] == what and tag["Value"] in values: - return True - return False + what = [tag["Value"] for tag in parameter.tags if tag["Key"] == key[4:]] if what is None: return False - elif option == "BeginsWith" and not any( - what.startswith(value) for value in values - ): - return False + # 'what' can be a list (of multiple tag-values, for instance) + is_list = isinstance(what, list) + if option == "BeginsWith": + if is_list and not any( + any(w.startswith(val) for w in what) for val in values + ): + return False + elif not is_list and not any(what.startswith(val) for val in values): + return False elif option == "Contains" and not any(value in what for value in values): return False - elif option == "Equals" and not any(what == value for value in values): - return False + elif option == "Equals": + if is_list and not any(val in what for val in values): + return False + elif not is_list and not any(what == val for val in values): + return False elif option == "OneLevel": if any(value == "/" and len(what.split("/")) == 2 for value in values): continue diff --git a/tests/test_ssm/test_ssm_boto3.py b/tests/test_ssm/test_ssm_boto3.py index 757dd1877..dffe73cc9 100644 --- a/tests/test_ssm/test_ssm_boto3.py +++ b/tests/test_ssm/test_ssm_boto3.py @@ -67,21 +67,14 @@ def test_delete_parameters(): def test_get_parameters_by_path(): client = boto3.client("ssm", region_name="us-east-1") - client.put_parameter( - Name="/foo/name1", Description="A test parameter", Value="value1", Type="String" - ) + client.put_parameter(Name="/foo/name1", Value="value1", Type="String") - client.put_parameter( - Name="/foo/name2", Description="A test parameter", Value="value2", Type="String" - ) + client.put_parameter(Name="/foo/name2", Value="value2", Type="String") - client.put_parameter( - Name="/bar/name3", Description="A test parameter", Value="value3", Type="String" - ) + client.put_parameter(Name="/bar/name3", Value="value3", Type="String") client.put_parameter( Name="/bar/name3/name4", - Description="A test parameter", Value="value4", Type="String", ) @@ -93,9 +86,7 @@ def test_get_parameters_by_path(): Type="StringList", ) - client.put_parameter( - Name="/baz/name2", Description="A test parameter", Value="value1", Type="String" - ) + client.put_parameter(Name="/baz/name2", Value="value1", Type="String") client.put_parameter( Name="/baz/pwd", @@ -105,13 +96,9 @@ def test_get_parameters_by_path(): KeyId="alias/aws/ssm", ) - client.put_parameter( - Name="foo", Description="A test parameter", Value="bar", Type="String" - ) + client.put_parameter(Name="foo", Value="bar", Type="String") - client.put_parameter( - Name="baz", Description="A test parameter", Value="qux", Type="String" - ) + client.put_parameter(Name="baz", Value="qux", Type="String") response = client.get_parameters_by_path(Path="/", Recursive=False) len(response["Parameters"]).should.equal(2) @@ -1045,6 +1032,48 @@ def test_describe_parameters_tags(): parameters[0]["Name"].should.equal("/spam/eggs") +@mock_ssm +def test_describe_parameters__multiple_tags(): + client = boto3.client("ssm", region_name="us-east-1") + + for x in "ab": + client.put_parameter( + Name=f"test_my_param_01_{x}", + Value=f"Contents of param {x}", + Type="String", + Tags=[{"Key": "hello", "Value": "world"}, {"Key": "x", "Value": x}], + ) + + response = client.describe_parameters( + ParameterFilters=[ + {"Key": "tag:x", "Option": "Equals", "Values": ["b"]}, + {"Key": "tag:hello", "Option": "Equals", "Values": ["world"]}, + ] + ) + response["Parameters"].should.have.length_of(1) + + # Both params contains hello:world - ensure we also check the second tag, x=b + response = client.describe_parameters( + ParameterFilters=[ + {"Key": "tag:hello", "Option": "Equals", "Values": ["world"]}, + {"Key": "tag:x", "Option": "Equals", "Values": ["b"]}, + ] + ) + response["Parameters"].should.have.length_of(1) + + # tag begins_with should also work + client.describe_parameters( + ParameterFilters=[ + {"Key": "tag:hello", "Option": "BeginsWith", "Values": ["w"]}, + ] + )["Parameters"].should.have.length_of(2) + client.describe_parameters( + ParameterFilters=[ + {"Key": "tag:x", "Option": "BeginsWith", "Values": ["a"]}, + ] + )["Parameters"].should.have.length_of(1) + + @mock_ssm def test_tags_in_list_tags_from_resource_parameter(): client = boto3.client("ssm", region_name="us-east-1")