Add iam.get_account_password_policy

This commit is contained in:
gruebel 2019-10-28 23:50:17 +01:00
parent 06581391bd
commit 65fa8f1a1b
5 changed files with 108 additions and 7 deletions

View File

@ -3262,8 +3262,7 @@
- [ ] describe_events - [ ] describe_events
## iam ## iam
60% implemented 61% implemented- [ ] add_client_id_to_open_id_connect_provider
- [ ] add_client_id_to_open_id_connect_provider
- [X] add_role_to_instance_profile - [X] add_role_to_instance_profile
- [X] add_user_to_group - [X] add_user_to_group
- [X] attach_group_policy - [X] attach_group_policy
@ -3317,7 +3316,7 @@
- [ ] generate_service_last_accessed_details - [ ] generate_service_last_accessed_details
- [X] get_access_key_last_used - [X] get_access_key_last_used
- [X] get_account_authorization_details - [X] get_account_authorization_details
- [ ] get_account_password_policy - [X] get_account_password_policy
- [ ] get_account_summary - [ ] get_account_summary
- [ ] get_context_keys_for_custom_policy - [ ] get_context_keys_for_custom_policy
- [ ] get_context_keys_for_principal_policy - [ ] get_context_keys_for_principal_policy

View File

@ -127,4 +127,13 @@ class InvalidInput(RESTError):
code = 400 code = 400
def __init__(self, message): def __init__(self, message):
super(InvalidInput, self).__init__("InvalidInput", message) super(InvalidInput, self).__init__(
'InvalidInput', message)
class NoSuchEntity(RESTError):
code = 404
def __init__(self, message):
super(NoSuchEntity, self).__init__(
'NoSuchEntity', message)

View File

@ -35,6 +35,7 @@ from .exceptions import (
EntityAlreadyExists, EntityAlreadyExists,
ValidationError, ValidationError,
InvalidInput, InvalidInput,
NoSuchEntity,
) )
from .utils import ( from .utils import (
random_access_key, random_access_key,
@ -1671,5 +1672,11 @@ class IAMBackend(BaseBackend):
require_uppercase_characters require_uppercase_characters
) )
def get_account_password_policy(self):
if not self.account_password_policy:
raise NoSuchEntity('The Password Policy with domain name {} cannot be found.'.format(ACCOUNT_ID))
return self.account_password_policy
iam_backend = IAMBackend() iam_backend = IAMBackend()

View File

@ -857,6 +857,12 @@ class IamResponse(BaseResponse):
template = self.response_template(UPDATE_ACCOUNT_PASSWORD_POLICY_TEMPLATE) template = self.response_template(UPDATE_ACCOUNT_PASSWORD_POLICY_TEMPLATE)
return template.render() return template.render()
def get_account_password_policy(self):
account_password_policy = iam_backend.get_account_password_policy()
template = self.response_template(GET_ACCOUNT_PASSWORD_POLICY_TEMPLATE)
return template.render(password_policy=account_password_policy)
LIST_ENTITIES_FOR_POLICY_TEMPLATE = """<ListEntitiesForPolicyResponse> LIST_ENTITIES_FOR_POLICY_TEMPLATE = """<ListEntitiesForPolicyResponse>
<ListEntitiesForPolicyResult> <ListEntitiesForPolicyResult>
@ -2196,3 +2202,30 @@ UPDATE_ACCOUNT_PASSWORD_POLICY_TEMPLATE = """<UpdateAccountPasswordPolicyRespons
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId> <RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ResponseMetadata> </ResponseMetadata>
</UpdateAccountPasswordPolicyResponse>""" </UpdateAccountPasswordPolicyResponse>"""
GET_ACCOUNT_PASSWORD_POLICY_TEMPLATE = """<GetAccountPasswordPolicyResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<GetAccountPasswordPolicyResult>
<PasswordPolicy>
<AllowUsersToChangePassword>{{ password_policy.allow_users_to_change_password | lower }}</AllowUsersToChangePassword>
<ExpirePasswords>{{ password_policy.expire_passwords | lower }}</ExpirePasswords>
{% if password_policy.hard_expiry %}
<HardExpiry>{{ password_policy.hard_expiry | lower }}</HardExpiry>
{% endif %}
{% if password_policy.max_password_age %}
<MaxPasswordAge>{{ password_policy.max_password_age }}</MaxPasswordAge>
{% endif %}
<MinimumPasswordLength>{{ password_policy.minimum_password_length }}</MinimumPasswordLength>
{% if password_policy.password_reuse_prevention %}
<PasswordReusePrevention>{{ password_policy.password_reuse_prevention }}</PasswordReusePrevention>
{% endif %}
<RequireLowercaseCharacters>{{ password_policy.require_lowercase_characters | lower }}</RequireLowercaseCharacters>
<RequireNumbers>{{ password_policy.require_numbers | lower }}</RequireNumbers>
<RequireSymbols>{{ password_policy.require_symbols | lower }}</RequireSymbols>
<RequireUppercaseCharacters>{{ password_policy.require_uppercase_characters | lower }}</RequireUppercaseCharacters>
</PasswordPolicy>
</GetAccountPasswordPolicyResult>
<ResponseMetadata>
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ResponseMetadata>
</GetAccountPasswordPolicyResponse>"""

View File

@ -2200,17 +2200,29 @@ def test_list_open_id_connect_providers():
@mock_iam @mock_iam
def test_update_account_password_policy(): def test_update_account_password_policy():
client = boto3.client('iam', region_name='us-east-1') client = boto3.client('iam', region_name='us-east-1')
client.update_account_password_policy() client.update_account_password_policy()
response = client.get_account_password_policy()
response['PasswordPolicy'].should.equal({
'AllowUsersToChangePassword': False,
'ExpirePasswords': False,
'MinimumPasswordLength': 6,
'RequireLowercaseCharacters': False,
'RequireNumbers': False,
'RequireSymbols': False,
'RequireUppercaseCharacters': False
})
@mock_iam @mock_iam
def test_update_account_password_policy_errors(): def test_update_account_password_policy_errors():
client = boto3.client('iam', region_name='us-east-1') client = boto3.client('iam', region_name='us-east-1')
client.update_account_password_policy.when.called_with( client.update_account_password_policy.when.called_with(
MaxPasswordAge = 1096, MaxPasswordAge=1096,
MinimumPasswordLength = 129, MinimumPasswordLength=129,
PasswordReusePrevention = 25 PasswordReusePrevention=25
).should.throw( ).should.throw(
ClientError, ClientError,
'3 validation errors detected: ' '3 validation errors detected: '
@ -2221,3 +2233,44 @@ def test_update_account_password_policy_errors():
'Value "1096" at "maxPasswordAge" failed to satisfy constraint: ' 'Value "1096" at "maxPasswordAge" failed to satisfy constraint: '
'Member must have value less than or equal to 1095' 'Member must have value less than or equal to 1095'
) )
@mock_iam
def test_get_account_password_policy():
client = boto3.client('iam', region_name='us-east-1')
client.update_account_password_policy(
AllowUsersToChangePassword=True,
HardExpiry=True,
MaxPasswordAge=60,
MinimumPasswordLength=10,
PasswordReusePrevention=3,
RequireLowercaseCharacters=True,
RequireNumbers=True,
RequireSymbols=True,
RequireUppercaseCharacters=True
)
response = client.get_account_password_policy()
response['PasswordPolicy'].should.equal({
'AllowUsersToChangePassword': True,
'ExpirePasswords': True,
'HardExpiry': True,
'MaxPasswordAge': 60,
'MinimumPasswordLength': 10,
'PasswordReusePrevention': 3,
'RequireLowercaseCharacters': True,
'RequireNumbers': True,
'RequireSymbols': True,
'RequireUppercaseCharacters': True
})
@mock_iam
def test_get_account_password_policy_errors():
client = boto3.client('iam', region_name='us-east-1')
client.get_account_password_policy.when.called_with().should.throw(
ClientError,
'The Password Policy with domain name 123456789012 cannot be found.'
)