Merge pull request #1224 from JackDanger/jack/implement-attached-group-policies
Implement IAM attached group policies
This commit is contained in:
commit
0c07c4467a
@ -74,21 +74,13 @@ class ManagedPolicy(Policy):
|
|||||||
|
|
||||||
is_attachable = True
|
is_attachable = True
|
||||||
|
|
||||||
def attach_to_role(self, role):
|
def attach_to(self, obj):
|
||||||
self.attachment_count += 1
|
self.attachment_count += 1
|
||||||
role.managed_policies[self.name] = self
|
obj.managed_policies[self.name] = self
|
||||||
|
|
||||||
def detach_from_role(self, role):
|
def detach_from(self, obj):
|
||||||
self.attachment_count -= 1
|
self.attachment_count -= 1
|
||||||
del role.managed_policies[self.name]
|
del obj.managed_policies[self.name]
|
||||||
|
|
||||||
def attach_to_user(self, user):
|
|
||||||
self.attachment_count += 1
|
|
||||||
user.managed_policies[self.name] = self
|
|
||||||
|
|
||||||
def detach_from_user(self, user):
|
|
||||||
self.attachment_count -= 1
|
|
||||||
del user.managed_policies[self.name]
|
|
||||||
|
|
||||||
|
|
||||||
class AWSManagedPolicy(ManagedPolicy):
|
class AWSManagedPolicy(ManagedPolicy):
|
||||||
@ -249,6 +241,7 @@ class Group(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.users = []
|
self.users = []
|
||||||
|
self.managed_policies = {}
|
||||||
self.policies = {}
|
self.policies = {}
|
||||||
|
|
||||||
def get_cfn_attribute(self, attribute_name):
|
def get_cfn_attribute(self, attribute_name):
|
||||||
@ -423,25 +416,47 @@ class IAMBackend(BaseBackend):
|
|||||||
def attach_role_policy(self, policy_arn, role_name):
|
def attach_role_policy(self, policy_arn, role_name):
|
||||||
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
||||||
policy = arns[policy_arn]
|
policy = arns[policy_arn]
|
||||||
policy.attach_to_role(self.get_role(role_name))
|
policy.attach_to(self.get_role(role_name))
|
||||||
|
|
||||||
def detach_role_policy(self, policy_arn, role_name):
|
def detach_role_policy(self, policy_arn, role_name):
|
||||||
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
||||||
try:
|
try:
|
||||||
policy = arns[policy_arn]
|
policy = arns[policy_arn]
|
||||||
policy.detach_from_role(self.get_role(role_name))
|
policy.detach_from(self.get_role(role_name))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise IAMNotFoundException("Policy {0} was not found.".format(policy_arn))
|
raise IAMNotFoundException("Policy {0} was not found.".format(policy_arn))
|
||||||
|
|
||||||
|
def attach_group_policy(self, policy_arn, group_name):
|
||||||
|
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
||||||
|
try:
|
||||||
|
policy = arns[policy_arn]
|
||||||
|
except KeyError:
|
||||||
|
raise IAMNotFoundException("Policy {0} was not found.".format(policy_arn))
|
||||||
|
policy.attach_to(self.get_group(group_name))
|
||||||
|
|
||||||
|
def detach_group_policy(self, policy_arn, group_name):
|
||||||
|
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
||||||
|
try:
|
||||||
|
policy = arns[policy_arn]
|
||||||
|
except KeyError:
|
||||||
|
raise IAMNotFoundException("Policy {0} was not found.".format(policy_arn))
|
||||||
|
policy.detach_from(self.get_group(group_name))
|
||||||
|
|
||||||
def attach_user_policy(self, policy_arn, user_name):
|
def attach_user_policy(self, policy_arn, user_name):
|
||||||
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
||||||
|
try:
|
||||||
policy = arns[policy_arn]
|
policy = arns[policy_arn]
|
||||||
policy.attach_to_user(self.get_user(user_name))
|
except KeyError:
|
||||||
|
raise IAMNotFoundException("Policy {0} was not found.".format(policy_arn))
|
||||||
|
policy.attach_to(self.get_user(user_name))
|
||||||
|
|
||||||
def detach_user_policy(self, policy_arn, user_name):
|
def detach_user_policy(self, policy_arn, user_name):
|
||||||
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
||||||
|
try:
|
||||||
policy = arns[policy_arn]
|
policy = arns[policy_arn]
|
||||||
policy.detach_from_user(self.get_user(user_name))
|
except KeyError:
|
||||||
|
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):
|
def create_policy(self, description, path, policy_document, policy_name):
|
||||||
policy = ManagedPolicy(
|
policy = ManagedPolicy(
|
||||||
@ -458,39 +473,15 @@ class IAMBackend(BaseBackend):
|
|||||||
|
|
||||||
def list_attached_role_policies(self, role_name, marker=None, max_items=100, path_prefix='/'):
|
def list_attached_role_policies(self, role_name, marker=None, max_items=100, path_prefix='/'):
|
||||||
policies = self.get_role(role_name).managed_policies.values()
|
policies = self.get_role(role_name).managed_policies.values()
|
||||||
|
return self._filter_attached_policies(policies, marker, max_items, path_prefix)
|
||||||
|
|
||||||
if path_prefix:
|
def list_attached_group_policies(self, group_name, marker=None, max_items=100, path_prefix='/'):
|
||||||
policies = [p for p in policies if p.path.startswith(path_prefix)]
|
policies = self.get_group(group_name).managed_policies.values()
|
||||||
|
return self._filter_attached_policies(policies, marker, max_items, path_prefix)
|
||||||
policies = sorted(policies, key=lambda policy: policy.name)
|
|
||||||
start_idx = int(marker) if marker else 0
|
|
||||||
|
|
||||||
policies = policies[start_idx:start_idx + max_items]
|
|
||||||
|
|
||||||
if len(policies) < max_items:
|
|
||||||
marker = None
|
|
||||||
else:
|
|
||||||
marker = str(start_idx + max_items)
|
|
||||||
|
|
||||||
return policies, marker
|
|
||||||
|
|
||||||
def list_attached_user_policies(self, user_name, marker=None, max_items=100, path_prefix='/'):
|
def list_attached_user_policies(self, user_name, marker=None, max_items=100, path_prefix='/'):
|
||||||
policies = self.get_user(user_name).managed_policies.values()
|
policies = self.get_user(user_name).managed_policies.values()
|
||||||
|
return self._filter_attached_policies(policies, marker, max_items, path_prefix)
|
||||||
if path_prefix:
|
|
||||||
policies = [p for p in policies if p.path.startswith(path_prefix)]
|
|
||||||
|
|
||||||
policies = sorted(policies, key=lambda policy: policy.name)
|
|
||||||
start_idx = int(marker) if marker else 0
|
|
||||||
|
|
||||||
policies = policies[start_idx:start_idx + max_items]
|
|
||||||
|
|
||||||
if len(policies) < max_items:
|
|
||||||
marker = None
|
|
||||||
else:
|
|
||||||
marker = str(start_idx + max_items)
|
|
||||||
|
|
||||||
return policies, marker
|
|
||||||
|
|
||||||
def list_policies(self, marker, max_items, only_attached, path_prefix, scope):
|
def list_policies(self, marker, max_items, only_attached, path_prefix, scope):
|
||||||
policies = self.managed_policies.values()
|
policies = self.managed_policies.values()
|
||||||
@ -504,6 +495,9 @@ class IAMBackend(BaseBackend):
|
|||||||
policies = [p for p in policies if not isinstance(
|
policies = [p for p in policies if not isinstance(
|
||||||
p, AWSManagedPolicy)]
|
p, AWSManagedPolicy)]
|
||||||
|
|
||||||
|
return self._filter_attached_policies(policies, marker, max_items, path_prefix)
|
||||||
|
|
||||||
|
def _filter_attached_policies(self, policies, marker, max_items, path_prefix):
|
||||||
if path_prefix:
|
if path_prefix:
|
||||||
policies = [p for p in policies if p.path.startswith(path_prefix)]
|
policies = [p for p in policies if p.path.startswith(path_prefix)]
|
||||||
|
|
||||||
|
@ -20,6 +20,20 @@ class IamResponse(BaseResponse):
|
|||||||
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
||||||
return template.render(name="DetachRolePolicyResponse")
|
return template.render(name="DetachRolePolicyResponse")
|
||||||
|
|
||||||
|
def attach_group_policy(self):
|
||||||
|
policy_arn = self._get_param('PolicyArn')
|
||||||
|
group_name = self._get_param('GroupName')
|
||||||
|
iam_backend.attach_group_policy(policy_arn, group_name)
|
||||||
|
template = self.response_template(ATTACH_GROUP_POLICY_TEMPLATE)
|
||||||
|
return template.render()
|
||||||
|
|
||||||
|
def detach_group_policy(self):
|
||||||
|
policy_arn = self._get_param('PolicyArn')
|
||||||
|
group_name = self._get_param('GroupName')
|
||||||
|
iam_backend.detach_group_policy(policy_arn, group_name)
|
||||||
|
template = self.response_template(DETACH_GROUP_POLICY_TEMPLATE)
|
||||||
|
return template.render()
|
||||||
|
|
||||||
def attach_user_policy(self):
|
def attach_user_policy(self):
|
||||||
policy_arn = self._get_param('PolicyArn')
|
policy_arn = self._get_param('PolicyArn')
|
||||||
user_name = self._get_param('UserName')
|
user_name = self._get_param('UserName')
|
||||||
@ -54,6 +68,17 @@ class IamResponse(BaseResponse):
|
|||||||
template = self.response_template(LIST_ATTACHED_ROLE_POLICIES_TEMPLATE)
|
template = self.response_template(LIST_ATTACHED_ROLE_POLICIES_TEMPLATE)
|
||||||
return template.render(policies=policies, marker=marker)
|
return template.render(policies=policies, marker=marker)
|
||||||
|
|
||||||
|
def list_attached_group_policies(self):
|
||||||
|
marker = self._get_param('Marker')
|
||||||
|
max_items = self._get_int_param('MaxItems', 100)
|
||||||
|
path_prefix = self._get_param('PathPrefix', '/')
|
||||||
|
group_name = self._get_param('GroupName')
|
||||||
|
policies, marker = iam_backend.list_attached_group_policies(
|
||||||
|
group_name, marker=marker, max_items=max_items,
|
||||||
|
path_prefix=path_prefix)
|
||||||
|
template = self.response_template(LIST_ATTACHED_GROUP_POLICIES_TEMPLATE)
|
||||||
|
return template.render(policies=policies, marker=marker)
|
||||||
|
|
||||||
def list_attached_user_policies(self):
|
def list_attached_user_policies(self):
|
||||||
marker = self._get_param('Marker')
|
marker = self._get_param('Marker')
|
||||||
max_items = self._get_int_param('MaxItems', 100)
|
max_items = self._get_int_param('MaxItems', 100)
|
||||||
@ -520,6 +545,18 @@ DETACH_USER_POLICY_TEMPLATE = """<DetachUserPolicyResponse>
|
|||||||
</ResponseMetadata>
|
</ResponseMetadata>
|
||||||
</DetachUserPolicyResponse>"""
|
</DetachUserPolicyResponse>"""
|
||||||
|
|
||||||
|
ATTACH_GROUP_POLICY_TEMPLATE = """<AttachGroupPolicyResponse>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</AttachGroupPolicyResponse>"""
|
||||||
|
|
||||||
|
DETACH_GROUP_POLICY_TEMPLATE = """<DetachGroupPolicyResponse>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</DetachGroupPolicyResponse>"""
|
||||||
|
|
||||||
CREATE_POLICY_TEMPLATE = """<CreatePolicyResponse>
|
CREATE_POLICY_TEMPLATE = """<CreatePolicyResponse>
|
||||||
<CreatePolicyResult>
|
<CreatePolicyResult>
|
||||||
<Policy>
|
<Policy>
|
||||||
@ -560,6 +597,28 @@ LIST_ATTACHED_ROLE_POLICIES_TEMPLATE = """<ListAttachedRolePoliciesResponse>
|
|||||||
</ResponseMetadata>
|
</ResponseMetadata>
|
||||||
</ListAttachedRolePoliciesResponse>"""
|
</ListAttachedRolePoliciesResponse>"""
|
||||||
|
|
||||||
|
LIST_ATTACHED_GROUP_POLICIES_TEMPLATE = """<ListAttachedGroupPoliciesResponse>
|
||||||
|
<ListAttachedGroupPoliciesResult>
|
||||||
|
{% if marker is none %}
|
||||||
|
<IsTruncated>false</IsTruncated>
|
||||||
|
{% else %}
|
||||||
|
<IsTruncated>true</IsTruncated>
|
||||||
|
<Marker>{{ marker }}</Marker>
|
||||||
|
{% endif %}
|
||||||
|
<AttachedPolicies>
|
||||||
|
{% for policy in policies %}
|
||||||
|
<member>
|
||||||
|
<PolicyName>{{ policy.name }}</PolicyName>
|
||||||
|
<PolicyArn>{{ policy.arn }}</PolicyArn>
|
||||||
|
</member>
|
||||||
|
{% endfor %}
|
||||||
|
</AttachedPolicies>
|
||||||
|
</ListAttachedGroupPoliciesResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</ListAttachedGroupPoliciesResponse>"""
|
||||||
|
|
||||||
LIST_ATTACHED_USER_POLICIES_TEMPLATE = """<ListAttachedUserPoliciesResponse>
|
LIST_ATTACHED_USER_POLICIES_TEMPLATE = """<ListAttachedUserPoliciesResponse>
|
||||||
<ListAttachedUserPoliciesResult>
|
<ListAttachedUserPoliciesResult>
|
||||||
{% if marker is none %}
|
{% if marker is none %}
|
||||||
|
@ -82,6 +82,26 @@ def test_put_group_policy():
|
|||||||
conn.put_group_policy('my-group', 'my-policy', '{"some": "json"}')
|
conn.put_group_policy('my-group', 'my-policy', '{"some": "json"}')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam
|
||||||
|
def test_attach_group_policies():
|
||||||
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
|
conn.create_group(GroupName='my-group')
|
||||||
|
conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty
|
||||||
|
policy_arn = 'arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role'
|
||||||
|
conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty
|
||||||
|
conn.attach_group_policy(GroupName='my-group', PolicyArn=policy_arn)
|
||||||
|
conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.equal(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'PolicyName': 'AmazonElasticMapReduceforEC2Role',
|
||||||
|
'PolicyArn': policy_arn,
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
conn.detach_group_policy(GroupName='my-group', PolicyArn=policy_arn)
|
||||||
|
conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty
|
||||||
|
|
||||||
|
|
||||||
@mock_iam_deprecated()
|
@mock_iam_deprecated()
|
||||||
def test_get_group_policy():
|
def test_get_group_policy():
|
||||||
conn = boto.connect_iam()
|
conn = boto.connect_iam()
|
||||||
@ -90,7 +110,8 @@ def test_get_group_policy():
|
|||||||
conn.get_group_policy('my-group', 'my-policy')
|
conn.get_group_policy('my-group', 'my-policy')
|
||||||
|
|
||||||
conn.put_group_policy('my-group', 'my-policy', '{"some": "json"}')
|
conn.put_group_policy('my-group', 'my-policy', '{"some": "json"}')
|
||||||
policy = conn.get_group_policy('my-group', 'my-policy')
|
conn.get_group_policy('my-group', 'my-policy')
|
||||||
|
|
||||||
|
|
||||||
@mock_iam_deprecated()
|
@mock_iam_deprecated()
|
||||||
def test_get_all_group_policies():
|
def test_get_all_group_policies():
|
||||||
@ -107,6 +128,6 @@ def test_get_all_group_policies():
|
|||||||
def test_list_group_policies():
|
def test_list_group_policies():
|
||||||
conn = boto3.client('iam', region_name='us-east-1')
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
conn.create_group(GroupName='my-group')
|
conn.create_group(GroupName='my-group')
|
||||||
policies = conn.list_group_policies(GroupName='my-group')['PolicyNames'].should.be.empty
|
conn.list_group_policies(GroupName='my-group')['PolicyNames'].should.be.empty
|
||||||
conn.put_group_policy(GroupName='my-group', PolicyName='my-policy', PolicyDocument='{"some": "json"}')
|
conn.put_group_policy(GroupName='my-group', PolicyName='my-policy', PolicyDocument='{"some": "json"}')
|
||||||
policies = conn.list_group_policies(GroupName='my-group')['PolicyNames'].should.equal(['my-policy'])
|
conn.list_group_policies(GroupName='my-group')['PolicyNames'].should.equal(['my-policy'])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user