mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-28 14:23:06 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4aab1599bd | ||
|
|
0c36194038 | ||
|
|
680cd4c6ee | ||
|
|
401b911171 | ||
|
|
7f61e72a2c | ||
|
|
3c3396a7b8 | ||
|
|
45f583b1ed | ||
|
|
2de1dccbf5 | ||
|
|
a44515c701 | ||
|
|
8cf2e7ef7b | ||
|
|
ec198d0e09 | ||
|
|
b162122630 | ||
|
|
b89d2b1316 | ||
|
|
1d3eab804d | ||
|
|
d3b8f54d7d | ||
|
|
b7d1a2789b | ||
|
|
6bfcfcdc81 | ||
|
|
ebe5671dff | ||
|
|
2266756968 | ||
|
|
3a0a1a7529 | ||
|
|
65015e63e9 | ||
|
|
dead467982 | ||
|
|
ae286f5226 | ||
|
|
ea53e34537 | ||
|
|
48b0a13a54 | ||
|
|
04a8299be6 | ||
|
|
b0252fb57a | ||
|
|
78091e2238 | ||
|
|
25afcc3491 |
16
.github/workflows/readme.yml
vendored
Normal file
16
.github/workflows/readme.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: readme test
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
jobs:
|
||||
ansible_test:
|
||||
name: Verify readme
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run readme test
|
||||
run: |
|
||||
error=0
|
||||
for i in roles/ipa*/README.md README-*.md; do grep -q $i README.md && echo "OK: $i" || { echo -e "\033[31;1mERROR: ${i} missing\033[0m"; error=1; } done
|
||||
exit $error
|
||||
@@ -71,6 +71,7 @@ Example playbook to ensure a global forwarder, with a custom port, is absent:
|
||||
forwarders:
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
port: 53
|
||||
action: member
|
||||
state: absent
|
||||
```
|
||||
|
||||
@@ -130,7 +131,8 @@ Variable | Description | Required
|
||||
| `port` - The custom port that should be used on this server. | no
|
||||
`forward_policy` | The global forwarding policy. It can be one of `only`, `first`, or `none`. | no
|
||||
`allow_sync_ptr` | Allow synchronization of forward (A, AAAA) and reverse (PTR) records (bool). | yes
|
||||
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
|
||||
`action` | Work on dnsconfig or member level. It can be one of `member` or `dnsconfig` and defaults to `dnsconfig`. Only `forwarders` can be managed with `action: member`. | no
|
||||
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. `absent` can only be used with `action: member` and `forwarders`. | yes
|
||||
|
||||
|
||||
Authors
|
||||
|
||||
10
README.md
10
README.md
@@ -13,7 +13,9 @@ Features
|
||||
* Repair mode for clients
|
||||
* Backup and restore, also to and from controller
|
||||
* Modules for automembership rule management
|
||||
* Modules for automount key management
|
||||
* Modules for automount location management
|
||||
* Modules for automount map management
|
||||
* Modules for config management
|
||||
* Modules for delegation management
|
||||
* Modules for dns config management
|
||||
@@ -63,7 +65,6 @@ Requirements
|
||||
**Controller**
|
||||
* Ansible version: 2.8+ (ansible-freeipa is an Ansible Collection)
|
||||
* /usr/bin/kinit is required on the controller if a one time password (OTP) is used
|
||||
* python3-gssapi is required on the controller if a one time password (OTP) is used with keytab to install the client.
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -283,7 +284,8 @@ ipaserver_domain=test.local
|
||||
ipaserver_realm=TEST.LOCAL
|
||||
```
|
||||
|
||||
For enhanced security it is possible to use a auto-generated one-time-password (OTP). This will be generated on the controller using the (first) server. It is needed to have the python-gssapi bindings installed on the controller for this.
|
||||
For enhanced security it is possible to use a auto-generated one-time-password (OTP). This will be generated on the controller using the (first) server.
|
||||
|
||||
To enable the generation of the one-time-password:
|
||||
```yaml
|
||||
[ipaclients:vars]
|
||||
@@ -425,7 +427,9 @@ Modules in plugin/modules
|
||||
=========================
|
||||
|
||||
* [ipaautomember](README-automember.md)
|
||||
* [ipaautomountkey](README-automountkey.md)
|
||||
* [ipaautomountlocation](README-automountlocation.md)
|
||||
* [ipaautomountmap](README-automountmap.md)
|
||||
* [ipaconfig](README-config.md)
|
||||
* [ipadelegation](README-delegation.md)
|
||||
* [ipadnsconfig](README-dnsconfig.md)
|
||||
@@ -435,7 +439,7 @@ Modules in plugin/modules
|
||||
* [ipagroup](README-group.md)
|
||||
* [ipahbacrule](README-hbacrule.md)
|
||||
* [ipahbacsvc](README-hbacsvc.md)
|
||||
* [ipahbacsvcgroup](README-hbacsvc.md)
|
||||
* [ipahbacsvcgroup](README-hbacsvcgroup.md)
|
||||
* [ipahost](README-host.md)
|
||||
* [ipahostgroup](README-hostgroup.md)
|
||||
* [ipalocation](README-location.md)
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Set dnsconfig.
|
||||
- name: Set dnsconfig forwarders.
|
||||
ipadnsconfig:
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
port: 53
|
||||
action: member
|
||||
state: absent
|
||||
|
||||
13
playbooks/dnsconfig/forwarders-present.yml
Normal file
13
playbooks/dnsconfig/forwarders-present.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Playbook to handle global DNS configuration
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Set dnsconfig forwarders.
|
||||
ipadnsconfig:
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
port: 53
|
||||
action: member
|
||||
@@ -59,8 +59,16 @@ options:
|
||||
Allow synchronization of forward (A, AAAA) and reverse (PTR) records.
|
||||
required: false
|
||||
type: bool
|
||||
action:
|
||||
description: |
|
||||
Work on dnsconfig or member level. It can be one of `member` or
|
||||
`dnsconfig`. Only `forwarders` can be managed with `action: member`.
|
||||
default: "dnsconfig"
|
||||
choices: ["member", "dnsconfig"]
|
||||
state:
|
||||
description: State to ensure
|
||||
description: |
|
||||
The state to ensure. It can be one of `present` or `absent`.
|
||||
`absent` can only be used with `action: member` and `forwarders`.
|
||||
default: present
|
||||
choices: ["present", "absent"]
|
||||
"""
|
||||
@@ -83,6 +91,7 @@ EXAMPLES = """
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
port: 53
|
||||
state: absent
|
||||
action: member
|
||||
|
||||
# Disable PTR record synchronization.
|
||||
- ipadnsconfig:
|
||||
@@ -118,7 +127,7 @@ def find_dnsconfig(module):
|
||||
return None
|
||||
|
||||
|
||||
def gen_args(module, state, dnsconfig, forwarders, forward_policy,
|
||||
def gen_args(module, state, action, dnsconfig, forwarders, forward_policy,
|
||||
allow_sync_ptr):
|
||||
_args = {}
|
||||
|
||||
@@ -137,15 +146,20 @@ def gen_args(module, state, dnsconfig, forwarders, forward_policy,
|
||||
|
||||
global_forwarders = dnsconfig.get('idnsforwarders', [])
|
||||
if state == 'absent':
|
||||
_args['idnsforwarders'] = [
|
||||
fwd for fwd in global_forwarders if fwd not in _forwarders]
|
||||
# When all forwarders should be excluded, use an empty string ('').
|
||||
if not _args['idnsforwarders']:
|
||||
_args['idnsforwarders'] = ['']
|
||||
if action == "member":
|
||||
_args['idnsforwarders'] = [
|
||||
fwd for fwd in global_forwarders if fwd not in _forwarders]
|
||||
# When all forwarders should be excluded,
|
||||
# use an empty string ('').
|
||||
if not _args['idnsforwarders']:
|
||||
_args['idnsforwarders'] = ['']
|
||||
|
||||
elif state == 'present':
|
||||
_args['idnsforwarders'] = [
|
||||
fwd for fwd in _forwarders if fwd not in global_forwarders]
|
||||
if action == "member":
|
||||
_args['idnsforwarders'] = \
|
||||
list(set(list(_forwarders) + list(global_forwarders)))
|
||||
else:
|
||||
_args['idnsforwarders'] = _forwarders
|
||||
# If no forwarders should be added, remove argument.
|
||||
if not _args['idnsforwarders']:
|
||||
del _args['idnsforwarders']
|
||||
@@ -179,6 +193,8 @@ def main():
|
||||
allow_sync_ptr=dict(type='bool', required=False, default=None),
|
||||
|
||||
# general
|
||||
action=dict(type="str", default="dnsconfig",
|
||||
choices=["member", "dnsconfig"]),
|
||||
state=dict(type="str", default="present",
|
||||
choices=["present", "absent"]),
|
||||
)
|
||||
@@ -191,11 +207,17 @@ def main():
|
||||
forward_policy = ansible_module.params_get('forward_policy')
|
||||
allow_sync_ptr = ansible_module.params_get('allow_sync_ptr')
|
||||
|
||||
action = ansible_module.params_get('action')
|
||||
state = ansible_module.params_get('state')
|
||||
|
||||
# Check parameters.
|
||||
invalid = []
|
||||
if state == "present" and action == "member":
|
||||
invalid = ['forward_policy', 'allow_sync_ptr']
|
||||
if state == 'absent':
|
||||
if action != "member":
|
||||
ansible_module.fail_json(
|
||||
msg="State 'absent' is only valid with action 'member'.")
|
||||
invalid = ['forward_policy', 'allow_sync_ptr']
|
||||
|
||||
ansible_module.params_fail_used_invalid(invalid, state)
|
||||
@@ -208,7 +230,7 @@ def main():
|
||||
with ansible_module.ipa_connect():
|
||||
|
||||
res_find = find_dnsconfig(ansible_module)
|
||||
args = gen_args(ansible_module, state, res_find, forwarders,
|
||||
args = gen_args(ansible_module, state, action, res_find, forwarders,
|
||||
forward_policy, allow_sync_ptr)
|
||||
|
||||
# Execute command only if configuration changes.
|
||||
|
||||
@@ -181,6 +181,7 @@ EXAMPLES = """
|
||||
RETURN = """
|
||||
"""
|
||||
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
|
||||
gen_add_list, gen_intersection_list
|
||||
@@ -198,7 +199,14 @@ def find_group(module, name):
|
||||
module.fail_json(
|
||||
msg="There is more than one group '%s'" % (name))
|
||||
elif len(_result["result"]) == 1:
|
||||
return _result["result"][0]
|
||||
_res = _result["result"][0]
|
||||
# The returned services are of type ipapython.kerberos.Principal,
|
||||
# also services are not case sensitive. Therefore services are
|
||||
# converted to lowercase strings to be able to do the comparison.
|
||||
if "member_service" in _res:
|
||||
_res["member_service"] = \
|
||||
[to_text(svc).lower() for svc in _res["member_service"]]
|
||||
return _res
|
||||
|
||||
return None
|
||||
|
||||
@@ -308,7 +316,8 @@ def main():
|
||||
nomembers = ansible_module.params_get("nomembers")
|
||||
user = ansible_module.params_get("user")
|
||||
group = ansible_module.params_get("group")
|
||||
service = ansible_module.params_get("service")
|
||||
# Services are not case sensitive
|
||||
service = ansible_module.params_get_lowercase("service")
|
||||
membermanager_user = ansible_module.params_get("membermanager_user")
|
||||
membermanager_group = ansible_module.params_get("membermanager_group")
|
||||
externalmember = ansible_module.params_get("externalmember")
|
||||
|
||||
@@ -139,7 +139,7 @@ RETURN = """
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
|
||||
gen_intersection_list
|
||||
gen_intersection_list, ensure_fqdn
|
||||
|
||||
|
||||
def find_hostgroup(module, name):
|
||||
@@ -281,6 +281,15 @@ def main():
|
||||
ansible_module.fail_json(
|
||||
msg="Renaming hostgroups is not supported by your IPA version")
|
||||
|
||||
# If hosts are given, ensure that the hosts are FQDN and also
|
||||
# lowercase to be able to do a proper comparison to exising hosts
|
||||
# in the hostgroup.
|
||||
# Fixes #666 (ipahostgroup not idempotent and with error)
|
||||
if host is not None:
|
||||
default_domain = ansible_module.ipa_get_domain()
|
||||
host = [ensure_fqdn(_host, default_domain).lower()
|
||||
for _host in host]
|
||||
|
||||
commands = []
|
||||
|
||||
for name in names:
|
||||
|
||||
@@ -297,17 +297,19 @@ def main():
|
||||
hostcategory = ansible_module.params_get("hostcategory") # noqa
|
||||
nomembers = ansible_module.params_get("nomembers") # noqa
|
||||
host = ansible_module.params_get("host")
|
||||
hostgroup = ansible_module.params_get("hostgroup")
|
||||
user = ansible_module.params_get("user")
|
||||
group = ansible_module.params_get("group")
|
||||
hostgroup = ansible_module.params_get_lowercase("hostgroup")
|
||||
user = ansible_module.params_get_lowercase("user")
|
||||
group = ansible_module.params_get_lowercase("group")
|
||||
allow_sudocmd = ansible_module.params_get('allow_sudocmd')
|
||||
allow_sudocmdgroup = ansible_module.params_get('allow_sudocmdgroup')
|
||||
allow_sudocmdgroup = \
|
||||
ansible_module.params_get_lowercase('allow_sudocmdgroup')
|
||||
deny_sudocmd = ansible_module.params_get('deny_sudocmd')
|
||||
deny_sudocmdgroup = ansible_module.params_get('deny_sudocmdgroup')
|
||||
deny_sudocmdgroup = \
|
||||
ansible_module.params_get_lowercase('deny_sudocmdgroup')
|
||||
sudooption = ansible_module.params_get("sudooption")
|
||||
order = ansible_module.params_get("order")
|
||||
runasuser = ansible_module.params_get("runasuser")
|
||||
runasgroup = ansible_module.params_get("runasgroup")
|
||||
runasuser = ansible_module.params_get_lowercase("runasuser")
|
||||
runasgroup = ansible_module.params_get_lowercase("runasgroup")
|
||||
action = ansible_module.params_get("action")
|
||||
|
||||
# state
|
||||
@@ -383,6 +385,17 @@ def main():
|
||||
)
|
||||
|
||||
commands = []
|
||||
host_add, host_del = [], []
|
||||
user_add, user_del = [], []
|
||||
group_add, group_del = [], []
|
||||
hostgroup_add, hostgroup_del = [], []
|
||||
allow_cmd_add, allow_cmd_del = [], []
|
||||
allow_cmdgroup_add, allow_cmdgroup_del = [], []
|
||||
deny_cmd_add, deny_cmd_del = [], []
|
||||
deny_cmdgroup_add, deny_cmdgroup_del = [], []
|
||||
sudooption_add, sudooption_del = [], []
|
||||
runasuser_add, runasuser_del = [], []
|
||||
runasgroup_add, runasgroup_del = [], []
|
||||
|
||||
for name in names:
|
||||
# Make sure sudorule exists
|
||||
@@ -487,95 +500,11 @@ def main():
|
||||
runasgroup_add, runasgroup_del = gen_add_del_lists(
|
||||
runasgroup,
|
||||
(
|
||||
res_find.get('ipasudorunas_group', [])
|
||||
res_find.get('ipasudorunasgroup_group', [])
|
||||
+ res_find.get('ipasudorunasextgroup', [])
|
||||
)
|
||||
)
|
||||
|
||||
# Add hosts and hostgroups
|
||||
if len(host_add) > 0 or len(hostgroup_add) > 0:
|
||||
commands.append([name, "sudorule_add_host",
|
||||
{
|
||||
"host": host_add,
|
||||
"hostgroup": hostgroup_add,
|
||||
}])
|
||||
# Remove hosts and hostgroups
|
||||
if len(host_del) > 0 or len(hostgroup_del) > 0:
|
||||
commands.append([name, "sudorule_remove_host",
|
||||
{
|
||||
"host": host_del,
|
||||
"hostgroup": hostgroup_del,
|
||||
}])
|
||||
|
||||
# Add users and groups
|
||||
if len(user_add) > 0 or len(group_add) > 0:
|
||||
commands.append([name, "sudorule_add_user",
|
||||
{
|
||||
"user": user_add,
|
||||
"group": group_add,
|
||||
}])
|
||||
# Remove users and groups
|
||||
if len(user_del) > 0 or len(group_del) > 0:
|
||||
commands.append([name, "sudorule_remove_user",
|
||||
{
|
||||
"user": user_del,
|
||||
"group": group_del,
|
||||
}])
|
||||
|
||||
# Add commands allowed
|
||||
if len(allow_cmd_add) > 0 or len(allow_cmdgroup_add) > 0:
|
||||
commands.append([name, "sudorule_add_allow_command",
|
||||
{"sudocmd": allow_cmd_add,
|
||||
"sudocmdgroup": allow_cmdgroup_add,
|
||||
}])
|
||||
|
||||
if len(allow_cmd_del) > 0 or len(allow_cmdgroup_del) > 0:
|
||||
commands.append([name, "sudorule_remove_allow_command",
|
||||
{"sudocmd": allow_cmd_del,
|
||||
"sudocmdgroup": allow_cmdgroup_del
|
||||
}])
|
||||
|
||||
# Add commands denied
|
||||
if len(deny_cmd_add) > 0 or len(deny_cmdgroup_add) > 0:
|
||||
commands.append([name, "sudorule_add_deny_command",
|
||||
{"sudocmd": deny_cmd_add,
|
||||
"sudocmdgroup": deny_cmdgroup_add,
|
||||
}])
|
||||
|
||||
if len(deny_cmd_del) > 0 or len(deny_cmdgroup_del) > 0:
|
||||
commands.append([name, "sudorule_remove_deny_command",
|
||||
{"sudocmd": deny_cmd_del,
|
||||
"sudocmdgroup": deny_cmdgroup_del
|
||||
}])
|
||||
|
||||
# Add RunAS Users
|
||||
if len(runasuser_add) > 0:
|
||||
commands.append([name, "sudorule_add_runasuser",
|
||||
{"user": runasuser_add}])
|
||||
# Remove RunAS Users
|
||||
if len(runasuser_del) > 0:
|
||||
commands.append([name, "sudorule_remove_runasuser",
|
||||
{"user": runasuser_del}])
|
||||
|
||||
# Add RunAS Groups
|
||||
if len(runasgroup_add) > 0:
|
||||
commands.append([name, "sudorule_add_runasgroup",
|
||||
{"group": runasgroup_add}])
|
||||
# Remove RunAS Groups
|
||||
if len(runasgroup_del) > 0:
|
||||
commands.append([name, "sudorule_remove_runasgroup",
|
||||
{"group": runasgroup_del}])
|
||||
|
||||
# Add sudo options
|
||||
for sudoopt in sudooption_add:
|
||||
commands.append([name, "sudorule_add_option",
|
||||
{"ipasudoopt": sudoopt}])
|
||||
|
||||
# Remove sudo options
|
||||
for sudoopt in sudooption_del:
|
||||
commands.append([name, "sudorule_remove_option",
|
||||
{"ipasudoopt": sudoopt}])
|
||||
|
||||
elif action == "member":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(msg="No sudorule '%s'" % name)
|
||||
@@ -585,56 +514,47 @@ def main():
|
||||
# deny_sudocmdgroup, sudooption, runasuser, runasgroup
|
||||
# and res_find to only try to add the items that not in
|
||||
# the sudorule already
|
||||
if host is not None and \
|
||||
"memberhost_host" in res_find:
|
||||
host = gen_add_list(
|
||||
host, res_find["memberhost_host"])
|
||||
if hostgroup is not None and \
|
||||
"memberhost_hostgroup" in res_find:
|
||||
hostgroup = gen_add_list(
|
||||
hostgroup, res_find["memberhost_hostgroup"])
|
||||
if user is not None and \
|
||||
"memberuser_user" in res_find:
|
||||
user = gen_add_list(
|
||||
user, res_find["memberuser_user"])
|
||||
if group is not None and \
|
||||
"memberuser_group" in res_find:
|
||||
group = gen_add_list(
|
||||
group, res_find["memberuser_group"])
|
||||
if allow_sudocmd is not None and \
|
||||
"memberallowcmd_sudocmd" in res_find:
|
||||
allow_sudocmd = gen_add_list(
|
||||
allow_sudocmd, res_find["memberallowcmd_sudocmd"])
|
||||
if allow_sudocmdgroup is not None and \
|
||||
"memberallowcmd_sudocmdgroup" in res_find:
|
||||
allow_sudocmdgroup = gen_add_list(
|
||||
if host is not None:
|
||||
host_add = gen_add_list(
|
||||
host, res_find.get("memberhost_host"))
|
||||
if hostgroup is not None:
|
||||
hostgroup_add = gen_add_list(
|
||||
hostgroup, res_find.get("memberhost_hostgroup"))
|
||||
if user is not None:
|
||||
user_add = gen_add_list(
|
||||
user, res_find.get("memberuser_user"))
|
||||
if group is not None:
|
||||
group_add = gen_add_list(
|
||||
group, res_find.get("memberuser_group"))
|
||||
if allow_sudocmd is not None:
|
||||
allow_cmd_add = gen_add_list(
|
||||
allow_sudocmd,
|
||||
res_find.get("memberallowcmd_sudocmd")
|
||||
)
|
||||
if allow_sudocmdgroup is not None:
|
||||
allow_cmdgroup_add = gen_add_list(
|
||||
allow_sudocmdgroup,
|
||||
res_find["memberallowcmd_sudocmdgroup"])
|
||||
if deny_sudocmd is not None and \
|
||||
"memberdenycmd_sudocmd" in res_find:
|
||||
deny_sudocmd = gen_add_list(
|
||||
deny_sudocmd, res_find["memberdenycmd_sudocmd"])
|
||||
if deny_sudocmdgroup is not None and \
|
||||
"memberdenycmd_sudocmdgroup" in res_find:
|
||||
deny_sudocmdgroup = gen_add_list(
|
||||
res_find.get("memberallowcmd_sudocmdgroup")
|
||||
)
|
||||
if deny_sudocmd is not None:
|
||||
deny_cmd_add = gen_add_list(
|
||||
deny_sudocmd,
|
||||
res_find.get("memberdenycmd_sudocmd")
|
||||
)
|
||||
if deny_sudocmdgroup is not None:
|
||||
deny_cmdgroup_add = gen_add_list(
|
||||
deny_sudocmdgroup,
|
||||
res_find["memberdenycmd_sudocmdgroup"])
|
||||
if sudooption is not None and \
|
||||
"ipasudoopt" in res_find:
|
||||
sudooption = gen_add_list(
|
||||
sudooption, res_find["ipasudoopt"])
|
||||
res_find.get("memberdenycmd_sudocmdgroup")
|
||||
)
|
||||
if sudooption is not None:
|
||||
sudooption_add = gen_add_list(
|
||||
sudooption, res_find.get("ipasudoopt"))
|
||||
# runasuser attribute can be used with both IPA and
|
||||
# non-IPA (external) users, so we need to compare
|
||||
# the provided list against both users and external
|
||||
# users list.
|
||||
if (
|
||||
runasuser is not None
|
||||
and (
|
||||
"ipasudorunas_user" in res_find
|
||||
or "ipasudorunasextuser" in res_find
|
||||
)
|
||||
):
|
||||
runasuser = gen_add_list(
|
||||
if runasuser is not None:
|
||||
runasuser_add = gen_add_list(
|
||||
runasuser,
|
||||
(list(res_find.get('ipasudorunas_user', []))
|
||||
+ list(res_find.get('ipasudorunasextuser', [])))
|
||||
@@ -643,69 +563,13 @@ def main():
|
||||
# non-IPA (external) groups, so we need to compare
|
||||
# the provided list against both users and external
|
||||
# groups list.
|
||||
if (
|
||||
runasgroup is not None
|
||||
and (
|
||||
"ipasudorunasgroup_group" in res_find
|
||||
or "ipasudorunasextgroup" in res_find
|
||||
)
|
||||
):
|
||||
runasgroup = gen_add_list(
|
||||
if runasgroup is not None:
|
||||
runasgroup_add = gen_add_list(
|
||||
runasgroup,
|
||||
(list(res_find.get("ipasudorunasgroup_group", []))
|
||||
+ list(res_find.get("ipasudorunasextgroup", [])))
|
||||
)
|
||||
|
||||
# Add hosts and hostgroups
|
||||
if host is not None or hostgroup is not None:
|
||||
commands.append([name, "sudorule_add_host",
|
||||
{
|
||||
"host": host,
|
||||
"hostgroup": hostgroup,
|
||||
}])
|
||||
|
||||
# Add users and groups
|
||||
if user is not None or group is not None:
|
||||
commands.append([name, "sudorule_add_user",
|
||||
{
|
||||
"user": user,
|
||||
"group": group,
|
||||
}])
|
||||
|
||||
# Add commands
|
||||
if allow_sudocmd is not None \
|
||||
or allow_sudocmdgroup is not None:
|
||||
commands.append([name, "sudorule_add_allow_command",
|
||||
{"sudocmd": allow_sudocmd,
|
||||
"sudocmdgroup": allow_sudocmdgroup,
|
||||
}])
|
||||
|
||||
# Add commands
|
||||
if deny_sudocmd is not None \
|
||||
or deny_sudocmdgroup is not None:
|
||||
commands.append([name, "sudorule_add_deny_command",
|
||||
{"sudocmd": deny_sudocmd,
|
||||
"sudocmdgroup": deny_sudocmdgroup,
|
||||
}])
|
||||
|
||||
# Add RunAS Users
|
||||
if runasuser is not None and len(runasuser) > 0:
|
||||
commands.append([name, "sudorule_add_runasuser",
|
||||
{"user": runasuser}])
|
||||
|
||||
# Add RunAS Groups
|
||||
if runasgroup is not None and len(runasgroup) > 0:
|
||||
commands.append([name, "sudorule_add_runasgroup",
|
||||
{"group": runasgroup}])
|
||||
|
||||
# Add options
|
||||
if sudooption is not None:
|
||||
existing_opts = res_find.get('ipasudoopt', [])
|
||||
for sudoopt in sudooption:
|
||||
if sudoopt not in existing_opts:
|
||||
commands.append([name, "sudorule_add_option",
|
||||
{"ipasudoopt": sudoopt}])
|
||||
|
||||
elif state == "absent":
|
||||
if action == "sudorule":
|
||||
if res_find is not None:
|
||||
@@ -721,153 +585,70 @@ def main():
|
||||
# and res_find to only try to remove the items that are
|
||||
# in sudorule
|
||||
if host is not None:
|
||||
if "memberhost_host" in res_find:
|
||||
host = gen_intersection_list(
|
||||
host, res_find["memberhost_host"])
|
||||
else:
|
||||
host = None
|
||||
host_del = gen_intersection_list(
|
||||
host, res_find.get("memberhost_host"))
|
||||
|
||||
if hostgroup is not None:
|
||||
if "memberhost_hostgroup" in res_find:
|
||||
hostgroup = gen_intersection_list(
|
||||
hostgroup, res_find["memberhost_hostgroup"])
|
||||
else:
|
||||
hostgroup = None
|
||||
hostgroup_del = gen_intersection_list(
|
||||
hostgroup, res_find.get("memberhost_hostgroup"))
|
||||
|
||||
if user is not None:
|
||||
if "memberuser_user" in res_find:
|
||||
user = gen_intersection_list(
|
||||
user, res_find["memberuser_user"])
|
||||
else:
|
||||
user = None
|
||||
user_del = gen_intersection_list(
|
||||
user, res_find.get("memberuser_user"))
|
||||
|
||||
if group is not None:
|
||||
if "memberuser_group" in res_find:
|
||||
group = gen_intersection_list(
|
||||
group, res_find["memberuser_group"])
|
||||
else:
|
||||
group = None
|
||||
group_del = gen_intersection_list(
|
||||
group, res_find.get("memberuser_group"))
|
||||
|
||||
if allow_sudocmd is not None:
|
||||
if "memberallowcmd_sudocmd" in res_find:
|
||||
allow_sudocmd = gen_intersection_list(
|
||||
allow_sudocmd,
|
||||
res_find["memberallowcmd_sudocmd"])
|
||||
else:
|
||||
allow_sudocmd = None
|
||||
allow_cmd_del = gen_intersection_list(
|
||||
allow_sudocmd,
|
||||
res_find.get("memberallowcmd_sudocmd")
|
||||
)
|
||||
if allow_sudocmdgroup is not None:
|
||||
if "memberallowcmd_sudocmdgroup" in res_find:
|
||||
allow_sudocmdgroup = gen_intersection_list(
|
||||
allow_sudocmdgroup,
|
||||
res_find["memberallowcmd_sudocmdgroup"])
|
||||
else:
|
||||
allow_sudocmdgroup = None
|
||||
allow_cmdgroup_del = gen_intersection_list(
|
||||
allow_sudocmdgroup,
|
||||
res_find.get("memberallowcmd_sudocmdgroup")
|
||||
)
|
||||
if deny_sudocmd is not None:
|
||||
if "memberdenycmd_sudocmd" in res_find:
|
||||
deny_sudocmd = gen_intersection_list(
|
||||
deny_sudocmd,
|
||||
res_find["memberdenycmd_sudocmd"])
|
||||
else:
|
||||
deny_sudocmd = None
|
||||
deny_cmd_del = gen_intersection_list(
|
||||
deny_sudocmd,
|
||||
res_find.get("memberdenycmd_sudocmd")
|
||||
)
|
||||
if deny_sudocmdgroup is not None:
|
||||
if "memberdenycmd_sudocmdgroup" in res_find:
|
||||
deny_sudocmdgroup = gen_intersection_list(
|
||||
deny_sudocmdgroup,
|
||||
res_find["memberdenycmd_sudocmdgroup"])
|
||||
else:
|
||||
deny_sudocmdgroup = None
|
||||
deny_cmdgroup_del = gen_intersection_list(
|
||||
deny_sudocmdgroup,
|
||||
res_find.get("memberdenycmd_sudocmdgroup")
|
||||
)
|
||||
if sudooption is not None:
|
||||
if "ipasudoopt" in res_find:
|
||||
sudooption = gen_intersection_list(
|
||||
sudooption, res_find["ipasudoopt"])
|
||||
else:
|
||||
sudooption = None
|
||||
sudooption_del = gen_intersection_list(
|
||||
sudooption, res_find.get("ipasudoopt"))
|
||||
# runasuser attribute can be used with both IPA and
|
||||
# non-IPA (external) users, so we need to compare
|
||||
# the provided list against both users and external
|
||||
# users list.
|
||||
if runasuser is not None:
|
||||
if (
|
||||
"ipasudorunas_user" in res_find
|
||||
or "ipasudorunasextuser" in res_find
|
||||
):
|
||||
runasuser = gen_intersection_list(
|
||||
runasuser,
|
||||
(
|
||||
list(res_find.get('ipasudorunas_user', []))
|
||||
+ list(res_find.get(
|
||||
'ipasudorunasextuser', []))
|
||||
)
|
||||
runasuser_del = gen_intersection_list(
|
||||
runasuser,
|
||||
(
|
||||
list(res_find.get('ipasudorunas_user', []))
|
||||
+ list(res_find.get('ipasudorunasextuser', []))
|
||||
)
|
||||
else:
|
||||
runasuser = None
|
||||
)
|
||||
# runasgroup attribute can be used with both IPA and
|
||||
# non-IPA (external) groups, so we need to compare
|
||||
# the provided list against both groups and external
|
||||
# groups list.
|
||||
if runasgroup is not None:
|
||||
if (
|
||||
"ipasudorunasgroup_group" in res_find
|
||||
or "ipasudorunasextgroup" in res_find
|
||||
):
|
||||
runasgroup = gen_intersection_list(
|
||||
runasgroup,
|
||||
(
|
||||
list(res_find.get(
|
||||
"ipasudorunasgroup_group", []))
|
||||
+ list(res_find.get(
|
||||
"ipasudorunasextgroup", []))
|
||||
)
|
||||
runasgroup_del = gen_intersection_list(
|
||||
runasgroup,
|
||||
(
|
||||
list(res_find.get(
|
||||
"ipasudorunasgroup_group", []))
|
||||
+ list(res_find.get(
|
||||
"ipasudorunasextgroup", []))
|
||||
)
|
||||
else:
|
||||
runasgroup = None
|
||||
|
||||
# Remove hosts and hostgroups
|
||||
if host is not None or hostgroup is not None:
|
||||
commands.append([name, "sudorule_remove_host",
|
||||
{
|
||||
"host": host,
|
||||
"hostgroup": hostgroup,
|
||||
}])
|
||||
|
||||
# Remove users and groups
|
||||
if user is not None or group is not None:
|
||||
commands.append([name, "sudorule_remove_user",
|
||||
{
|
||||
"user": user,
|
||||
"group": group,
|
||||
}])
|
||||
|
||||
# Remove allow commands
|
||||
if allow_sudocmd is not None \
|
||||
or allow_sudocmdgroup is not None:
|
||||
commands.append([name, "sudorule_remove_allow_command",
|
||||
{"sudocmd": allow_sudocmd,
|
||||
"sudocmdgroup": allow_sudocmdgroup
|
||||
}])
|
||||
|
||||
# Remove deny commands
|
||||
if deny_sudocmd is not None \
|
||||
or deny_sudocmdgroup is not None:
|
||||
commands.append([name, "sudorule_remove_deny_command",
|
||||
{"sudocmd": deny_sudocmd,
|
||||
"sudocmdgroup": deny_sudocmdgroup
|
||||
}])
|
||||
|
||||
# Remove RunAS Users
|
||||
if runasuser is not None:
|
||||
commands.append([name, "sudorule_remove_runasuser",
|
||||
{"user": runasuser}])
|
||||
|
||||
# Remove RunAS Groups
|
||||
if runasgroup is not None:
|
||||
commands.append([name, "sudorule_remove_runasgroup",
|
||||
{"group": runasgroup}])
|
||||
|
||||
# Remove options
|
||||
if sudooption is not None:
|
||||
existing_opts = res_find.get('ipasudoopt', [])
|
||||
for sudoopt in sudooption:
|
||||
if sudoopt in existing_opts:
|
||||
commands.append([name,
|
||||
"sudorule_remove_option",
|
||||
{"ipasudoopt": sudoopt}])
|
||||
)
|
||||
|
||||
elif state == "enabled":
|
||||
if res_find is None:
|
||||
@@ -892,6 +673,99 @@ def main():
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
# Manage members.
|
||||
# Manage hosts and hostgroups
|
||||
if host_add or hostgroup_add:
|
||||
commands.append([name, "sudorule_add_host",
|
||||
{
|
||||
"host": host_add,
|
||||
"hostgroup": hostgroup_add,
|
||||
}])
|
||||
if host_del or hostgroup_del:
|
||||
commands.append([name, "sudorule_remove_host",
|
||||
{
|
||||
"host": host_del,
|
||||
"hostgroup": hostgroup_del,
|
||||
}])
|
||||
|
||||
# Manage users and groups
|
||||
if user_add or group_add:
|
||||
commands.append([
|
||||
name, "sudorule_add_user",
|
||||
{"user": user_add, "group": group_add}
|
||||
])
|
||||
if user_del or group_del:
|
||||
commands.append([
|
||||
name, "sudorule_remove_user",
|
||||
{"user": user_del, "group": group_del}
|
||||
])
|
||||
|
||||
# Manage commands allowed
|
||||
if allow_cmd_add or allow_cmdgroup_add:
|
||||
commands.append([
|
||||
name, "sudorule_add_allow_command",
|
||||
{
|
||||
"sudocmd": allow_cmd_add,
|
||||
"sudocmdgroup": allow_cmdgroup_add,
|
||||
}
|
||||
])
|
||||
if allow_cmd_del or allow_cmdgroup_del:
|
||||
commands.append([
|
||||
name, "sudorule_remove_allow_command",
|
||||
{
|
||||
"sudocmd": allow_cmd_del,
|
||||
"sudocmdgroup": allow_cmdgroup_del
|
||||
}
|
||||
])
|
||||
# Manage commands denied
|
||||
if deny_cmd_add or deny_cmdgroup_add:
|
||||
commands.append([
|
||||
name, "sudorule_add_deny_command",
|
||||
{
|
||||
"sudocmd": deny_cmd_add,
|
||||
"sudocmdgroup": deny_cmdgroup_add,
|
||||
}
|
||||
])
|
||||
if deny_cmd_del or deny_cmdgroup_del:
|
||||
commands.append([
|
||||
name, "sudorule_remove_deny_command",
|
||||
{
|
||||
"sudocmd": deny_cmd_del,
|
||||
"sudocmdgroup": deny_cmdgroup_del
|
||||
}
|
||||
])
|
||||
# Manage RunAS users
|
||||
if runasuser_add:
|
||||
commands.append([
|
||||
name, "sudorule_add_runasuser", {"user": runasuser_add}
|
||||
])
|
||||
if runasuser_del:
|
||||
commands.append([
|
||||
name, "sudorule_remove_runasuser", {"user": runasuser_del}
|
||||
])
|
||||
|
||||
# Manage RunAS Groups
|
||||
if runasgroup_add:
|
||||
commands.append([
|
||||
name, "sudorule_add_runasgroup", {"group": runasgroup_add}
|
||||
])
|
||||
if runasgroup_del:
|
||||
commands.append([
|
||||
name, "sudorule_remove_runasgroup",
|
||||
{"group": runasgroup_del}
|
||||
])
|
||||
# Manage sudo options
|
||||
if sudooption_add:
|
||||
for option in sudooption_add:
|
||||
commands.append([
|
||||
name, "sudorule_add_option", {"ipasudoopt": option}
|
||||
])
|
||||
if sudooption_del:
|
||||
for option in sudooption_del:
|
||||
commands.append([
|
||||
name, "sudorule_remove_option", {"ipasudoopt": option}
|
||||
])
|
||||
|
||||
# Execute commands
|
||||
|
||||
changed = ansible_module.execute_ipa_commands(
|
||||
|
||||
@@ -474,41 +474,31 @@ user:
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, date_format, \
|
||||
encode_certificate, load_cert_from_str, DN_x500_text, to_text
|
||||
encode_certificate, load_cert_from_str, DN_x500_text, to_text, \
|
||||
ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
|
||||
def find_user(module, name, preserved=False):
|
||||
def find_user(module, name):
|
||||
_args = {
|
||||
"all": True,
|
||||
"uid": name,
|
||||
}
|
||||
if preserved:
|
||||
_args["preserved"] = preserved
|
||||
|
||||
_result = module.ipa_command("user_find", name, _args)
|
||||
try:
|
||||
_result = module.ipa_command("user_show", name, _args).get("result")
|
||||
except ipalib_errors.NotFound:
|
||||
return None
|
||||
|
||||
if len(_result["result"]) > 1:
|
||||
module.fail_json(
|
||||
msg="There is more than one user '%s'" % (name))
|
||||
elif len(_result["result"]) == 1:
|
||||
# Transform each principal to a string
|
||||
_result = _result["result"][0]
|
||||
if "krbprincipalname" in _result \
|
||||
and _result["krbprincipalname"] is not None:
|
||||
_list = []
|
||||
for x in _result["krbprincipalname"]:
|
||||
_list.append(str(x))
|
||||
_result["krbprincipalname"] = _list
|
||||
certs = _result.get("usercertificate")
|
||||
if certs is not None:
|
||||
_result["usercertificate"] = [encode_certificate(x)
|
||||
for x in certs]
|
||||
return _result
|
||||
|
||||
return None
|
||||
# Transform each principal to a string
|
||||
_result["krbprincipalname"] = [
|
||||
to_text(x) for x in (_result.get("krbprincipalname") or [])
|
||||
]
|
||||
_result["usercertificate"] = [
|
||||
encode_certificate(x) for x in (_result.get("usercertificate") or [])
|
||||
]
|
||||
return _result
|
||||
|
||||
|
||||
def gen_args(first, last, fullname, displayname, initials, homedir, shell,
|
||||
@@ -1085,12 +1075,6 @@ def main():
|
||||
|
||||
# Make sure user exists
|
||||
res_find = find_user(ansible_module, name)
|
||||
# Also search for preserved user if the user could not be found
|
||||
if res_find is None:
|
||||
res_find_preserved = find_user(ansible_module, name,
|
||||
preserved=True)
|
||||
else:
|
||||
res_find_preserved = None
|
||||
|
||||
# Create command
|
||||
if state == "present":
|
||||
@@ -1104,10 +1088,6 @@ def main():
|
||||
departmentnumber, employeenumber, employeetype,
|
||||
preferredlanguage, noprivate, nomembers)
|
||||
|
||||
# Also check preserved users
|
||||
if res_find is None and res_find_preserved is not None:
|
||||
res_find = res_find_preserved
|
||||
|
||||
if action == "user":
|
||||
# Found the user
|
||||
if res_find is not None:
|
||||
@@ -1310,16 +1290,16 @@ def main():
|
||||
gen_certmapdata_args(_data)])
|
||||
|
||||
elif state == "absent":
|
||||
# Also check preserved users
|
||||
if res_find is None and res_find_preserved is not None:
|
||||
res_find = res_find_preserved
|
||||
|
||||
if action == "user":
|
||||
if res_find is not None:
|
||||
args = {}
|
||||
if preserve is not None:
|
||||
args["preserve"] = preserve
|
||||
commands.append([name, "user_del", args])
|
||||
if (
|
||||
not res_find.get("preserved", False)
|
||||
or not args.get("preserve", False)
|
||||
):
|
||||
commands.append([name, "user_del", args])
|
||||
elif action == "member":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(
|
||||
@@ -1370,17 +1350,18 @@ def main():
|
||||
commands.append([name, "user_remove_certmapdata",
|
||||
gen_certmapdata_args(_data)])
|
||||
elif state == "undeleted":
|
||||
if res_find_preserved is not None:
|
||||
commands.append([name, "user_undel", {}])
|
||||
if res_find is not None:
|
||||
if res_find.get("preserved", False):
|
||||
commands.append([name, "user_undel", {}])
|
||||
else:
|
||||
raise ValueError("No preserved user '%s'" % name)
|
||||
raise ValueError("No user '%s'" % name)
|
||||
|
||||
elif state == "enabled":
|
||||
if res_find is not None:
|
||||
if res_find["nsaccountlock"]:
|
||||
commands.append([name, "user_enable", {}])
|
||||
else:
|
||||
raise ValueError("No disabled user '%s'" % name)
|
||||
raise ValueError("No user '%s'" % name)
|
||||
|
||||
elif state == "disabled":
|
||||
if res_find is not None:
|
||||
@@ -1392,6 +1373,8 @@ def main():
|
||||
elif state == "unlocked":
|
||||
if res_find is not None:
|
||||
commands.append([name, "user_unlock", {}])
|
||||
else:
|
||||
raise ValueError("No user '%s'" % name)
|
||||
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
@@ -33,7 +33,6 @@ Requirements
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* /usr/bin/kinit is required on the controller if a one time password (OTP) is used
|
||||
* python3-gssapi is required on the controller if a one time password (OTP) is used with keytab
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -21,10 +21,6 @@ from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
try:
|
||||
import gssapi
|
||||
except ImportError:
|
||||
gssapi = None
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
@@ -82,22 +78,17 @@ def kinit_keytab(principal, keytab, ccache_name, config):
|
||||
It uses the specified config file to kinit and stores the TGT
|
||||
in ccache_name.
|
||||
"""
|
||||
if gssapi is None:
|
||||
raise ImportError("gssapi is not available")
|
||||
|
||||
args = ["/usr/bin/kinit", "-kt", keytab, "-c", ccache_name, principal]
|
||||
old_config = os.environ.get('KRB5_CONFIG')
|
||||
os.environ['KRB5_CONFIG'] = config
|
||||
os.environ["KRB5_CONFIG"] = config
|
||||
|
||||
try:
|
||||
name = gssapi.Name(principal, gssapi.NameType.kerberos_principal)
|
||||
store = {'ccache': ccache_name,
|
||||
'client_keytab': keytab}
|
||||
cred = gssapi.Credentials(name=name, store=store, usage='initiate')
|
||||
return cred
|
||||
return run_cmd(args)
|
||||
finally:
|
||||
if old_config is not None:
|
||||
os.environ['KRB5_CONFIG'] = old_config
|
||||
os.environ["KRB5_CONFIG"] = old_config
|
||||
else:
|
||||
os.environ.pop('KRB5_CONFIG', None)
|
||||
os.environ.pop("KRB5_CONFIG", None)
|
||||
|
||||
|
||||
KRB5CONF_TEMPLATE = """
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: Test automountmap
|
||||
hosts: ipaserver
|
||||
hosts: "{{ ipa_test_host | default('ipaserver') }}"
|
||||
become: no
|
||||
gather_facts: no
|
||||
|
||||
|
||||
40
tests/automount/test_automountmap_client_context.yml
Normal file
40
tests/automount/test_automountmap_client_context.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
- name: Test automountmap
|
||||
hosts: ipaclients, ipaserver
|
||||
become: no
|
||||
gather_facts: no
|
||||
|
||||
tasks:
|
||||
- name: Include FreeIPA facts.
|
||||
include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
# Test will only be executed if host is not a server.
|
||||
- name: Execute with server context in the client.
|
||||
ipaautomountmap:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: server
|
||||
location: default
|
||||
name: ThisShouldNotWork
|
||||
register: result
|
||||
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
|
||||
when: ipa_host_is_client
|
||||
|
||||
# Import basic module tests, and execute with ipa_context set to 'client'.
|
||||
# If ipaclients is set, it will be executed using the client, if not,
|
||||
# ipaserver will be used.
|
||||
#
|
||||
# With this setup, tests can be executed against an IPA client, against
|
||||
# an IPA server using "client" context, and ensure that tests are executed
|
||||
# in upstream CI.
|
||||
|
||||
- name: Test automountmap using client context, in client host.
|
||||
import_playbook: test_automountmap.yml
|
||||
when: groups['ipaclients']
|
||||
vars:
|
||||
ipa_test_host: ipaclients
|
||||
|
||||
- name: Test automountmap using client context, in server host.
|
||||
import_playbook: test_automountmap.yml
|
||||
when: groups['ipaclients'] is not defined or not groups['ipaclients']
|
||||
vars:
|
||||
ipa_context: client
|
||||
@@ -17,6 +17,7 @@
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
port: 53
|
||||
state: absent
|
||||
action: member
|
||||
|
||||
# Tests.
|
||||
- name: Set config to invalid IPv4.
|
||||
@@ -74,23 +75,72 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarder is absent.
|
||||
- name: Ensure forwarder 8.8.8.8 is absent.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.8.8
|
||||
state: absent
|
||||
action: member
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarder is absent, again.
|
||||
- name: Ensure forwarder 8.8.8.8 is absent, again.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.8.8
|
||||
state: absent
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarder 8.8.4.4 is present.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarder 8.8.8.8 is present.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.8.8
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarder 8.8.4.4 is present.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarders are absent.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
- ip_address: 8.8.8.8
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarders are absent, again.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
- ip_address: 8.8.8.8
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
@@ -168,10 +218,10 @@
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
port: 53
|
||||
state: absent
|
||||
action: member
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
|
||||
- name: Ensure all forwarders are absent, again.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -182,6 +232,69 @@
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
port: 53
|
||||
state: absent
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarder is present.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.8.8
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarders is not present.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
check_mode: yes
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarders are present.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
- ip_address: 8.8.8.8
|
||||
action: member
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarders are present, again.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
- ip_address: 8.8.8.8
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure another forwarder is present.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure forwarders are present.
|
||||
ipadnsconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
forwarders:
|
||||
- ip_address: 8.8.4.4
|
||||
- ip_address: 8.8.8.8
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
@@ -197,3 +310,4 @@
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
port: 53
|
||||
state: absent
|
||||
action: member
|
||||
|
||||
@@ -2,9 +2,20 @@
|
||||
- name: Test group
|
||||
hosts: "{{ ipa_test_host | default('ipaserver') }}"
|
||||
become: true
|
||||
gather_facts: false
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
# setup
|
||||
- include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
# GET FQDN_AT_DOMAIN
|
||||
|
||||
- name: Get fqdn_at_domain
|
||||
set_fact:
|
||||
fqdn_at_domain: "{{ ansible_facts['fqdn'] + '@' + ipaserver_realm }}"
|
||||
|
||||
# CLEANUP TEST ITEMS
|
||||
|
||||
- name: Ensure users user1, user2 and user3 are absent
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -19,6 +30,8 @@
|
||||
name: group3,group2,group1
|
||||
state: absent
|
||||
|
||||
# CREATE TEST ITEMS
|
||||
|
||||
- name: Ensure users user1..user3 are present
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -36,6 +49,8 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
# TESTS
|
||||
|
||||
- name: Ensure group1 is present
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -119,6 +134,156 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
# service
|
||||
|
||||
- block:
|
||||
|
||||
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is present in group group1
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'HTTP/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is present in group group1, again
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'HTTP/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure service "{{ 'ldap/' + fqdn_at_domain }}" is present in group group1
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'ldap/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure service "{{ 'ldap/' + fqdn_at_domain }}" is present in group group1, again
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'ldap/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is absent in group group1
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'HTTP/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is absent in group group1, again
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'HTTP/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure service "{{ 'ldap/' + fqdn_at_domain }}" is absent in group group1
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'ldap/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure service "{{ 'ldap/' + fqdn_at_domain }}" is absent in group group1, again
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'ldap/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure services are present in group group1
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'HTTP/' + fqdn_at_domain }}"
|
||||
- "{{ 'ldap/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure services are present in group group1, again
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'http/' + fqdn_at_domain }}"
|
||||
- "{{ 'ldap/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure services are absent in group group1
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'HTTP/' + fqdn_at_domain }}"
|
||||
- "{{ 'LDAP/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure services are absent in group group1, again
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: group1
|
||||
service:
|
||||
- "{{ 'HTTP/' + fqdn_at_domain }}"
|
||||
- "{{ 'ldap/' + fqdn_at_domain }}"
|
||||
action: member
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
when: ipa_version is version('4.7.0', '>=')
|
||||
|
||||
# user
|
||||
|
||||
- name: Ensure users user1, user2 and user3 are present in group group1
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -297,6 +462,8 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
# CLEANUP TEST ITEMS
|
||||
|
||||
- name: Ensure group group3, group2 and group1 are absent
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
@@ -133,6 +133,19 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure hosts db1 and db2 (no FQDN) are member of host-group databases again
|
||||
ipahostgroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: databases
|
||||
state: present
|
||||
host:
|
||||
- db1
|
||||
- db2
|
||||
action: member
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure host-group mysql-server is member of host-group databases
|
||||
ipahostgroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
name:
|
||||
- /sbin/ifconfig
|
||||
- /usr/bin/vim
|
||||
- /usr/bin/emacs
|
||||
state: present
|
||||
|
||||
- name: Ensure sudocmdgroup is available
|
||||
@@ -68,6 +69,14 @@
|
||||
sudocmd: /usr/bin/vim
|
||||
state: present
|
||||
|
||||
- name: Ensure sudocmdgroup is available
|
||||
ipasudocmdgroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: test_sudorule2
|
||||
sudocmd: /usr/bin/emacs
|
||||
state: present
|
||||
|
||||
- name: Ensure sudorules are absent
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -606,6 +615,7 @@
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
allow_sudocmdgroup: test_sudorule
|
||||
action: member
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
@@ -616,6 +626,7 @@
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
allow_sudocmdgroup: test_sudorule
|
||||
action: member
|
||||
state: present
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
@@ -648,6 +659,7 @@
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
deny_sudocmdgroup: test_sudorule
|
||||
action: member
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
@@ -658,6 +670,7 @@
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
deny_sudocmdgroup: test_sudorule
|
||||
action: member
|
||||
state: present
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
@@ -684,6 +697,114 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with `test_sudorule` sudocmdgroup in allow_sudocmdgroup.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
allow_sudocmdgroup: test_sudorule
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with `test_sudorule2` sudocmdgroup in allow_sudocmdgroup.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
allow_sudocmdgroup: test_sudorule2
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with both sudocmdgroup in allow_sudocmdgroup.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
allow_sudocmdgroup:
|
||||
- test_sudorule
|
||||
- test_sudorule2
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with both sudocmdgroup, again.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
allow_sudocmdgroup:
|
||||
- test_sudorule
|
||||
- test_sudorule2
|
||||
state: present
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with only `test_sudorule` sudocmdgroup in allow_sudocmdgroup.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
allow_sudocmdgroup: test_sudorule
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with `test_sudorule` sudocmdgroup in deny_sudocmdgroup.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
deny_sudocmdgroup: test_sudorule
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with `test_sudorule2` sudocmdgroup in deny_sudocmdgroup.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
deny_sudocmdgroup: test_sudorule2
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with both sudocmdgroup in deny_sudocmdgroup.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
deny_sudocmdgroup:
|
||||
- test_sudorule
|
||||
- test_sudorule2
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with both sudocmdgroup, again.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
deny_sudocmdgroup:
|
||||
- test_sudorule
|
||||
- test_sudorule2
|
||||
state: present
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is present, with only `test_sudorule` sudocmdgroup in deny_sudocmdgroup.
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testrule1
|
||||
deny_sudocmdgroup: test_sudorule
|
||||
state: present
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure sudorule is absent
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -889,7 +1010,9 @@
|
||||
ipasudocmdgroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: test_sudorule
|
||||
name:
|
||||
- test_sudorule
|
||||
- test_sudorule2
|
||||
state: absent
|
||||
|
||||
- name: Ensure sudocmds are absent
|
||||
@@ -899,6 +1022,7 @@
|
||||
name:
|
||||
- /sbin/ifconfig
|
||||
- /usr/bin/vim
|
||||
- /usr/bin/emacs
|
||||
state: absent
|
||||
|
||||
- name: Ensure sudorules are absent
|
||||
|
||||
290
tests/sudorule/test_sudorule_member_case_insensitive.yml
Normal file
290
tests/sudorule/test_sudorule_member_case_insensitive.yml
Normal file
@@ -0,0 +1,290 @@
|
||||
---
|
||||
- name: Test sudorule members should be case insensitive.
|
||||
hosts: "{{ ipa_test_host | default('ipaserver') }}"
|
||||
become: no
|
||||
gather_facts: no
|
||||
|
||||
vars:
|
||||
groups_present:
|
||||
- eleMENT1
|
||||
- Element2
|
||||
- eLeMenT3
|
||||
- ElemENT4
|
||||
|
||||
|
||||
tasks:
|
||||
- block:
|
||||
# SETUP
|
||||
- name: Ensure domain name
|
||||
set_fact:
|
||||
ipa_domain: ipa.test
|
||||
when: ipa_domain is not defined
|
||||
|
||||
- name: Ensure test groups exist.
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
- name: Ensure test hostgroups exist.
|
||||
ipahostgroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
- name: Ensure test hosts exist.
|
||||
ipahost:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}.{{ ipa_domain }}"
|
||||
force: yes
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
- name: Ensure test users exist.
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "user{{ item }}"
|
||||
first: "{{ item }}"
|
||||
last: "{{ item }}"
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
- name: Ensure sudorule do not exist
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
# TESTS
|
||||
- name: Start tests.
|
||||
debug:
|
||||
msg: "Tests are starting."
|
||||
|
||||
- name: Ensure sudorule exist with runasusers members
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
runasuser: "user{{ item }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or not result.changed
|
||||
|
||||
- name: Ensure sudorule exist with lowercase runasusers members
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
runasuser: "user{{ item | lower }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule exist with uppercase runasusers members
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
runasuser: "user{{ item | upper }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule exist with runasgroup members
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
runasgroup: "{{ item }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or not result.changed
|
||||
|
||||
- name: Ensure sudorule exist with lowercase runasgroup members
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
runasgroup: "{{ item | lower }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule exist with uppercase runasgroup members
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
runasgroup: "{{ item | upper }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule do not exist
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
#####
|
||||
|
||||
- name: Ensure sudorule exist with members
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
hostgroup: "{{ item }}"
|
||||
host: "{{ item }}.{{ ipa_domain }}"
|
||||
group: "{{ item }}"
|
||||
user: "user{{ item }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or not result.changed
|
||||
|
||||
- name: Ensure sudorule exist with members, lowercase
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
hostgroup: "{{ item | lower }}"
|
||||
host: "{{ item | lower }}.{{ ipa_domain }}"
|
||||
group: "{{ item | lower }}"
|
||||
user: "user{{ item | lower }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule exist with members, uppercase
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
cmdcategory: all
|
||||
hostgroup: "{{ item | upper }}"
|
||||
host: "{{ item | upper }}.{{ ipa_domain }}"
|
||||
group: "{{ item | upper }}"
|
||||
user: "user{{ item | upper }}"
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule member is absent
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
hostgroup: "{{ item }}"
|
||||
host: "{{ item }}.{{ ipa_domain }}"
|
||||
group: "{{ item }}"
|
||||
user: "user{{ item }}"
|
||||
action: member
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or not result.changed
|
||||
|
||||
- name: Ensure sudorule member is absent, lowercase
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
hostgroup: "{{ item | lower }}"
|
||||
host: "{{ item | lower }}.{{ ipa_domain }}"
|
||||
group: "{{ item | lower }}"
|
||||
user: "user{{ item | lower }}"
|
||||
action: member
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule member is absent, upercase
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
hostgroup: "{{ item | upper }}"
|
||||
host: "{{ item | upper }}.{{ ipa_domain }}"
|
||||
group: "{{ item | upper }}"
|
||||
user: "user{{ item | upper }}"
|
||||
action: member
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule member is present, upercase
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
hostgroup: "{{ item | upper }}"
|
||||
host: "{{ item | upper }}.{{ ipa_domain }}"
|
||||
group: "{{ item | upper }}"
|
||||
user: "user{{ item | upper }}"
|
||||
action: member
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or not result.changed
|
||||
|
||||
- name: Ensure sudorule member is present, lowercase
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
hostgroup: "{{ item | lower }}"
|
||||
host: "{{ item | lower }}.{{ ipa_domain }}"
|
||||
group: "{{ item | lower }}"
|
||||
user: "user{{ item | lower }}"
|
||||
action: member
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: Ensure sudorule member is present, mixed case
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
hostgroup: "{{ item }}"
|
||||
host: "{{ item }}.{{ ipa_domain }}"
|
||||
group: "{{ item }}"
|
||||
user: "user{{ item }}"
|
||||
action: member
|
||||
loop: "{{ groups_present }}"
|
||||
register: result
|
||||
failed_when: result.failed or result.changed
|
||||
|
||||
- name: End tests.
|
||||
debug:
|
||||
msg: "All tests executed."
|
||||
|
||||
always:
|
||||
# cleanup
|
||||
- name: Ensure sudorule do not exist
|
||||
ipasudorule:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
- name: Ensure test groups do not exist.
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
- name: Ensure test hostgroups do not exist.
|
||||
ipahostgroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
- name: Ensure test hosts do not exist.
|
||||
ipahost:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "{{ item }}.{{ ipa_domain }}"
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
|
||||
- name: Ensure test users do not exist.
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "user{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ groups_present }}"
|
||||
@@ -51,8 +51,8 @@
|
||||
gid: 100
|
||||
phone: "+555123457"
|
||||
email: pinky@acme.com
|
||||
principalexpiration: "20220119235959"
|
||||
#passwordexpiration: "2022-01-19 23:59:59"
|
||||
principalexpiration: "21220119235959"
|
||||
passwordexpiration: "2122-01-19 23:59:59"
|
||||
first: pinky
|
||||
last: Acme
|
||||
initials: pa
|
||||
@@ -249,6 +249,16 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky absent and preserved, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
preserve: yes
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: User pinky undeleted (preserved before)
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -258,6 +268,15 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky undeleted (preserved before), again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
state: undeleted
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Users pinky disabled
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -267,6 +286,15 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Users pinky disabled, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
state: disabled
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: User pinky enabled
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -276,6 +304,44 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky enabled, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
state: enabled
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: User pinky absent and preserved for future exclusion.
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
preserve: yes
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky absent
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky absent and preserved, when already absent
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
preserve: yes
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Remove test users
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
@@ -143,8 +143,8 @@
|
||||
gid: 100
|
||||
phone: "+555123457"
|
||||
email: pinky@acme.com
|
||||
principalexpiration: "20220119235959"
|
||||
#passwordexpiration: "2022-01-19 23:59:59"
|
||||
principalexpiration: "21220119235959"
|
||||
passwordexpiration: "2122-01-19 23:59:59"
|
||||
first: pinky
|
||||
last: Acme
|
||||
initials: pa
|
||||
@@ -186,8 +186,8 @@
|
||||
gid: 100
|
||||
phone: "+555123457"
|
||||
email: pinky@acme.com
|
||||
principalexpiration: "20220119235959"
|
||||
#passwordexpiration: "2022-01-19 23:59:59"
|
||||
principalexpiration: "21220119235959"
|
||||
passwordexpiration: "2122-01-19 23:59:59"
|
||||
first: pinky
|
||||
last: Acme
|
||||
initials: pa
|
||||
@@ -369,6 +369,15 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky absent and preserved, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: pinky
|
||||
preserve: yes
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: User pinky undeleted (preserved before)
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -377,6 +386,14 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky undeleted (preserved before), again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: pinky
|
||||
state: undeleted
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Users pinky disabled
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -385,6 +402,14 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Users pinky disabled, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: pinky
|
||||
state: disabled
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: User pinky enabled
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -393,6 +418,43 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky enabled, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: pinky
|
||||
state: enabled
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: User pinky absent and preserved for future exclusion.
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
preserve: yes
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky absent
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky absent and preserved, when already absent
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
preserve: yes
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Remove test users
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
Reference in New Issue
Block a user