mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 01:18:58 +00:00
Merge pull request #22687 from lyft/boto-iam-consistency
Make boto_iam more consistent with boto_iam_role for groups
This commit is contained in:
commit
3362c13625
@ -405,25 +405,56 @@ def put_group_policy(group_name, policy_name, policy_json, region=None, key=None
|
||||
salt myminion boto_iam.put_group_policy mygroup policyname policyrules
|
||||
'''
|
||||
group = get_group(group_name, region, key, keyid, profile)
|
||||
if group:
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
try:
|
||||
created = conn.put_group_policy(group_name, policy_name,
|
||||
policy_json)
|
||||
if created:
|
||||
log.info('Created policy for group {0}.'.format(group_name))
|
||||
return True
|
||||
msg = 'Could not create policy for group {0}'
|
||||
log.error(msg.format(group_name))
|
||||
except boto.exception.BotoServerError as e:
|
||||
log.debug(e)
|
||||
msg = 'Failed to create policy for group {0}'
|
||||
log.error(msg.format(group_name))
|
||||
else:
|
||||
if not group:
|
||||
log.error('Group {0} does not exist'.format(group_name))
|
||||
return False
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
try:
|
||||
if not isinstance(policy_json, string_types):
|
||||
policy_json = json.dumps(policy_json)
|
||||
created = conn.put_group_policy(group_name, policy_name,
|
||||
policy_json)
|
||||
if created:
|
||||
log.info('Created policy for group {0}.'.format(group_name))
|
||||
return True
|
||||
msg = 'Could not create policy for group {0}'
|
||||
log.error(msg.format(group_name))
|
||||
except boto.exception.BotoServerError as e:
|
||||
log.debug(e)
|
||||
msg = 'Failed to create policy for group {0}'
|
||||
log.error(msg.format(group_name))
|
||||
return False
|
||||
|
||||
|
||||
def delete_group_policy(group_name, policy_name, region=None, key=None,
|
||||
keyid=None, profile=None):
|
||||
'''
|
||||
Delete a group policy.
|
||||
|
||||
CLI example::
|
||||
|
||||
salt myminion boto_iam.delete_group_policy mygroup mypolicy
|
||||
'''
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
_policy = get_group_policy(
|
||||
group_name, policy_name, region, key, keyid, profile
|
||||
)
|
||||
if not _policy:
|
||||
return True
|
||||
try:
|
||||
conn.delete_group_policy(group_name, policy_name)
|
||||
msg = 'Successfully deleted {0} policy for group {1}.'
|
||||
log.info(msg.format(policy_name, group_name))
|
||||
return True
|
||||
except boto.exception.BotoServerError as e:
|
||||
log.debug(e)
|
||||
msg = 'Failed to delete {0} policy for group {1}.'
|
||||
log.error(msg.format(policy_name, group_name))
|
||||
return False
|
||||
|
||||
|
||||
def get_group_policy(group_name, policy_name, region=None, key=None,
|
||||
keyid=None, profile=None):
|
||||
'''
|
||||
@ -452,6 +483,27 @@ def get_group_policy(group_name, policy_name, region=None, key=None,
|
||||
return False
|
||||
|
||||
|
||||
def get_all_group_policies(group_name, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
'''
|
||||
Get a list of policy names from a group.
|
||||
|
||||
CLI example::
|
||||
|
||||
salt myminion boto_iam.get_all_group_policies mygroup
|
||||
'''
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
try:
|
||||
response = conn.get_all_group_policies(group_name)
|
||||
_list = response.list_group_policies_response.list_group_policies_result
|
||||
return _list.policy_names
|
||||
except boto.exception.BotoServerError as e:
|
||||
log.debug(e)
|
||||
return []
|
||||
|
||||
|
||||
def create_login_profile(user_name, password, region=None, key=None,
|
||||
keyid=None, profile=None):
|
||||
'''
|
||||
|
@ -106,6 +106,9 @@ import xml.etree.cElementTree as xml
|
||||
# Import Salt Libs
|
||||
import salt.utils
|
||||
import salt.utils.odict as odict
|
||||
import salt.utils.dictupdate as dictupdate
|
||||
import salt.ext.six as six
|
||||
from salt.ext.six import string_types
|
||||
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -397,83 +400,157 @@ def _case_group(ret, name, group, region=None, key=None, keyid=None, profile=Non
|
||||
return ret
|
||||
|
||||
|
||||
def group_present(name, policy_name=None, policy=None, users=None, region=None, key=None, keyid=None, profile=None):
|
||||
def group_present(name, policies=None, policies_from_pillars=None, users=None, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
|
||||
Ensure the IAM group is present
|
||||
|
||||
name (string) – The name of the new group.
|
||||
name (string)
|
||||
The name of the new group.
|
||||
|
||||
policy_name (string) - The policy document to add to the group.
|
||||
policies (dict)
|
||||
A dict of IAM group policy documents.
|
||||
|
||||
users (list) - A list of users to be added to the group.
|
||||
policies_from_pillars (list)
|
||||
A list of pillars that contain role policy dicts. Policies in the
|
||||
pillars will be merged in the order defined in the list and key
|
||||
conflicts will be handled by later defined keys overriding earlier
|
||||
defined keys. The policies defined here will be merged with the
|
||||
policies defined in the policies argument. If keys conflict, the keys
|
||||
in the policies argument will override the keys defined in
|
||||
policies_from_pillars.
|
||||
|
||||
region (string) - Region to connect to.
|
||||
users (list)
|
||||
A list of users to be added to the group.
|
||||
|
||||
key (string) - Secret key to be used.
|
||||
region (string)
|
||||
Region to connect to.
|
||||
|
||||
keyid (string) - Access key to be used.
|
||||
key (string)
|
||||
Secret key to be used.
|
||||
|
||||
profile (dict) - A dict with region, key and keyid, or a pillar key (string)
|
||||
that contains a dict with region, key and keyid.
|
||||
keyid (string)
|
||||
Access key to be used.
|
||||
|
||||
profile (dict)
|
||||
A dict with region, key and keyid, or a pillar key (string) that
|
||||
contains a dict with region, key and keyid.
|
||||
'''
|
||||
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
|
||||
if not policies:
|
||||
policies = {}
|
||||
if not policies_from_pillars:
|
||||
policies_from_pillars = []
|
||||
_policies = {}
|
||||
for policy in policies_from_pillars:
|
||||
_policy = __salt__['pillar.get'](policy)
|
||||
_policies.update(_policy)
|
||||
_policies.update(policies)
|
||||
exists = __salt__['boto_iam.get_group'](group_name=name, region=region, key=key, keyid=keyid, profile=profile)
|
||||
if not exists:
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'IAM user {0} is set to be created.'.format(name)
|
||||
ret['comment'] = 'IAM group {0} is set to be created.'.format(name)
|
||||
ret['result'] = None
|
||||
return ret
|
||||
created = __salt__['boto_iam.create_group'](group_name=name, region=region, key=key, keyid=keyid, profile=profile)
|
||||
if created:
|
||||
ret['changes']['group'] = created
|
||||
ret['comment'] = os.linesep.join([ret['comment'], 'Group {0} has been created.'.format(name)])
|
||||
if policy_name and policy:
|
||||
ret = _case_policy(ret, name, policy_name, policy, region, key, keyid, profile)
|
||||
if users:
|
||||
log.debug('users are : {0}'.format(users))
|
||||
for user in users:
|
||||
log.debug('user is : {0}'.format(user))
|
||||
ret = _case_group(ret, user, name, region, key, keyid, profile)
|
||||
if not created:
|
||||
ret['comment'] = 'Failed to create IAM user {0}.'.format(name)
|
||||
ret['result'] = False
|
||||
return ret
|
||||
ret['changes']['group'] = created
|
||||
ret['comment'] = os.linesep.join([ret['comment'], 'Group {0} has been created.'.format(name)])
|
||||
else:
|
||||
ret['comment'] = os.linesep.join([ret['comment'], 'Group {0} is present.'.format(name)])
|
||||
if policy_name and policy:
|
||||
ret = _case_policy(ret, name, policy_name, policy, region, key, keyid, profile)
|
||||
if users:
|
||||
log.debug('Users are : {0}.'.format(users))
|
||||
for user in users:
|
||||
log.debug('User is : {0}.'.format(user))
|
||||
ret = _case_group(ret, user, name, region, key, keyid, profile)
|
||||
# User exists, ensure group policies and users are set.
|
||||
_ret = _group_policies_present(
|
||||
name, _policies, region, key, keyid, profile
|
||||
)
|
||||
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
||||
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
|
||||
if not _ret['result']:
|
||||
ret['result'] = _ret['result']
|
||||
return ret
|
||||
# TODO: make this work like _group_policies_present. This is currently not
|
||||
# fully idempotent.
|
||||
if users:
|
||||
log.debug('Users are : {0}.'.format(users))
|
||||
for user in users:
|
||||
log.debug('User is : {0}.'.format(user))
|
||||
ret = _case_group(ret, user, name, region, key, keyid, profile)
|
||||
return ret
|
||||
|
||||
|
||||
def _case_policy(ret, group_name, policy_name, policy, region=None, key=None, keyid=None, profile=None):
|
||||
exists = __salt__['boto_iam.get_group_policy'](group_name, policy_name, region, key, keyid, profile)
|
||||
if exists:
|
||||
log.debug('Policy exists is : {0}.'.format(exists))
|
||||
if not isinstance(policy, str):
|
||||
policy = json.loads(policy, object_pairs_hook=odict.OrderedDict)
|
||||
log.debug('Policy in Json is : {0}.'.format(policy))
|
||||
if exists == policy:
|
||||
ret['comment'] = os.linesep.join([ret['comment'], 'Policy {0} is present.'.format(group_name)])
|
||||
def _group_policies_present(
|
||||
name,
|
||||
policies=None,
|
||||
region=None,
|
||||
key=None,
|
||||
keyid=None,
|
||||
profile=None):
|
||||
ret = {'result': True, 'comment': '', 'changes': {}}
|
||||
policies_to_create = {}
|
||||
policies_to_delete = []
|
||||
for policy_name, policy in six.iteritems(policies):
|
||||
if isinstance(policy, string_types):
|
||||
dict_policy = json.loads(
|
||||
policy, object_pairs_hook=odict.OrderedDict
|
||||
)
|
||||
else:
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'Group policy {0} is set to be updated.'.format(policy_name)
|
||||
ret['result'] = None
|
||||
return ret
|
||||
__salt__['boto_iam.put_group_policy'](group_name, policy_name, policy, region, key, keyid, profile)
|
||||
ret['comment'] = os.linesep.join([ret['comment'], 'Policy {0} has been added to group {1}.'.format(policy_name, group_name)])
|
||||
ret['changes']['policy_name'] = policy
|
||||
else:
|
||||
dict_policy = policy
|
||||
_policy = __salt__['boto_iam.get_group_policy'](
|
||||
name, policy_name, region, key, keyid, profile
|
||||
)
|
||||
if _policy != dict_policy:
|
||||
policies_to_create[policy_name] = policy
|
||||
_list = __salt__['boto_iam.get_all_group_policies'](
|
||||
name, region, key, keyid, profile
|
||||
)
|
||||
for policy_name in _list:
|
||||
if policy_name not in policies:
|
||||
policies_to_delete.append(policy_name)
|
||||
if policies_to_create or policies_to_delete:
|
||||
_to_modify = list(policies_to_delete)
|
||||
_to_modify.extend(policies_to_create)
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'Group policy {0} is set to be created.'.format(policy_name)
|
||||
msg = '{0} policies to be modified on group {1}.'
|
||||
ret['comment'] = msg.format(', '.join(_to_modify), name)
|
||||
ret['result'] = None
|
||||
return ret
|
||||
__salt__['boto_iam.put_group_policy'](group_name, policy_name, policy, region, key, keyid, profile)
|
||||
ret['comment'] = os.linesep.join([ret['comment'], 'Policy {0} has been added to group {1}.'.format(policy_name, group_name)])
|
||||
ret['changes'][policy_name] = policy
|
||||
ret['changes']['old'] = {'policies': _list}
|
||||
for policy_name, policy in six.iteritems(policies_to_create):
|
||||
policy_set = __salt__['boto_iam.put_group_policy'](
|
||||
name, policy_name, policy, region, key, keyid, profile
|
||||
)
|
||||
if not policy_set:
|
||||
_list = __salt__['boto_iam.get_all_group_policies'](
|
||||
name, region, key, keyid, profile
|
||||
)
|
||||
ret['changes']['new'] = {'policies': _list}
|
||||
ret['result'] = False
|
||||
msg = 'Failed to add policy {0} to group {1}'
|
||||
ret['comment'] = msg.format(policy_name, name)
|
||||
return ret
|
||||
for policy_name in policies_to_delete:
|
||||
policy_unset = __salt__['boto_iam.delete_group_policy'](
|
||||
name, policy_name, region, key, keyid, profile
|
||||
)
|
||||
if not policy_unset:
|
||||
_list = __salt__['boto_iam.get_all_group_policies'](
|
||||
name, region, key, keyid, profile
|
||||
)
|
||||
ret['changes']['new'] = {'policies': _list}
|
||||
ret['result'] = False
|
||||
msg = 'Failed to add policy {0} to group {1}'
|
||||
ret['comment'] = msg.format(policy_name, name)
|
||||
return ret
|
||||
_list = __salt__['boto_iam.get_all_group_policies'](
|
||||
name, region, key, keyid, profile
|
||||
)
|
||||
ret['changes']['new'] = {'policies': _list}
|
||||
msg = '{0} policies modified on group {1}.'
|
||||
ret['comment'] = msg.format(', '.join(_list), name)
|
||||
return ret
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user