Add tag & untag user (#3638)

* Add iam.tag_user

* Add iam.untag_user

* Fix Python2 error
This commit is contained in:
Anton Grübel 2021-02-01 12:37:54 +01:00 committed by GitHub
commit fe9f1dfe14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 165 additions and 81 deletions

View file

@ -45,6 +45,7 @@ from .utils import (
random_resource_id,
random_policy_id,
)
from ..utilities.tagging_service import TaggingService
class MFADevice(object):
@ -924,7 +925,7 @@ class Group(BaseModel):
class User(CloudFormationModel):
def __init__(self, name, path=None, tags=None):
def __init__(self, name, path=None):
self.name = name
self.id = random_resource_id()
self.path = path if path else "/"
@ -937,7 +938,6 @@ class User(CloudFormationModel):
self.password = None
self.password_reset_required = False
self.signing_certificates = {}
self.tags = tags
@property
def arn(self):
@ -1135,7 +1135,8 @@ class User(CloudFormationModel):
):
properties = cloudformation_json.get("Properties", {})
path = properties.get("Path")
return iam_backend.create_user(resource_physical_name, path)
user, _ = iam_backend.create_user(resource_physical_name, path)
return user
@classmethod
def update_from_cloudformation_json(
@ -1415,6 +1416,8 @@ class IAMBackend(BaseBackend):
self.account_summary = AccountSummary(self)
self.inline_policies = {}
self.access_keys = {}
self.tagger = TaggingService()
super(IAMBackend, self).__init__()
def _init_managed_policies(self):
@ -1978,16 +1981,16 @@ class IAMBackend(BaseBackend):
"EntityAlreadyExists", "User {0} already exists".format(user_name)
)
user = User(user_name, path, tags)
user = User(user_name, path)
self.tagger.tag_resource(user.arn, tags or [])
self.users[user_name] = user
return user
return user, self.tagger.list_tags_for_resource(user.arn)
def get_user(self, user_name):
user = None
try:
user = self.users[user_name]
except KeyError:
raise IAMNotFoundException("User {0} not found".format(user_name))
def get_user(self, name):
user = self.users.get(name)
if not user:
raise NoSuchEntity("The user with name {} cannot be found.".format(name))
return user
@ -2147,7 +2150,7 @@ class IAMBackend(BaseBackend):
def list_user_tags(self, user_name):
user = self.get_user(user_name)
return user.tags
return self.tagger.list_tags_for_resource(user.arn)
def put_user_policy(self, user_name, policy_name, policy_json):
user = self.get_user(user_name)
@ -2204,7 +2207,7 @@ class IAMBackend(BaseBackend):
try: # User may have been deleted before their access key...
user = self.get_user(key.user_name)
user.delete_access_key(key.access_key_id)
except IAMNotFoundException:
except NoSuchEntity:
pass
del self.access_keys[name]
@ -2250,7 +2253,7 @@ class IAMBackend(BaseBackend):
"CreateDate": user.created_iso_8601,
"PasswordLastUsed": None, # not supported
"PermissionsBoundary": {}, # ToDo: add put_user_permissions_boundary() functionality
"Tags": {}, # ToDo: add tag_user() functionality
"Tags": self.tagger.list_tags_for_resource(user.arn)["Tags"],
}
user.enable_mfa_device(
@ -2355,6 +2358,7 @@ class IAMBackend(BaseBackend):
code="DeleteConflict",
message="Cannot delete entity, must delete policies first.",
)
self.tagger.delete_all_tags_for_resource(user.arn)
del self.users[user_name]
def report_generated(self):
@ -2574,5 +2578,15 @@ class IAMBackend(BaseBackend):
inline_policy.unapply_policy(self)
del self.inline_policies[policy_id]
def tag_user(self, name, tags):
user = self.get_user(name)
self.tagger.tag_resource(user.arn, tags)
def untag_user(self, name, tag_keys):
user = self.get_user(name)
self.tagger.untag_resource_using_names(user.arn, tag_keys)
iam_backend = IAMBackend()

View file

@ -471,9 +471,9 @@ class IamResponse(BaseResponse):
user_name = self._get_param("UserName")
path = self._get_param("Path")
tags = self._get_multi_param("Tags.member")
user = iam_backend.create_user(user_name, path, tags)
user, user_tags = iam_backend.create_user(user_name, path, tags)
template = self.response_template(USER_TEMPLATE)
return template.render(action="Create", user=user)
return template.render(action="Create", user=user, tags=user_tags["Tags"])
def get_user(self):
user_name = self._get_param("UserName")
@ -572,7 +572,7 @@ class IamResponse(BaseResponse):
user_name = self._get_param("UserName")
tags = iam_backend.list_user_tags(user_name)
template = self.response_template(LIST_USER_TAGS_TEMPLATE)
return template.render(user_tags=tags or [])
return template.render(user_tags=tags["Tags"])
def put_user_policy(self):
user_name = self._get_param("UserName")
@ -989,6 +989,24 @@ class IamResponse(BaseResponse):
template = self.response_template(GET_ACCOUNT_SUMMARY_TEMPLATE)
return template.render(summary_map=account_summary.summary_map)
def tag_user(self):
name = self._get_param("UserName")
tags = self._get_multi_param("Tags.member")
iam_backend.tag_user(name, tags)
template = self.response_template(TAG_USER_TEMPLATE)
return template.render()
def untag_user(self):
name = self._get_param("UserName")
tag_keys = self._get_multi_param("TagKeys.member")
iam_backend.untag_user(name, tag_keys)
template = self.response_template(UNTAG_USER_TEMPLATE)
return template.render()
LIST_ENTITIES_FOR_POLICY_TEMPLATE = """<ListEntitiesForPolicyResponse>
<ListEntitiesForPolicyResult>
@ -1684,9 +1702,9 @@ USER_TEMPLATE = """<{{ action }}UserResponse>
<UserId>{{ user.id }}</UserId>
<CreateDate>{{ user.created_iso_8601 }}</CreateDate>
<Arn>{{ user.arn }}</Arn>
{% if user.tags %}
{% if tags %}
<Tags>
{% for tag in user.tags %}
{% for tag in tags %}
<member>
<Key>{{ tag['Key'] }}</Key>
<Value>{{ tag['Value'] }}</Value>
@ -2039,13 +2057,23 @@ LIST_VIRTUAL_MFA_DEVICES_TEMPLATE = """<ListVirtualMFADevicesResponse xmlns="htt
{% if device.enable_date %}
<EnableDate>{{ device.enabled_iso_8601 }}</EnableDate>
{% endif %}
{% if device.user %}
{% if device.user_attribute %}
<User>
<Path>{{ device.user.path }}</Path>
<UserName>{{ device.user.name }}</UserName>
<UserId>{{ device.user.id }}</UserId>
<CreateDate>{{ device.user.created_iso_8601 }}</CreateDate>
<Arn>{{ device.user.arn }}</Arn>
<Path>{{ device.user_attribute.Path }}</Path>
<UserName>{{ device.user_attribute.UserName }}</UserName>
<UserId>{{ device.user_attribute.UserId }}</UserId>
<CreateDate>{{ device.user_attribute.CreateDate }}</CreateDate>
<Arn>{{ device.user_attribute.Arn }}</Arn>
{% if device.user_attribute.Tags %}
<Tags>
{% for tag in device.user_attribute.Tags %}
<member>
<Key>{{ tag['Key'] }}</Key>
<Value>{{ tag['Value'] }}</Value>
</member>
{% endfor %}
</Tags>
{% endif %}
</User>
{% endif %}
</member>
@ -2514,3 +2542,17 @@ GET_ACCOUNT_SUMMARY_TEMPLATE = """<GetAccountSummaryResponse xmlns="https://iam.
<RequestId>85cb9b90-ac28-11e4-a88d-97964EXAMPLE</RequestId>
</ResponseMetadata>
</GetAccountSummaryResponse>"""
TAG_USER_TEMPLATE = """<TagUserResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<ResponseMetadata>
<RequestId>EXAMPLE8-90ab-cdef-fedc-ba987EXAMPLE</RequestId>
</ResponseMetadata>
</TagUserResponse>"""
UNTAG_USER_TEMPLATE = """<UntagUserResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<ResponseMetadata>
<RequestId>EXAMPLE8-90ab-cdef-fedc-ba987EXAMPLE</RequestId>
</ResponseMetadata>
</UntagUserResponse>"""