Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix AWS iam_user remove #59079

Merged
merged 2 commits into from
Oct 21, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
110 changes: 77 additions & 33 deletions lib/ansible/modules/cloud/amazon/iam_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@
'''

from ansible.module_utils._text import to_native
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.ec2 import camel_dict_to_snake_dict, ec2_argument_spec, get_aws_connection_info, boto3_conn
from ansible.module_utils.ec2 import HAS_BOTO3

import traceback

try:
from botocore.exceptions import ClientError, ParamValidationError
from botocore.exceptions import ClientError, ParamValidationError, BotoCoreError
except ImportError:
pass # caught by imported HAS_BOTO3

Expand Down Expand Up @@ -227,38 +227,72 @@ def create_or_update_user(connection, module):

def destroy_user(connection, module):

params = dict()
params['UserName'] = module.params.get('name')
user_name = module.params.get('name')

if get_user(connection, module, params['UserName']):
# Check mode means we would remove this user
if module.check_mode:
module.exit_json(changed=True)
user = get_user(connection, module, user_name)
# User is not present
if not user:
module.exit_json(changed=False)

# Remove any attached policies otherwise deletion fails
try:
for policy in get_attached_policy_list(connection, module, params['UserName']):
connection.detach_user_policy(UserName=params['UserName'], PolicyArn=policy['PolicyArn'])
except ClientError as e:
module.fail_json(msg="Unable to detach policy {0} from user {1}: {2}".format(
policy['PolicyArn'], params['UserName'], to_native(e)),
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
except ParamValidationError as e:
module.fail_json(msg="Unable to detach policy {0} from user {1}: {2}".format(
policy['PolicyArn'], params['UserName'], to_native(e)),
exception=traceback.format_exc())
# Check mode means we would remove this user
if module.check_mode:
module.exit_json(changed=True)

try:
connection.delete_user(**params)
except ClientError as e:
module.fail_json(msg="Unable to delete user {0}: {1}".format(params['UserName'], to_native(e)),
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
except ParamValidationError as e:
module.fail_json(msg="Unable to delete user {0}: {1}".format(params['UserName'], to_native(e)),
exception=traceback.format_exc())
# Remove any attached policies otherwise deletion fails
try:
for policy in get_attached_policy_list(connection, module, user_name):
connection.detach_user_policy(UserName=user_name, PolicyArn=policy['PolicyArn'])
except (ClientError, BotoCoreError) as e:
module.fail_json_aws(e, msg="Unable to delete user {0}".format(user_name))

else:
module.exit_json(changed=False)
try:
# Remove user's access keys
access_keys = connection.list_access_keys(UserName=user_name)["AccessKeyMetadata"]
for access_key in access_keys:
connection.delete_access_key(UserName=user_name, AccessKeyId=access_key["AccessKeyId"])

# Remove user's login profile (console password)
delete_user_login_profile(connection, module, user_name)

# Remove user's ssh public keys
ssh_public_keys = connection.list_ssh_public_keys(UserName=user_name)["SSHPublicKeys"]
for ssh_public_key in ssh_public_keys:
connection.delete_ssh_public_key(UserName=user_name, SSHPublicKeyId=ssh_public_key["SSHPublicKeyId"])

# Remove user's service specific credentials
service_credentials = connection.list_service_specific_credentials(UserName=user_name)["ServiceSpecificCredentials"]
for service_specific_credential in service_credentials:
connection.delete_service_specific_credential(
UserName=user_name,
ServiceSpecificCredentialId=service_specific_credential["ServiceSpecificCredentialId"]
)

# Remove user's signing certificates
signing_certificates = connection.list_signing_certificates(UserName=user_name)["Certificates"]
for signing_certificate in signing_certificates:
connection.delete_signing_certificate(
UserName=user_name,
CertificateId=signing_certificate["CertificateId"]
)

# Remove user's MFA devices
mfa_devices = connection.list_mfa_devices(UserName=user_name)["MFADevices"]
for mfa_device in mfa_devices:
connection.deactivate_mfa_device(UserName=user_name, SerialNumber=mfa_device["SerialNumber"])

# Remove user's inline policies
inline_policies = connection.list_user_policies(UserName=user_name)["PolicyNames"]
for policy_name in inline_policies:
connection.delete_user_policy(UserName=user_name, PolicyName=policy_name)

# Remove user's group membership
user_groups = connection.list_groups_for_user(UserName=user_name)["Groups"]
for group in user_groups:
connection.remove_user_from_group(UserName=user_name, GroupName=group["GroupName"])

connection.delete_user(UserName=user_name)
except (ClientError, BotoCoreError) as e:
module.fail_json_aws(e, msg="Unable to delete user {0}".format(user_name))

module.exit_json(changed=True)

Expand Down Expand Up @@ -286,8 +320,18 @@ def get_attached_policy_list(connection, module, name):
if e.response['Error']['Code'] == 'NoSuchEntity':
return None
else:
module.fail_json(msg="Unable to get policies for user {0}: {1}".format(name, to_native(e)),
**camel_dict_to_snake_dict(e.response))
module.fail_json_aws(e, msg="Unable to get policies for user {0}".format(name))


def delete_user_login_profile(connection, module, user_name):

try:
return connection.delete_login_profile(UserName=user_name)
except ClientError as e:
if e.response["Error"]["Code"] == "NoSuchEntity":
return None
else:
module.fail_json_aws(e, msg="Unable to delete login profile for user {0}".format(user_name))


def main():
Expand All @@ -302,7 +346,7 @@ def main():
)
)

module = AnsibleModule(
module = AnsibleAWSModule(
argument_spec=argument_spec,
supports_check_mode=True
)
Expand Down