1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00
community.general/plugins/modules/ipa_group.py
Felix Fontein 18a6bdd6aa
Add attributes to ipa and keycloak modules (#5950)
Add attributes to ipa and keycloak modules.
2023-02-24 09:25:31 +01:00

342 lines
11 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r'''
---
module: ipa_group
author: Thomas Krahn (@Nosmoht)
short_description: Manage FreeIPA group
description:
- Add, modify and delete group within IPA server
attributes:
check_mode:
support: full
diff_mode:
support: none
options:
append:
description:
- If C(true), add the listed I(user) and I(group) to the group members.
- If C(false), only the listed I(user) and I(group) will be group members, removing any other members.
default: false
type: bool
version_added: 4.0.0
cn:
description:
- Canonical name.
- Can not be changed as it is the unique identifier.
required: true
aliases: ['name']
type: str
description:
description:
- Description of the group.
type: str
external:
description:
- Allow adding external non-IPA members from trusted domains.
type: bool
gidnumber:
description:
- GID (use this option to set it manually).
aliases: ['gid']
type: str
group:
description:
- List of group names assigned to this group.
- If I(append=false) and an empty list is passed all groups will be removed from this group.
- Groups that are already assigned but not passed will be removed.
- If I(append=true) the listed groups will be assigned without removing other groups.
- If option is omitted assigned groups will not be checked or changed.
type: list
elements: str
nonposix:
description:
- Create as a non-POSIX group.
type: bool
user:
description:
- List of user names assigned to this group.
- If I(append=false) and an empty list is passed all users will be removed from this group.
- Users that are already assigned but not passed will be removed.
- If I(append=true) the listed users will be assigned without removing other users.
- If option is omitted assigned users will not be checked or changed.
type: list
elements: str
external_user:
description:
- List of external users assigned to this group.
- Behaves identically to I(user) with respect to I(append) attribute.
- List entries can be in C(DOMAIN\\username) or SID format.
- Unless SIDs are provided, the module will always attempt to make changes even if the group already has all the users.
This is because only SIDs are returned by IPA query.
- I(external=true) is needed for this option to work.
type: list
elements: str
version_added: 6.3.0
state:
description:
- State to ensure
default: "present"
choices: ["absent", "present"]
type: str
extends_documentation_fragment:
- community.general.ipa.documentation
- community.general.attributes
'''
EXAMPLES = r'''
- name: Ensure group is present
community.general.ipa_group:
name: oinstall
gidnumber: '54321'
state: present
ipa_host: ipa.example.com
ipa_user: admin
ipa_pass: topsecret
- name: Ensure that groups sysops and appops are assigned to ops but no other group
community.general.ipa_group:
name: ops
group:
- sysops
- appops
ipa_host: ipa.example.com
ipa_user: admin
ipa_pass: topsecret
- name: Ensure that users linus and larry are assign to the group, but no other user
community.general.ipa_group:
name: sysops
user:
- linus
- larry
ipa_host: ipa.example.com
ipa_user: admin
ipa_pass: topsecret
- name: Ensure that new starter named john is member of the group, without removing other members
community.general.ipa_group:
name: developers
user:
- john
append: true
state: present
ipa_host: ipa.example.com
ipa_user: admin
ipa_pass: topsecret
- name: Add external user to a group
community.general.ipa_group:
name: developers
external: true
append: true
external_user:
- S-1-5-21-123-1234-12345-63421
ipa_host: ipa.example.com
ipa_user: admin
ipa_pass: topsecret
- name: Add a user from MYDOMAIN
community.general.ipa_group:
name: developers
external: true
append: true
external_user:
- MYDOMAIN\\john
ipa_host: ipa.example.com
ipa_user: admin
ipa_pass: topsecret
- name: Ensure group is absent
community.general.ipa_group:
name: sysops
state: absent
ipa_host: ipa.example.com
ipa_user: admin
ipa_pass: topsecret
'''
RETURN = r'''
group:
description: Group as returned by IPA API
returned: always
type: dict
'''
import traceback
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.ipa import IPAClient, ipa_argument_spec
from ansible.module_utils.common.text.converters import to_native
class GroupIPAClient(IPAClient):
def __init__(self, module, host, port, protocol):
super(GroupIPAClient, self).__init__(module, host, port, protocol)
def group_find(self, name):
return self._post_json(method='group_find', name=None, item={'all': True, 'cn': name})
def group_add(self, name, item):
return self._post_json(method='group_add', name=name, item=item)
def group_mod(self, name, item):
return self._post_json(method='group_mod', name=name, item=item)
def group_del(self, name):
return self._post_json(method='group_del', name=name)
def group_add_member(self, name, item):
return self._post_json(method='group_add_member', name=name, item=item)
def group_add_member_group(self, name, item):
return self.group_add_member(name=name, item={'group': item})
def group_add_member_user(self, name, item):
return self.group_add_member(name=name, item={'user': item})
def group_add_member_externaluser(self, name, item):
return self.group_add_member(name=name, item={'ipaexternalmember': item})
def group_remove_member(self, name, item):
return self._post_json(method='group_remove_member', name=name, item=item)
def group_remove_member_group(self, name, item):
return self.group_remove_member(name=name, item={'group': item})
def group_remove_member_user(self, name, item):
return self.group_remove_member(name=name, item={'user': item})
def group_remove_member_externaluser(self, name, item):
return self.group_remove_member(name=name, item={'ipaexternalmember': item})
def get_group_dict(description=None, external=None, gid=None, nonposix=None):
group = {}
if description is not None:
group['description'] = description
if external is not None:
group['external'] = external
if gid is not None:
group['gidnumber'] = gid
if nonposix is not None:
group['nonposix'] = nonposix
return group
def get_group_diff(client, ipa_group, module_group):
data = []
# With group_add attribute nonposix is passed, whereas with group_mod only posix can be passed.
if 'nonposix' in module_group:
# Only non-posix groups can be changed to posix
if not module_group['nonposix'] and ipa_group.get('nonposix'):
module_group['posix'] = True
del module_group['nonposix']
if 'external' in module_group:
if module_group['external'] and 'ipaexternalgroup' in ipa_group.get('objectclass'):
del module_group['external']
return client.get_diff(ipa_data=ipa_group, module_data=module_group)
def ensure(module, client):
state = module.params['state']
name = module.params['cn']
group = module.params['group']
user = module.params['user']
external = module.params['external']
external_user = module.params['external_user']
append = module.params['append']
module_group = get_group_dict(description=module.params['description'],
external=external,
gid=module.params['gidnumber'],
nonposix=module.params['nonposix'])
ipa_group = client.group_find(name=name)
if (not (external or external_user is None)):
module.fail_json("external_user can only be set if external = True")
changed = False
if state == 'present':
if not ipa_group:
changed = True
if not module.check_mode:
ipa_group = client.group_add(name, item=module_group)
else:
diff = get_group_diff(client, ipa_group, module_group)
if len(diff) > 0:
changed = True
if not module.check_mode:
data = {}
for key in diff:
data[key] = module_group.get(key)
client.group_mod(name=name, item=data)
if group is not None:
changed = client.modify_if_diff(name, ipa_group.get('member_group', []), group,
client.group_add_member_group,
client.group_remove_member_group,
append=append) or changed
if user is not None:
changed = client.modify_if_diff(name, ipa_group.get('member_user', []), user,
client.group_add_member_user,
client.group_remove_member_user,
append=append) or changed
if external_user is not None:
changed = client.modify_if_diff(name, ipa_group.get('ipaexternalmember', []), external_user,
client.group_add_member_externaluser,
client.group_remove_member_externaluser,
append=append) or changed
else:
if ipa_group:
changed = True
if not module.check_mode:
client.group_del(name)
return changed, client.group_find(name=name)
def main():
argument_spec = ipa_argument_spec()
argument_spec.update(cn=dict(type='str', required=True, aliases=['name']),
description=dict(type='str'),
external=dict(type='bool'),
external_user=dict(type='list', elements='str'),
gidnumber=dict(type='str', aliases=['gid']),
group=dict(type='list', elements='str'),
nonposix=dict(type='bool'),
state=dict(type='str', default='present', choices=['present', 'absent']),
user=dict(type='list', elements='str'),
append=dict(type='bool', default=False))
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True,
)
client = GroupIPAClient(module=module,
host=module.params['ipa_host'],
port=module.params['ipa_port'],
protocol=module.params['ipa_prot'])
try:
client.login(username=module.params['ipa_user'],
password=module.params['ipa_pass'])
changed, group = ensure(module, client)
module.exit_json(changed=changed, group=group)
except Exception as e:
module.fail_json(msg=to_native(e), exception=traceback.format_exc())
if __name__ == '__main__':
main()