Added policy tagging that was previously marked as missing (#4520)

This commit is contained in:
Sam Attridge 2021-11-03 20:58:40 +00:00 committed by GitHub
parent ccd216dfe5
commit ff6d7a13c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 663 additions and 9 deletions

View File

@ -2364,7 +2364,7 @@
- [X] list_open_id_connect_providers
- [X] list_policies
- [ ] list_policies_granting_service_access
- [ ] list_policy_tags
- [X] list_policy_tags
- [X] list_policy_versions
- [X] list_role_policies
- [X] list_role_tags
@ -2397,7 +2397,7 @@
- [ ] tag_instance_profile
- [ ] tag_mfa_device
- [ ] tag_open_id_connect_provider
- [ ] tag_policy
- [X] tag_policy
- [X] tag_role
- [ ] tag_saml_provider
- [ ] tag_server_certificate
@ -2405,7 +2405,7 @@
- [ ] untag_instance_profile
- [ ] untag_mfa_device
- [ ] untag_open_id_connect_provider
- [ ] untag_policy
- [X] untag_policy
- [X] untag_role
- [ ] untag_saml_provider
- [ ] untag_server_certificate

View File

@ -108,7 +108,7 @@ class Policy(CloudFormationModel):
self.description = description or ""
self.id = random_policy_id()
self.path = path or "/"
self.tags = {tag["Key"]: tag["Value"] for tag in tags or []}
self.tags = tags
if default_version_id:
self.default_version_id = default_version_id
@ -141,6 +141,9 @@ class Policy(CloudFormationModel):
def updated_iso_8601(self):
return iso_8601_datetime_with_milliseconds(self.update_date)
def get_tags(self):
return [self.tags[tag] for tag in self.tags]
class SAMLProvider(BaseModel):
def __init__(self, name, saml_metadata_document=None):
@ -284,6 +287,7 @@ class ManagedPolicy(Policy, CloudFormationModel):
"awsRegion": "global",
"availabilityZone": "Not Applicable",
"resourceCreationTime": str(self.create_date),
"tags": self.tags,
"configuration": {
"policyName": self.name,
"policyId": self.id,
@ -296,6 +300,12 @@ class ManagedPolicy(Policy, CloudFormationModel):
"description": self.description,
"createDate": str(self.create_date.isoformat()),
"updateDate": str(self.create_date.isoformat()),
"tags": list(
map(
lambda key: {"key": key, "value": self.tags[key]["Value"]},
self.tags,
)
),
"policyVersionList": list(
map(
lambda version: {
@ -331,12 +341,14 @@ class ManagedPolicy(Policy, CloudFormationModel):
group_names = properties.get("Groups", [])
user_names = properties.get("Users", [])
role_names = properties.get("Roles", [])
tags = properties.get("Tags", {})
policy = iam_backend.create_policy(
description=description,
path=path,
policy_document=policy_document,
policy_name=name,
tags=tags,
)
for group_name in group_names:
iam_backend.attach_group_policy(
@ -1568,16 +1580,17 @@ class IAMBackend(BaseBackend):
raise IAMNotFoundException("Policy {0} was not found.".format(policy_arn))
policy.detach_from(self.get_user(user_name))
def create_policy(self, description, path, policy_document, policy_name, tags=None):
def create_policy(self, description, path, policy_document, policy_name, tags):
iam_policy_document_validator = IAMPolicyDocumentValidator(policy_document)
iam_policy_document_validator.validate()
clean_tags = self._tag_verification(tags)
policy = ManagedPolicy(
policy_name,
description=description,
document=policy_document,
path=path,
tags=tags,
tags=clean_tags,
)
if policy.arn in self.managed_policies:
raise EntityAlreadyExists(
@ -1849,6 +1862,42 @@ class IAMBackend(BaseBackend):
role.tags.pop(ref_key, None)
def list_policy_tags(self, policy_arn, marker, max_items=100):
policy = self.get_policy(policy_arn)
max_items = int(max_items)
tag_index = sorted(policy.tags)
start_idx = int(marker) if marker else 0
tag_index = tag_index[start_idx : start_idx + max_items]
if len(policy.tags) <= (start_idx + max_items):
marker = None
else:
marker = str(start_idx + max_items)
# Make the tag list of dict's:
tags = [policy.tags[tag] for tag in tag_index]
return tags, marker
def tag_policy(self, policy_arn, tags):
clean_tags = self._tag_verification(tags)
policy = self.get_policy(policy_arn)
policy.tags.update(clean_tags)
def untag_policy(self, policy_arn, tag_keys):
if len(tag_keys) > 50:
raise TooManyTags(tag_keys, param="tagKeys")
policy = self.get_policy(policy_arn)
for key in tag_keys:
ref_key = key.lower()
self._validate_tag_key(key, exception_param="tagKeys")
policy.tags.pop(ref_key, None)
def create_policy_version(self, policy_arn, policy_document, set_as_default):
iam_policy_document_validator = IAMPolicyDocumentValidator(policy_document)
iam_policy_document_validator.validate()

View File

@ -308,6 +308,34 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_POLICY_VERSIONS_TEMPLATE)
return template.render(policy_versions=policy_versions)
def list_policy_tags(self):
policy_arn = self._get_param("PolicyArn")
marker = self._get_param("Marker")
max_items = self._get_param("MaxItems", 100)
tags, marker = iam_backend.list_policy_tags(policy_arn, marker, max_items)
template = self.response_template(LIST_POLICY_TAG_TEMPLATE)
return template.render(tags=tags, marker=marker)
def tag_policy(self):
policy_arn = self._get_param("PolicyArn")
tags = self._get_multi_param("Tags.member")
iam_backend.tag_policy(policy_arn, tags)
template = self.response_template(TAG_POLICY_TEMPLATE)
return template.render()
def untag_policy(self):
policy_arn = self._get_param("PolicyArn")
tag_keys = self._get_multi_param("TagKeys.member")
iam_backend.untag_policy(policy_arn, tag_keys)
template = self.response_template(UNTAG_POLICY_TEMPLATE)
return template.render()
def delete_policy_version(self):
policy_arn = self._get_param("PolicyArn")
version_id = self._get_param("VersionId")
@ -1129,14 +1157,16 @@ GET_POLICY_TEMPLATE = """<GetPolicyResponse>
<AttachmentCount>{{ policy.attachment_count }}</AttachmentCount>
<CreateDate>{{ policy.created_iso_8601 }}</CreateDate>
<UpdateDate>{{ policy.updated_iso_8601 }}</UpdateDate>
{% if policy.tags %}
<Tags>
{% for tag_key, tag_value in policy.tags.items() %}
{% for tag in policy.get_tags() %}
<member>
<Key>{{ tag_key }}</Key>
<Value>{{ tag_value }}</Value>
<Key>{{ tag['Key'] }}</Key>
<Value>{{ tag['Value'] }}</Value>
</member>
{% endfor %}
</Tags>
{% endif %}
</Policy>
</GetPolicyResult>
<ResponseMetadata>
@ -2495,6 +2525,41 @@ UNTAG_ROLE_TEMPLATE = """<UntagRoleResponse xmlns="https://iam.amazonaws.com/doc
</UntagRoleResponse>"""
TAG_POLICY_TEMPLATE = """<TagPolicyResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<ResponseMetadata>
<RequestId>EXAMPLE8-90ab-cdef-fedc-ba987EXAMPLE</RequestId>
</ResponseMetadata>
</TagPolicyResponse>"""
LIST_POLICY_TAG_TEMPLATE = """<ListPolicyTagsResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<ListPolicyTagsResult>
<IsTruncated>{{ 'true' if marker else 'false' }}</IsTruncated>
{% if marker %}
<Marker>{{ marker }}</Marker>
{% endif %}
<Tags>
{% for tag in tags %}
<member>
<Key>{{ tag['Key'] }}</Key>
<Value>{{ tag['Value'] }}</Value>
</member>
{% endfor %}
</Tags>
</ListPolicyTagsResult>
<ResponseMetadata>
<RequestId>EXAMPLE8-90ab-cdef-fedc-ba987EXAMPLE</RequestId>
</ResponseMetadata>
</ListPolicyTagsResponse>"""
UNTAG_POLICY_TEMPLATE = """<UntagPolicyResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<ResponseMetadata>
<RequestId>EXAMPLE8-90ab-cdef-fedc-ba987EXAMPLE</RequestId>
</ResponseMetadata>
</UntagPolicyResponse>"""
CREATE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE = """<CreateOpenIDConnectProviderResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<CreateOpenIDConnectProviderResult>
<OpenIDConnectProviderArn>{{ open_id_provider.arn }}</OpenIDConnectProviderArn>

View File

@ -960,6 +960,543 @@ def test_delete_default_policy_version():
)
@mock_iam()
def test_create_policy_with_tags():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(
PolicyName="TestCreatePolicyWithTags1",
PolicyDocument=MOCK_POLICY,
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
Description="testing",
)
# Get policy:
policy = conn.get_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(
ACCOUNT_ID, "TestCreatePolicyWithTags1"
)
)["Policy"]
assert len(policy["Tags"]) == 2
assert policy["Tags"][0]["Key"] == "somekey"
assert policy["Tags"][0]["Value"] == "somevalue"
assert policy["Tags"][1]["Key"] == "someotherkey"
assert policy["Tags"][1]["Value"] == "someothervalue"
assert policy["Description"] == "testing"
@mock_iam()
def test_create_policy_with_empty_tag_value():
conn = boto3.client("iam", region_name="us-east-1")
# Empty is good:
conn.create_policy(
PolicyName="TestCreatePolicyWithTags2",
PolicyDocument=MOCK_POLICY,
Tags=[{"Key": "somekey", "Value": ""}],
)
tags = conn.list_policy_tags(
PolicyArn="arn:aws:iam::{}:policy/{}".format(
ACCOUNT_ID, "TestCreatePolicyWithTags2"
)
)
assert len(tags["Tags"]) == 1
assert tags["Tags"][0]["Key"] == "somekey"
assert tags["Tags"][0]["Value"] == ""
@mock_iam()
def test_create_policy_with_too_many_tags():
conn = boto3.client("iam", region_name="us-east-1")
# With more than 50 tags:
with pytest.raises(ClientError) as ce:
too_many_tags = list(
map(lambda x: {"Key": str(x), "Value": str(x)}, range(0, 51))
)
conn.create_policy(
PolicyName="TestCreatePolicyWithTags3",
PolicyDocument=MOCK_POLICY,
Tags=too_many_tags,
)
assert (
"failed to satisfy constraint: Member must have length less than or equal to 50."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_create_policy_with_duplicate_tag():
conn = boto3.client("iam", region_name="us-east-1")
# With a duplicate tag:
with pytest.raises(ClientError) as ce:
conn.create_policy(
PolicyName="TestCreatePolicyWithTags3",
PolicyDocument=MOCK_POLICY,
Tags=[{"Key": "0", "Value": ""}, {"Key": "0", "Value": ""}],
)
assert (
"Duplicate tag keys found. Please note that Tag keys are case insensitive."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_create_policy_with_duplicate_tag_different_casing():
conn = boto3.client("iam", region_name="us-east-1")
# Duplicate tag with different casing:
with pytest.raises(ClientError) as ce:
conn.create_policy(
PolicyName="TestCreatePolicyWithTags3",
PolicyDocument=MOCK_POLICY,
Tags=[{"Key": "a", "Value": ""}, {"Key": "A", "Value": ""}],
)
assert (
"Duplicate tag keys found. Please note that Tag keys are case insensitive."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_create_policy_with_tag_containing_large_key():
conn = boto3.client("iam", region_name="us-east-1")
# With a really big key:
with pytest.raises(ClientError) as ce:
conn.create_policy(
PolicyName="TestCreatePolicyWithTags3",
PolicyDocument=MOCK_POLICY,
Tags=[{"Key": "0" * 129, "Value": ""}],
)
assert (
"Member must have length less than or equal to 128."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_create_policy_with_tag_containing_large_value():
conn = boto3.client("iam", region_name="us-east-1")
# With a really big value:
with pytest.raises(ClientError) as ce:
conn.create_policy(
PolicyName="TestCreatePolicyWithTags3",
PolicyDocument=MOCK_POLICY,
Tags=[{"Key": "0", "Value": "0" * 257}],
)
assert (
"Member must have length less than or equal to 256."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_create_policy_with_tag_containing_invalid_character():
conn = boto3.client("iam", region_name="us-east-1")
# With an invalid character:
with pytest.raises(ClientError) as ce:
conn.create_policy(
PolicyName="TestCreatePolicyWithTags3",
PolicyDocument=MOCK_POLICY,
Tags=[{"Key": "NOWAY!", "Value": ""}],
)
assert (
"Member must satisfy regular expression pattern: [\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+"
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_create_policy_with_no_tags():
"""Tests both the tag_policy and get_policy_tags capability"""
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
# Get without tags:
policy = conn.get_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy")
)["Policy"]
assert not policy.get("Tags")
@mock_iam()
def test_get_policy_with_tags():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# Get policy:
policy = conn.get_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy")
)["Policy"]
assert len(policy["Tags"]) == 2
assert policy["Tags"][0]["Key"] == "somekey"
assert policy["Tags"][0]["Value"] == "somevalue"
assert policy["Tags"][1]["Key"] == "someotherkey"
assert policy["Tags"][1]["Value"] == "someothervalue"
@mock_iam()
def test_list_policy_tags():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# List_policy_tags:
tags = conn.list_policy_tags(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy")
)
assert len(tags["Tags"]) == 2
assert tags["Tags"][0]["Key"] == "somekey"
assert tags["Tags"][0]["Value"] == "somevalue"
assert tags["Tags"][1]["Key"] == "someotherkey"
assert tags["Tags"][1]["Value"] == "someothervalue"
assert not tags["IsTruncated"]
assert not tags.get("Marker")
@mock_iam()
def test_list_policy_tags_pagination():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# Test pagination:
tags = conn.list_policy_tags(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
MaxItems=1,
)
assert len(tags["Tags"]) == 1
assert tags["IsTruncated"]
assert tags["Tags"][0]["Key"] == "somekey"
assert tags["Tags"][0]["Value"] == "somevalue"
assert tags["Marker"] == "1"
tags = conn.list_policy_tags(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Marker=tags["Marker"],
)
assert len(tags["Tags"]) == 1
assert tags["Tags"][0]["Key"] == "someotherkey"
assert tags["Tags"][0]["Value"] == "someothervalue"
assert not tags["IsTruncated"]
assert not tags.get("Marker")
@mock_iam()
def test_updating_existing_tag():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# Test updating an existing tag:
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[{"Key": "somekey", "Value": "somenewvalue"}],
)
tags = conn.list_policy_tags(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy")
)
assert len(tags["Tags"]) == 2
assert tags["Tags"][0]["Key"] == "somekey"
assert tags["Tags"][0]["Value"] == "somenewvalue"
@mock_iam()
def test_updating_existing_tag_with_empty_value():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# Empty is good:
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[{"Key": "somekey", "Value": ""}],
)
tags = conn.list_policy_tags(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy")
)
assert len(tags["Tags"]) == 2
assert tags["Tags"][0]["Key"] == "somekey"
assert tags["Tags"][0]["Value"] == ""
@mock_iam()
def test_updating_existing_tagged_policy_with_too_many_tags():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# With more than 50 tags:
with pytest.raises(ClientError) as ce:
too_many_tags = list(
map(lambda x: {"Key": str(x), "Value": str(x)}, range(0, 51))
)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=too_many_tags,
)
assert (
"failed to satisfy constraint: Member must have length less than or equal to 50."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_updating_existing_tagged_policy_with_duplicate_tag():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# With a duplicate tag:
with pytest.raises(ClientError) as ce:
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[{"Key": "0", "Value": ""}, {"Key": "0", "Value": ""}],
)
assert (
"Duplicate tag keys found. Please note that Tag keys are case insensitive."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_updating_existing_tagged_policy_with_duplicate_tag_different_casing():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# Duplicate tag with different casing:
with pytest.raises(ClientError) as ce:
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[{"Key": "a", "Value": ""}, {"Key": "A", "Value": ""}],
)
assert (
"Duplicate tag keys found. Please note that Tag keys are case insensitive."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_updating_existing_tagged_policy_with_large_key():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# With a really big key:
with pytest.raises(ClientError) as ce:
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[{"Key": "0" * 129, "Value": ""}],
)
assert (
"Member must have length less than or equal to 128."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_updating_existing_tagged_policy_with_large_value():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# With a really big value:
with pytest.raises(ClientError) as ce:
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[{"Key": "0", "Value": "0" * 257}],
)
assert (
"Member must have length less than or equal to 256."
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_updating_existing_tagged_policy_with_invalid_character():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestTagPolicy", PolicyDocument=MOCK_POLICY)
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# With an invalid character:
with pytest.raises(ClientError) as ce:
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestTagPolicy"),
Tags=[{"Key": "NOWAY!", "Value": ""}],
)
assert (
"Member must satisfy regular expression pattern: [\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+"
in ce.value.response["Error"]["Message"]
)
@mock_iam()
def test_tag_non_existant_policy():
conn = boto3.client("iam", region_name="us-east-1")
# With a policy that doesn't exist:
with pytest.raises(ClientError):
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "NotAPolicy"),
Tags=[{"Key": "some", "Value": "value"}],
)
@mock_iam
def test_untag_policy():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_policy(PolicyName="TestUnTagPolicy", PolicyDocument=MOCK_POLICY)
# With proper tag values:
conn.tag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestUnTagPolicy"),
Tags=[
{"Key": "somekey", "Value": "somevalue"},
{"Key": "someotherkey", "Value": "someothervalue"},
],
)
# Remove them:
conn.untag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestUnTagPolicy"),
TagKeys=["somekey"],
)
tags = conn.list_policy_tags(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestUnTagPolicy")
)
assert len(tags["Tags"]) == 1
assert tags["Tags"][0]["Key"] == "someotherkey"
assert tags["Tags"][0]["Value"] == "someothervalue"
# And again:
conn.untag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestUnTagPolicy"),
TagKeys=["someotherkey"],
)
tags = conn.list_policy_tags(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestUnTagPolicy")
)
assert not tags["Tags"]
# Test removing tags with invalid values:
# With more than 50 tags:
with pytest.raises(ClientError) as ce:
conn.untag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestUnTagPolicy"),
TagKeys=[str(x) for x in range(0, 51)],
)
assert (
"failed to satisfy constraint: Member must have length less than or equal to 50."
in ce.value.response["Error"]["Message"]
)
assert "tagKeys" in ce.value.response["Error"]["Message"]
# With a really big key:
with pytest.raises(ClientError) as ce:
conn.untag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestUnTagPolicy"),
TagKeys=["0" * 129],
)
assert (
"Member must have length less than or equal to 128."
in ce.value.response["Error"]["Message"]
)
assert "tagKeys" in ce.value.response["Error"]["Message"]
# With an invalid character:
with pytest.raises(ClientError) as ce:
conn.untag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "TestUnTagPolicy"),
TagKeys=["NOWAY!"],
)
assert (
"Member must satisfy regular expression pattern: [\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+"
in ce.value.response["Error"]["Message"]
)
assert "tagKeys" in ce.value.response["Error"]["Message"]
# With a policy that doesn't exist:
with pytest.raises(ClientError):
conn.untag_policy(
PolicyArn="arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, "NotAPolicy"),
TagKeys=["somevalue"],
)
# Has boto3 equivalent
@mock_iam_deprecated()
def test_create_user():
@ -3473,6 +4010,7 @@ def test_role_config_dict():
path="/",
policy_document=json.dumps(basic_policy),
policy_name="basic_policy",
tags=[],
)
.arn
)
@ -3974,6 +4512,7 @@ def test_policy_list_config_discovered_resources():
path="",
policy_document=json.dumps(basic_policy),
policy_name="policy{}".format(ix),
tags=[],
)
policies.append(
{"id": this_policy.id, "name": this_policy.name,}
@ -4057,6 +4596,7 @@ def test_policy_config_dict():
path="/",
policy_document=json.dumps(basic_policy),
policy_name="basic_policy",
tags=[],
)
.arn
)