Improve consistency of IAM_{role,user,group} behaviour (#64258)

* iam_user: use AnsibleAWSModule.client to fetch connection rather than C&P code

* iam_role: Add deprecation warning so we can switch purge_polices default behaviour from true to false

* iam_user/role/group: Rename 'managed_policy' and 'purge_policy'

Rename from singluar to plural (we accept a *list* of policies), and add aliases for the old values.

* Cleanup documentation

* Changelog
This commit is contained in:
Mark Chappell 2019-11-21 22:38:44 +01:00 committed by Jill R
parent 784e507671
commit 6e652ae6df
5 changed files with 76 additions and 60 deletions

View file

@ -0,0 +1,5 @@
deprecated_features:
- 'iam_role: The default value of the purge_policies has been deprecated and will change from true to false in Ansible 2.14'
minor_changes:
- 'iam_role, iam_user and iam_group: the managed_policy option has been renamed to managed_policies (with an alias added)'
- 'iam_role, iam_user and iam_group: the purge_policy option has been renamed to purge_policies (with an alias added)'

View file

@ -58,7 +58,7 @@ The following functionality will be removed in Ansible 2.14. Please update updat
* The :ref:`openssl_csr <openssl_csr_module>` module's option ``version`` no longer supports values other than ``1`` (the current only standardized CSR version).
* :ref:`docker_container <docker_container_module>`: the ``trust_image_content`` option will be removed. It has always been ignored by the module.
* :ref:`iam_managed_policy <iam_managed_policy_module>`: the ``fail_on_delete`` option wil be removed. It has always been ignored by the module.
* :ref:`iam_managed_policy <iam_managed_policy_module>`: the ``fail_on_delete`` option will be removed. It has always been ignored by the module.
* :ref:`s3_lifecycle <s3_lifecycle_module>`: the ``requester_pays`` option will be removed. It has always been ignored by the module.
* :ref:`s3_sync <s3_sync_module>`: the ``retries`` option will be removed. It has always been ignored by the module.
* The return values ``err`` and ``out`` of :ref:`docker_stack <docker_stack_module>` have been deprecated. Use ``stdout`` and ``stderr`` from now on instead.
@ -76,6 +76,7 @@ The following functionality will change in Ansible 2.14. Please update update yo
* The :ref:`docker_container <docker_container_module>` module has a new option, ``container_default_behavior``, whose default value will change from ``compatibility`` to ``no_defaults``. Set to an explicit value to avoid deprecation warnings.
* :ref:`iam_policy <iam_policy_module>`: the default value for the ``skip_duplicates`` option will change from ``true`` to ``false``. To maintain the existing behavior explicitly set it to ``true``.
* :ref:`iam_role <iam_role_module>`: the ``purge_policies`` option (also know as ``purge_policy``) default value will change from ``true`` to ``false``
The following modules will be removed in Ansible 2.14. Please update your playbooks accordingly.

View file

@ -26,7 +26,7 @@ DOCUMENTATION = '''
module: iam_group
short_description: Manage AWS IAM groups
description:
- Manage AWS IAM groups
- Manage AWS IAM groups.
version_added: "2.4"
author:
- Nick Aslanidis (@naslanidis)
@ -37,31 +37,36 @@ options:
- The name of the group to create.
required: true
type: str
managed_policy:
managed_policies:
description:
- A list of managed policy ARNs or friendly names to attach to the role. To embed an inline policy, use M(iam_policy).
- A list of managed policy ARNs or friendly names to attach to the role.
- To embed an inline policy, use M(iam_policy).
required: false
type: list
elements: str
aliases: ['managed_policy']
users:
description:
- A list of existing users to add as members of the group.
required: false
type: list
elements: str
state:
description:
- Create or remove the IAM group
- Create or remove the IAM group.
required: true
choices: [ 'present', 'absent' ]
type: str
purge_policy:
purge_policies:
description:
- Detach policy which not included in managed_policy list
- When I(purge_policies=true) any managed policies not listed in I(managed_policies) will be detatched.
required: false
default: false
type: bool
aliases: ['purge_policy', 'purge_managed_policies']
purge_users:
description:
- Detach users which not included in users list
- When I(purge_users=true) users which are not included in I(users) will be detached.
required: false
default: false
type: bool
@ -82,14 +87,14 @@ EXAMPLES = '''
# Create a group and attach a managed policy using its ARN
- iam_group:
name: testgroup1
managed_policy:
managed_policies:
- arn:aws:iam::aws:policy/AmazonSNSFullAccess
state: present
# Create a group with users as members and attach a managed policy using its ARN
- iam_group:
name: testgroup1
managed_policy:
managed_policies:
- arn:aws:iam::aws:policy/AmazonSNSFullAccess
users:
- test_user1
@ -100,12 +105,12 @@ EXAMPLES = '''
- iam_group:
name: testgroup1
state: present
purge_policy: true
purge_policies: true
# Remove all group members from an existing group
- iam_group:
name: testgroup1
managed_policy:
managed_policies:
- arn:aws:iam::aws:policy/AmazonSNSFullAccess
purge_users: true
state: present
@ -233,10 +238,10 @@ def create_or_update_group(connection, module):
params = dict()
params['GroupName'] = module.params.get('name')
managed_policies = module.params.get('managed_policy')
managed_policies = module.params.get('managed_policies')
users = module.params.get('users')
purge_users = module.params.get('purge_users')
purge_policy = module.params.get('purge_policy')
purge_policies = module.params.get('purge_policies')
changed = False
if managed_policies:
managed_policies = convert_friendly_names_to_arns(connection, module, managed_policies)
@ -267,7 +272,7 @@ def create_or_update_group(connection, module):
current_attached_policies_arn_list.append(policy['PolicyArn'])
# If managed_policies has a single empty element we want to remove all attached policies
if purge_policy:
if purge_policies:
# Detach policies not present
for policy_arn in list(set(current_attached_policies_arn_list) - set(managed_policies)):
changed = True
@ -408,11 +413,11 @@ def main():
argument_spec = dict(
name=dict(required=True),
managed_policy=dict(default=[], type='list'),
managed_policies=dict(default=[], type='list', aliases=['managed_policy']),
users=dict(default=[], type='list'),
state=dict(choices=['present', 'absent'], required=True),
purge_users=dict(default=False, type='bool'),
purge_policy=dict(default=False, type='bool')
purge_policies=dict(default=False, type='bool', aliases=['purge_policy', 'purge_managed_policies'])
)
module = AnsibleAWSModule(

View file

@ -14,7 +14,7 @@ DOCUMENTATION = '''
module: iam_role
short_description: Manage AWS IAM roles
description:
- Manage AWS IAM roles
- Manage AWS IAM roles.
version_added: "2.3"
author: "Rob White (@wimnat)"
options:
@ -30,15 +30,15 @@ options:
type: str
description:
description:
- Provide a description of the new role.
- Provides a description of the role.
version_added: "2.5"
type: str
boundary:
description:
- The ARN of an IAM managed policy to use to restrict the permissions this role can pass on to IAM roles/users that it creates.
- Boundaries cannot be set on Instance Profiles, so if this option is specified then I(create_instance_profile) must be false.
- Boundaries cannot be set on Instance Profiles, as such if this option is specified then I(create_instance_profile) must be C(false).
- This is intended for roles/users that have permissions to create new IAM objects.
- For more information on boundaries, see U(https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html)
- For more information on boundaries, see U(https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html).
- Requires botocore 1.10.57 or above.
aliases: [boundary_policy_arn]
version_added: "2.7"
@ -46,13 +46,14 @@ options:
assume_role_policy_document:
description:
- The trust relationship policy document that grants an entity permission to assume the role.
- "This parameter is required when I(state=present)."
- This parameter is required when I(state=present).
type: json
managed_policy:
managed_policies:
description:
- A list of managed policy ARNs or, since Ansible 2.4, a list of either managed policy ARNs or friendly names.
To embed an inline policy, use M(iam_policy). To remove existing policies, use an empty list item.
aliases: [ managed_policies ]
- To remove all policies set I(purge_polices=true) and I(managed_policies=[None]).
- To embed an inline policy, use M(iam_policy).
aliases: ['managed_policy']
type: list
max_session_duration:
description:
@ -62,10 +63,11 @@ options:
type: int
purge_policies:
description:
- Detaches any managed policies not listed in the I(managed_policy) option. Set to false if you want to attach policies elsewhere.
default: true
- When I(purge_policies=true) any managed policies not listed in I(managed_policies) will be detatched.
- By default I(purge_policies=true). In Ansible 2.14 this will be changed to I(purge_policies=false).
version_added: "2.5"
type: bool
aliases: ['purge_policy', 'purge_managed_policies']
state:
description:
- Create or remove the IAM role.
@ -80,8 +82,8 @@ options:
type: bool
delete_instance_profile:
description:
- When deleting a role will also delete the instance profile created with
the same name as the role.
- When I(delete_instance_profile=true) and I(state=absent) deleting a role will also delete the instance
profile created with the same I(name) as the role.
- Only applies when I(state=absent).
default: false
version_added: "2.10"
@ -119,14 +121,14 @@ EXAMPLES = '''
iam_role:
name: mynewrole
assume_role_policy_document: "{{ lookup('file','policy.json') }}"
managed_policy:
managed_policies:
- arn:aws:iam::aws:policy/PowerUserAccess
- name: Keep the role created above but remove all managed policies
iam_role:
name: mynewrole
assume_role_policy_document: "{{ lookup('file','policy.json') }}"
managed_policy: []
managed_policies: []
- name: Delete the role
iam_role:
@ -276,7 +278,10 @@ def create_or_update_role(connection, module):
params['Description'] = module.params.get('description')
if module.params.get('boundary') is not None:
params['PermissionsBoundary'] = module.params.get('boundary')
managed_policies = module.params.get('managed_policy')
managed_policies = module.params.get('managed_policies')
purge_policies = module.params.get('purge_policies')
if purge_policies is None:
purge_policies = True
create_instance_profile = module.params.get('create_instance_profile')
if managed_policies:
managed_policies = convert_friendly_names_to_arns(connection, module, managed_policies)
@ -320,7 +325,7 @@ def create_or_update_role(connection, module):
current_attached_policies_arn_list = [policy['PolicyArn'] for policy in current_attached_policies]
# If a single empty list item then all managed policies to be removed
if len(managed_policies) == 1 and not managed_policies[0] and module.params.get('purge_policies'):
if len(managed_policies) == 1 and not managed_policies[0] and purge_policies:
# Detach policies not present
if remove_policies(connection, module, set(current_attached_policies_arn_list) - set(managed_policies), params):
@ -329,7 +334,7 @@ def create_or_update_role(connection, module):
# Make a list of the ARNs from the attached policies
# Detach roles not defined in task
if module.params.get('purge_policies'):
if purge_policies:
if remove_policies(connection, module, set(current_attached_policies_arn_list) - set(managed_policies), params):
changed = True
@ -565,14 +570,14 @@ def main():
name=dict(type='str', required=True),
path=dict(type='str', default="/"),
assume_role_policy_document=dict(type='json'),
managed_policy=dict(type='list', aliases=['managed_policies']),
managed_policies=dict(type='list', aliases=['managed_policy']),
max_session_duration=dict(type='int'),
state=dict(type='str', choices=['present', 'absent'], default='present'),
description=dict(type='str'),
boundary=dict(type='str', aliases=['boundary_policy_arn']),
create_instance_profile=dict(type='bool', default=True),
delete_instance_profile=dict(type='bool', default=False),
purge_policies=dict(type='bool', default=True),
purge_policies=dict(type='bool', aliases=['purge_policy', 'purge_managed_policies']),
tags=dict(type='dict'),
purge_tags=dict(type='bool', default=True),
)
@ -580,6 +585,10 @@ def main():
required_if=[('state', 'present', ['assume_role_policy_document'])],
supports_check_mode=True)
if module.params.get('purge_policies') is None:
module.deprecate('In Ansible 2.14 the default value of purge_policies will change from true to false.'
' To maintain the existing behaviour explicity set purge_policies=true', version='2.14')
if module.params.get('boundary'):
if module.params.get('create_instance_profile'):
module.fail_json(msg="When using a boundary policy, `create_instance_profile` must be set to `false`.")

View file

@ -14,7 +14,7 @@ DOCUMENTATION = '''
module: iam_user
short_description: Manage AWS IAM users
description:
- Manage AWS IAM users
- Manage AWS IAM users.
version_added: "2.5"
author: Josh Souza (@joshsouza)
options:
@ -23,23 +23,26 @@ options:
- The name of the user to create.
required: true
type: str
managed_policy:
managed_policies:
description:
- A list of managed policy ARNs or friendly names to attach to the user. To embed an inline policy, use M(iam_policy).
- A list of managed policy ARNs or friendly names to attach to the user.
- To embed an inline policy, use M(iam_policy).
required: false
type: list
aliases: ['managed_policy']
state:
description:
- Create or remove the IAM user
- Create or remove the IAM user.
required: true
choices: [ 'present', 'absent' ]
type: str
purge_policy:
purge_policies:
description:
- Detach policies which are not included in managed_policy list
- When I(purge_policies=true) any managed policies not listed in I(managed_policies) will be detatched.
required: false
default: false
type: bool
aliases: ['purge_policy', 'purge_managed_policies']
requirements: [ botocore, boto3 ]
extends_documentation_fragment:
- aws
@ -60,7 +63,7 @@ EXAMPLES = '''
# Create a user and attach a managed policy using its ARN
- iam_user:
name: testuser1
managed_policy:
managed_policies:
- arn:aws:iam::aws:policy/AmazonSNSFullAccess
state: present
@ -68,7 +71,7 @@ EXAMPLES = '''
- iam_user:
name: testuser1
state: present
purge_policy: true
purge_policies: true
# Delete the user
- iam_user:
@ -157,8 +160,8 @@ def create_or_update_user(connection, module):
params = dict()
params['UserName'] = module.params.get('name')
managed_policies = module.params.get('managed_policy')
purge_policy = module.params.get('purge_policy')
managed_policies = module.params.get('managed_policies')
purge_policies = module.params.get('purge_policies')
changed = False
if managed_policies:
managed_policies = convert_friendly_names_to_arns(connection, module, managed_policies)
@ -189,7 +192,7 @@ def create_or_update_user(connection, module):
current_attached_policies_arn_list.append(policy['PolicyArn'])
# If managed_policies has a single empty element we want to remove all attached policies
if purge_policy:
if purge_policies:
# Detach policies not present
for policy_arn in list(set(current_attached_policies_arn_list) - set(managed_policies)):
changed = True
@ -342,26 +345,19 @@ def delete_user_login_profile(connection, module, user_name):
def main():
argument_spec = ec2_argument_spec()
argument_spec.update(
dict(
name=dict(required=True, type='str'),
managed_policy=dict(default=[], type='list'),
state=dict(choices=['present', 'absent'], required=True),
purge_policy=dict(default=False, type='bool')
)
argument_spec = dict(
name=dict(required=True, type='str'),
managed_policies=dict(default=[], type='list', aliases=['managed_policy']),
state=dict(choices=['present', 'absent'], required=True),
purge_policies=dict(default=False, type='bool', aliases=['purge_policy', 'purge_managed_policies'])
)
module = AnsibleAWSModule(
argument_spec=argument_spec,
supports_check_mode=True
)
if not HAS_BOTO3:
module.fail_json(msg='boto3 required for this module')
region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)
connection = boto3_conn(module, conn_type='client', resource='iam', region=region, endpoint=ec2_url, **aws_connect_params)
connection = module.client('iam')
state = module.params.get("state")