From ea488927a5f6cb0ce5a74abd96bf07ef92beb4cb Mon Sep 17 00:00:00 2001 From: Evan Davis Date: Mon, 17 Apr 2017 12:57:43 -0700 Subject: [PATCH 1/2] add delete_virtual_mfa_device function to boto_iam module to expose boto3 iam client's delete_virtual_mfa_device method --- salt/modules/boto_iam.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/salt/modules/boto_iam.py b/salt/modules/boto_iam.py index e2b5256019..97eccd6616 100644 --- a/salt/modules/boto_iam.py +++ b/salt/modules/boto_iam.py @@ -54,7 +54,10 @@ from salt.ext.six.moves.urllib.parse import unquote as _unquote # pylint: disab try: import boto import boto.iam + import boto3 + import botocore logging.getLogger('boto').setLevel(logging.CRITICAL) + logging.getLogger('boto3').setLevel(logging.CRITICAL) HAS_BOTO = True except ImportError: HAS_BOTO = False @@ -890,6 +893,31 @@ def deactivate_mfa_device(user_name, serial, region=None, key=None, keyid=None, return False +def delete_virtual_mfa_device(serial, region=None, key=None, keyid=None, profile=None): + ''' + Deletes the specified virtual MFA device. + + CLI Example: + + .. code-block:: bash + + salt myminion boto_iam.delete_virtual_mfa_device serial_num + ''' + conn = __utils__['boto3.get_connection_func']('iam')() + try: + conn.delete_virtual_mfa_device(SerialNumber=serial) + log.info('Deleted virtual MFA device {0}.'.format(serial)) + return True + except botocore.exceptions.ClientError as e: + log.debug(e) + if 'NoSuchEntity' in str(e): + log.info('Virtual MFA device {0} not found.'.format(serial)) + return True + msg = 'Failed to delete virtual MFA device {0}.' + log.error(msg.format(serial)) + return False + + def update_account_password_policy(allow_users_to_change_password=None, hard_expiry=None, max_password_age=None, minimum_password_length=None, From 1ace66bce79d5798403fd3f1dd63001aea8e6910 Mon Sep 17 00:00:00 2001 From: Evan Davis Date: Mon, 17 Apr 2017 12:58:48 -0700 Subject: [PATCH 2/2] when deactivating a user's mfa device, try to delete the virtual mfa devices with the same serial number --- salt/states/boto_iam.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/salt/states/boto_iam.py b/salt/states/boto_iam.py index 1ffebabbfd..745df6f344 100644 --- a/salt/states/boto_iam.py +++ b/salt/states/boto_iam.py @@ -250,12 +250,19 @@ def user_absent(name, delete_keys=True, delete_mfa_devices=True, delete_profile= for d in devices: serial = d['serial_number'] if __opts__['test']: - ret['comment'] = ' '.join([ret['comment'], 'IAM user {0} MFA device {1} is set to be deleted.'.format(name, serial)]) + ret['comment'] = ' '.join([ret['comment'], 'IAM user {0} MFA device {1} is set to be deactivated.'.format(name, serial)]) ret['result'] = None else: - mfa_deleted = __salt__['boto_iam.deactivate_mfa_device'](user_name=name, serial=serial, region=region, key=key, keyid=keyid, profile=profile) + mfa_deactivated = __salt__['boto_iam.deactivate_mfa_device'](user_name=name, serial=serial, region=region, key=key, keyid=keyid, profile=profile) + if mfa_deactivated: + ret['comment'] = ' '.join([ret['comment'], 'IAM user {0} MFA device {1} is deactivated.'.format(name, serial)]) + if __opts__['test']: + ret['comment'] = ' '.join([ret['comment'], 'Virtual MFA device {0} is set to be deleted.'.format(serial)]) + ret['result'] = None + else: + mfa_deleted = __salt__['boto_iam.delete_virtual_mfa_device'](serial=serial, region=region, key=key, keyid=keyid, profile=profile) if mfa_deleted: - ret['comment'] = ' '.join([ret['comment'], 'IAM user {0} MFA device {1} are deleted.'.format(name, serial)]) + ret['comment'] = ' '.join([ret['comment'], 'Virtual MFA device {0} is deleted.'.format(serial)]) # delete the user's login profile if delete_profile: if __opts__['test']: