import ansible-freeipa-0.1.8-3.el8

This commit is contained in:
CentOS Sources 2020-04-28 04:55:51 -04:00 committed by Stepan Oksanichenko
parent 961430aca3
commit 0695dc66b6
17 changed files with 3778 additions and 179 deletions

View File

@ -1 +1 @@
4dcce87f3b09e7c53760980e6687de575a44ee4e SOURCES/ansible-freeipa-0.1.6.tar.gz
583ac570c030eb68a2026a506054f2f93587beb4 SOURCES/ansible-freeipa-0.1.8.tar.gz

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/ansible-freeipa-0.1.6.tar.gz
SOURCES/ansible-freeipa-0.1.8.tar.gz

View File

@ -1,51 +0,0 @@
From 5bb44245c6c43d752c1e066ebdc6cb3eb0253d98 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Wed, 4 Sep 2019 14:40:46 +0200
Subject: [PATCH] ansible_ipa_client: Drop import of
configure_nsswitch_database
configure_nsswitch_database has been removed with the freeipa commit
https://github.com/freeipa/freeipa/commit/41ef8fba31ddbb32e2e5b7cccdc9b582a0809111
The 4.4 compatibility hack leads to a ALREADY installed error in
ipaclient_test because of the removal. This affects ipaclient and
ipareplica roles and also the ipaclient deployment part in ipaserver.
configure_nsswitch_database is not used any more in ipaclient role modules
and therefore simply can be removed from ansible_ipa_client.
---
roles/ipaclient/module_utils/ansible_ipa_client.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/roles/ipaclient/module_utils/ansible_ipa_client.py b/roles/ipaclient/module_utils/ansible_ipa_client.py
index 30b8d42..d45171b 100644
--- a/roles/ipaclient/module_utils/ansible_ipa_client.py
+++ b/roles/ipaclient/module_utils/ansible_ipa_client.py
@@ -35,7 +35,7 @@
"configure_sssd_conf", "realm_to_suffix", "run", "timeconf",
"serialization", "configure_krb5_conf", "get_ca_certs",
"SECURE_PATH", "get_server_connection_interface",
- "configure_nsswitch_database", "disable_ra", "client_dns",
+ "disable_ra", "client_dns",
"configure_certmonger", "update_ssh_keys",
"configure_openldap_conf", "hardcode_ldap_server",
"get_certs_from_ldap", "save_state", "create_ipa_nssdb",
@@ -143,7 +143,7 @@ def knobs(self):
try:
from ipaclient.install.client import configure_krb5_conf, \
get_ca_certs, SECURE_PATH, get_server_connection_interface, \
- configure_nsswitch_database, disable_ra, client_dns, \
+ disable_ra, client_dns, \
configure_certmonger, update_ssh_keys, configure_openldap_conf, \
hardcode_ldap_server, get_certs_from_ldap, save_state, \
create_ipa_nssdb, configure_ssh_config, configure_sshd_config, \
@@ -204,8 +204,6 @@ def configure_krb5_conf(
get_server_connection_interface = \
ipa_client_install.get_server_connection_interface
- configure_nsswitch_database = \
- ipa_client_install.configure_nsswitch_database
disable_ra = ipa_client_install.disable_ra
client_dns = ipa_client_install.client_dns
configure_certmonger = ipa_client_install.configure_certmonger

View File

@ -1,13 +0,0 @@
diff -up ansible-freeipa-0.1.6/utils/gen_module_docs.py.remove-key-dirserv_cert_files ansible-freeipa-0.1.6/utils/gen_module_docs.py
--- ansible-freeipa-0.1.6/utils/gen_module_docs.py.gen_module_docs-drop-key-dirserv_cert_files 2019-07-23 10:01:59.000000000 +0200
+++ ansible-freeipa-0.1.6/utils/gen_module_docs.py 2019-07-23 11:27:12.921162481 +0200
@@ -47,9 +47,6 @@ param_docs = {
"setup_ca": "Configure a dogtag CA",
"setup_kra": "Configure a dogtag KRA",
"setup_dns": "Configure bind with our zone",
- "dirserv_cert_files": [
- "File containing the Directory Server SSL certificate and private key"
- ],
"force_join": "Force client enrollment even if already enrolled",
"subject_base": [
"The certificate subject base (default O=<realm-name>).",

View File

@ -1,62 +0,0 @@
From e4497c18e9fb39b4e8c022eb0898060005cf6af6 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Fri, 26 Jul 2019 18:33:41 +0200
Subject: [PATCH] ipatopologysegment: Store suffix for commands in command list
With adding the domain and ca suffixes with `suffix: domain+ca` only ca
has been added as the suffix was only used from the last command. The
suffix is now stored together with the command and the argument. This
will fix this error.
Fixes: #106 (Last suffix adding twice in the list of topology segments)
---
plugins/modules/ipatopologysegment.py | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/plugins/modules/ipatopologysegment.py b/plugins/modules/ipatopologysegment.py
index d64c7be..e768f72 100644
--- a/plugins/modules/ipatopologysegment.py
+++ b/plugins/modules/ipatopologysegment.py
@@ -256,12 +256,12 @@ def main():
del args[key]
if len(args) > 1:
# cn needs to be in args always
- commands.append(["topologysegment_mod", args])
+ commands.append(["topologysegment_mod", args, suffix])
# else: Nothing to change
else:
if name is None:
args["cn"] = to_text("%s-to-%s" % (left, right))
- commands.append(["topologysegment_add", args])
+ commands.append(["topologysegment_add", args, suffix])
elif state in ["absent", "disabled"]:
# Make sure topology segment does not exist
@@ -274,7 +274,7 @@ def main():
args = {
"cn": res_find["cn"][0]
}
- commands.append(["topologysegment_del", args])
+ commands.append(["topologysegment_del", args, suffix])
elif state == "checked":
# Check if topology segment does exists
@@ -309,14 +309,15 @@ def main():
elif direction == "right-to-left":
args["right"] = True
- commands.append(["topologysegment_reinitialize", args])
+ commands.append(["topologysegment_reinitialize", args,
+ suffix])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute command
- for command, args in commands:
- api_command(ansible_module, command, to_text(suffix), args)
+ for command, args, _suffix in commands:
+ api_command(ansible_module, command, to_text(_suffix), args)
changed = True
except Exception as e:

View File

@ -1,38 +0,0 @@
From c212b43516cb870bbaa86c607dde33f373768043 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Fri, 26 Jul 2019 19:30:11 +0200
Subject: [PATCH] ipatopologysegment: Fail for missing entry with reinitialized
Currently it is ignored if the entry for reinitialized can not be found if
the name or left and right are not correct. Now there is a failure in this
case.
Fixes: #107 (Reinitialize are failed to find the node in ipatopology ..)
Signed-off-by: Thomas Woerner <twoerner@redhat.com>
---
plugins/modules/ipatopologysegment.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/plugins/modules/ipatopologysegment.py b/plugins/modules/ipatopologysegment.py
index e768f72..e506b53 100644
--- a/plugins/modules/ipatopologysegment.py
+++ b/plugins/modules/ipatopologysegment.py
@@ -311,6 +311,18 @@ def main():
commands.append(["topologysegment_reinitialize", args,
suffix])
+ else:
+ params = []
+ if name is not None:
+ params.append("name=%s" % name)
+ if left is not None:
+ params.append("left=%s" % left)
+ if right is not None:
+ params.append("right=%s" % right)
+ ansible_module.fail_json(
+ msg="No entry '%s' for suffix '%s'" %
+ (",".join(params), suffix))
+
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)

View File

@ -0,0 +1,177 @@
From 3780a9a00e77ae0fd2944b36adad446d094fc90f Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Tue, 11 Feb 2020 10:34:39 +0100
Subject: [PATCH] ansible_freeipa_module: Fix comparison of bool parameters in
compare_args_ipa
Bool types are not iterable. Therefore the comparison using sets was failing
with a TypeError. This prevented to change the bool parameters for hosts.
A test for the host module has been added to verify that the bool parameters
can be modified.
New test:
tests/host/test_host_bool_params.yml
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1784514
---
.../module_utils/ansible_freeipa_module.py | 18 ++-
tests/host/test_host_bool_params.yml | 119 ++++++++++++++++++
2 files changed, 133 insertions(+), 4 deletions(-)
create mode 100644 tests/host/test_host_bool_params.yml
diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
index 8154a12..9e97b88 100644
--- a/plugins/module_utils/ansible_freeipa_module.py
+++ b/plugins/module_utils/ansible_freeipa_module.py
@@ -222,10 +222,20 @@ def compare_args_ipa(module, args, ipa):
arg = [to_text(_arg) for _arg in arg]
if isinstance(ipa_arg[0], unicode) and isinstance(arg[0], int):
arg = [to_text(_arg) for _arg in arg]
- # module.warn("%s <=> %s" % (arg, ipa_arg))
- if set(arg) != set(ipa_arg):
- # module.warn("DIFFERENT")
- return False
+ # module.warn("%s <=> %s" % (repr(arg), repr(ipa_arg)))
+ try:
+ arg_set = set(arg)
+ ipa_arg_set = set(ipa_arg)
+ except TypeError:
+ if arg != ipa_arg:
+ # module.warn("%s != %s" % (repr(arg), repr(ipa_arg)))
+ return False
+ else:
+ if arg_set != ipa_arg_set:
+ # module.warn("%s != %s" % (repr(arg), repr(ipa_arg)))
+ return False
+
+ # module.warn("%s == %s" % (repr(arg), repr(ipa_arg)))
return True
diff --git a/tests/host/test_host_bool_params.yml b/tests/host/test_host_bool_params.yml
new file mode 100644
index 0000000..824ea99
--- /dev/null
+++ b/tests/host/test_host_bool_params.yml
@@ -0,0 +1,119 @@
+---
+- name: Test host bool parameters
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ - name: Get Domain from server name
+ set_fact:
+ ipaserver_domain: "{{ groups.ipaserver[0].split('.')[1:] | join ('.') }}"
+ when: ipaserver_domain is not defined
+
+ - name: Set host1_fqdn .. host6_fqdn
+ set_fact:
+ host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
+
+ - name: Host absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name:
+ - "{{ host1_fqdn }}"
+ update_dns: yes
+ state: absent
+
+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ force: yes
+ requires_pre_auth: yes
+ ok_as_delegate: yes
+ ok_to_auth_as_delegate: yes
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ requires_pre_auth: yes
+ ok_as_delegate: yes
+ ok_to_auth_as_delegate: yes
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate set to no
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ requires_pre_auth: no
+ ok_as_delegate: no
+ ok_to_auth_as_delegate: no
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate set to no again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ requires_pre_auth: no
+ ok_as_delegate: no
+ ok_to_auth_as_delegate: no
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ requires_pre_auth: yes
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ requires_pre_auth: yes
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with ok_as_delegate
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ok_as_delegate: yes
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with ok_as_delegate again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ok_as_delegate: yes
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with ok_to_auth_as_delegate
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ok_to_auth_as_delegate: yes
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" present with ok_to_auth_as_delegate again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ok_to_auth_as_delegate: yes
+ register: result
+ failed_when: result.changed
+
+ - name: Host absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name:
+ - "{{ host1_fqdn }}"
+ update_dns: yes
+ state: absent

View File

@ -0,0 +1,838 @@
From 3865ce657e3ea1b621aa054c792201aedfde2d11 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Fri, 7 Feb 2020 10:11:38 +0100
Subject: [PATCH] ipahbacrule: Fix handing of members with action hbacrule
Changing members (host, hostgroup, hbacsvc, hbacsvcgroup, user, group) with
action hbacrule was not working due to the use of the wrong parameter
prefix. This has been fixed and the old members are removed correctly now.
The test script has been reworked completely to verify the fix.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1787996
---
plugins/modules/ipahbacrule.py | 24 +-
tests/hbacrule/test_hbacrule.yml | 549 +++++++++++++++++++++++--------
2 files changed, 432 insertions(+), 141 deletions(-)
diff --git a/plugins/modules/ipahbacrule.py b/plugins/modules/ipahbacrule.py
index 385876b..82340c2 100644
--- a/plugins/modules/ipahbacrule.py
+++ b/plugins/modules/ipahbacrule.py
@@ -344,41 +344,41 @@ def main():
# Generate addition and removal lists
host_add = list(
set(host or []) -
- set(res_find.get("member_host", [])))
+ set(res_find.get("memberhost_host", [])))
host_del = list(
- set(res_find.get("member_host", [])) -
+ set(res_find.get("memberhost_host", [])) -
set(host or []))
hostgroup_add = list(
set(hostgroup or []) -
- set(res_find.get("member_hostgroup", [])))
+ set(res_find.get("memberhost_hostgroup", [])))
hostgroup_del = list(
- set(res_find.get("member_hostgroup", [])) -
+ set(res_find.get("memberhost_hostgroup", [])) -
set(hostgroup or []))
hbacsvc_add = list(
set(hbacsvc or []) -
- set(res_find.get("member_hbacsvc", [])))
+ set(res_find.get("memberservice_hbacsvc", [])))
hbacsvc_del = list(
- set(res_find.get("member_hbacsvc", [])) -
+ set(res_find.get("memberservice_hbacsvc", [])) -
set(hbacsvc or []))
hbacsvcgroup_add = list(
set(hbacsvcgroup or []) -
- set(res_find.get("member_hbacsvcgroup", [])))
+ set(res_find.get("memberservice_hbacsvcgroup", [])))
hbacsvcgroup_del = list(
- set(res_find.get("member_hbacsvcgroup", [])) -
+ set(res_find.get("memberservice_hbacsvcgroup", [])) -
set(hbacsvcgroup or []))
user_add = list(
set(user or []) -
- set(res_find.get("member_user", [])))
+ set(res_find.get("memberuser_user", [])))
user_del = list(
- set(res_find.get("member_user", [])) -
+ set(res_find.get("memberuser_user", [])) -
set(user or []))
group_add = list(
set(group or []) -
- set(res_find.get("member_group", [])))
+ set(res_find.get("memberuser_group", [])))
group_del = list(
- set(res_find.get("member_group", [])) -
+ set(res_find.get("memberuser_group", [])) -
set(group or []))
# Add hosts and hostgroups
diff --git a/tests/hbacrule/test_hbacrule.yml b/tests/hbacrule/test_hbacrule.yml
index a5615cc..38858d3 100644
--- a/tests/hbacrule/test_hbacrule.yml
+++ b/tests/hbacrule/test_hbacrule.yml
@@ -1,338 +1,629 @@
---
-- name: Tests
+- name: Playbook to handle hbacrules
hosts: ipaserver
become: true
- gather_facts: false
tasks:
- - name: Ensure HBAC Rule allhosts is absent
- ipahbacrule:
+ - name: Get Domain from server name
+ set_fact:
+ ipaserver_domain: "{{ groups.ipaserver[0].split('.')[1:] | join ('.') }}"
+ when: ipaserver_domain is not defined
+
+ # CLEANUP TEST ITEMS
+
+ - name: Ensure test hosts are absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
+ - "{{ 'testhost03.' + ipaserver_domain }}"
+ - "{{ 'testhost04.' + ipaserver_domain }}"
+ state: absent
+
+ - name: Ensure test hostgroups are absent
+ ipahostgroup:
ipaadmin_password: MyPassword123
- name: allhosts,sshd-pinky,loginRule
+ name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04
state: absent
- - name: User pinky absent
+ - name: Ensure test users are absent
ipauser:
ipaadmin_password: MyPassword123
- name: pinky
+ name: testuser01,testuser02,testuser03,testuser04
state: absent
- - name: User group login absent
+ - name: Ensure test user groups are absent
ipagroup:
ipaadmin_password: MyPassword123
- name: login
+ name: testgroup01,testgroup02,testgroup03,testgroup04
+ state: absent
+
+ - name: Ensure test HBAC Services are absent
+ ipahbacsvc:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04
+ state: absent
+
+ - name: Ensure test HBAC Service Groups are absent
+ ipahbacsvcgroup:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04
state: absent
- - name: User pinky present
+ # CREATE TEST ITEMS
+
+ - name: Ensure hosts "{{ 'host[1..4].' + ipaserver_domain }}" are present
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ 'testhost01.' + ipaserver_domain }}"
+ force: yes
+ - name: "{{ 'testhost02.' + ipaserver_domain }}"
+ force: yes
+ - name: "{{ 'testhost03.' + ipaserver_domain }}"
+ force: yes
+ - name: "{{ 'testhost04.' + ipaserver_domain }}"
+ force: yes
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure host-group testhostgroup01 is present
+ ipahostgroup:
+ ipaadmin_password: MyPassword123
+ name: testhostgroup01
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure host-group testhostgroup02 is present
+ ipahostgroup:
+ ipaadmin_password: MyPassword123
+ name: testhostgroup02
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure host-group testhostgroup03 is present
+ ipahostgroup:
+ ipaadmin_password: MyPassword123
+ name: testhostgroup03
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure host-group testhostgroup04 is present
+ ipahostgroup:
+ ipaadmin_password: MyPassword123
+ name: testhostgroup04
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure testusers are present
ipauser:
ipaadmin_password: MyPassword123
- name: pinky
- uid: 10001
- gid: 100
- phone: "+555123457"
- email: pinky@acme.com
- principalexpiration: "20220119235959"
- #passwordexpiration: "2022-01-19 23:59:59"
- first: pinky
- last: Acme
+ users:
+ - name: testuser01
+ first: test
+ last: user01
+ - name: testuser02
+ first: test
+ last: user02
+ - name: testuser03
+ first: test
+ last: user03
+ - name: testuser04
+ first: test
+ last: user04
register: result
failed_when: not result.changed
- - name: User group login present
+ - name: Ensure user group testgroup01 is present
ipagroup:
ipaadmin_password: MyPassword123
- name: login
+ name: testgroup01
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule allhosts is present
- ipahbacrule:
+ - name: Ensure user group testgroup02 is present
+ ipagroup:
ipaadmin_password: MyPassword123
- name: allhosts
- usercategory: all
+ name: testgroup02
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule allhosts is present again
- ipahbacrule:
+ - name: Ensure user group testgroup03 is present
+ ipagroup:
ipaadmin_password: MyPassword123
- name: allhosts
- usercategory: all
+ name: testgroup03
register: result
- failed_when: result.changed
+ failed_when: not result.changed
- - name: Ensure host "{{ groups.ipaserver[0] }}" is present in HBAC Rule allhosts
+ - name: Ensure user group testgroup04 is present
+ ipagroup:
+ ipaadmin_password: MyPassword123
+ name: testgroup04
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC Service testhbacsvc01 is present
+ ipahbacsvc:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvc01
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC Service testhbacsvc02 is present
+ ipahbacsvc:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvc02
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC Service testhbacsvc03 is present
+ ipahbacsvc:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvc03
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC Service testhbacsvc04 is present
+ ipahbacsvc:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvc04
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC Service Group testhbacsvcgroup01 is present
+ ipahbacsvcgroup:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvcgroup01
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC Service Group testhbacsvcgroup02 is present
+ ipahbacsvcgroup:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvcgroup02
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC Service Group testhbacsvcgroup03 is present
+ ipahbacsvcgroup:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvcgroup03
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC Service Group testhbacsvcgroup04 is present
+ ipahbacsvcgroup:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvcgroup04
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure test HBAC rule hbacrule01 is absent
ipahbacrule:
ipaadmin_password: MyPassword123
- name: allhosts
- host: "{{ groups.ipaserver[0] }}"
- action: member
+ name: hbacrule01
+ state: absent
+
+ # ENSURE HBACRULE
+
+ - name: Ensure HBAC rule hbacrule01 is present
+ ipahbacrule:
+ ipaadmin_password: MyPassword123
+ name: hbacrule01
register: result
failed_when: not result.changed
- - name: Ensure host "{{ groups.ipaserver[0] }}" is present in HBAC Rule allhosts again
+ - name: Ensure HBAC rule hbacrule01 is present again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: allhosts
- host: "{{ groups.ipaserver[0] }}"
- action: member
+ name: hbacrule01
register: result
failed_when: result.changed
- - name: Ensure HBAC Rule sshd-pinky is present
+ # CHANGE HBACRULE WITH ALL MEMBERS
+
+ - name: Ensure HBAC rule hbacrule01 is present with hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- hostcategory: all
+ name: hbacrule01
+ host:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
+ hostgroup: testhostgroup01,testhostgroup02
+ user: testuser01,testuser02
+ group: testgroup01,testgroup02
+ hbacsvc: testhbacsvc01,testhbacsvc02
+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule sshd-pinky is present again
+ - name: Ensure HBAC rule hbacrule01 is present with hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- hostcategory: all
+ name: hbacrule01
+ host:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
+ hostgroup: testhostgroup01,testhostgroup02
+ user: testuser01,testuser02
+ group: testgroup01,testgroup02
+ hbacsvc: testhbacsvc01,testhbacsvc02
+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
register: result
failed_when: result.changed
- - name: Ensure user pinky is present in HBAC Rule sshd-pinky
+ # REMOVE MEMBERS ONE BY ONE
+
+ - name: Ensure test HBAC rule hbacrule01 host members are absent
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- user: pinky
+ name: hbacrule01
+ host:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
+ state: absent
action: member
register: result
failed_when: not result.changed
- - name: Ensure user pinky is present in HBAC Rule sshd-pinky again
+ - name: Ensure test HBAC rule hbacrule01 host members are absent again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- user: pinky
+ name: hbacrule01
+ host:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
+ state: absent
action: member
register: result
failed_when: result.changed
- - name: Ensure HBAC service sshd is present in HBAC Rule sshd-pinky
+ - name: Ensure test HBAC rule hbacrule01 hostgroup members are absent
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- hbacsvc: sshd
+ name: hbacrule01
+ hostgroup: testhostgroup01,testhostgroup02
+ state: absent
action: member
register: result
failed_when: not result.changed
- - name: Ensure HBAC service sshd is present in HBAC Rule sshd-pinky again
+ - name: Ensure test HBAC rule hbacrule01 hostgroup members are absent again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- hbacsvc: sshd
+ name: hbacrule01
+ hostgroup: testhostgroup01,testhostgroup02
+ state: absent
action: member
register: result
failed_when: result.changed
- - name: Ensure HBAC Rule loginRule is present with HBAC service sshd
+ - name: Ensure test HBAC rule hbacrule01 user members are absent
ipahbacrule:
ipaadmin_password: MyPassword123
- name: loginRule
- group: login
+ name: hbacrule01
+ user: testuser01,testuser02
+ state: absent
+ action: member
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule loginRule is present with HBAC service sshd again
+ - name: Ensure test HBAC rule hbacrule01 user members are absent again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: loginRule
- group: login
+ name: hbacrule01
+ user: testuser01,testuser02
+ state: absent
+ action: member
register: result
failed_when: result.changed
- - name: Ensure user pinky is present in HBAC Rule loginRule
+ - name: Ensure test HBAC rule hbacrule01 user group members are absent
ipahbacrule:
ipaadmin_password: MyPassword123
- name: loginRule
- user: pinky
+ name: hbacrule01
+ group: testgroup01,testgroup02
+ state: absent
action: member
register: result
failed_when: not result.changed
- - name: Ensure user pinky is present in HBAC Rule loginRule again
+ - name: Ensure test HBAC rule hbacrule01 user group members are absent again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: loginRule
- user: pinky
+ name: hbacrule01
+ group: testgroup01,testgroup02
+ state: absent
action: member
register: result
failed_when: result.changed
- - name: Ensure user pinky is absent in HBAC Rule loginRule
+ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are absent
ipahbacrule:
ipaadmin_password: MyPassword123
- name: loginRule
- user: pinky
- action: member
+ name: hbacrule01
+ hbacsvc: testhbacsvc01,testhbacsvc02
state: absent
+ action: member
register: result
failed_when: not result.changed
- - name: Ensure user pinky is absent in HBAC Rule loginRule again
+ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are absent again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: loginRule
- user: pinky
- action: member
+ name: hbacrule01
+ hbacsvc: testhbacsvc01,testhbacsvc02
state: absent
+ action: member
register: result
failed_when: result.changed
- - name: Ensure HBAC Rule loginRule is absent
+ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are absent
ipahbacrule:
ipaadmin_password: MyPassword123
- name: loginRule
+ name: hbacrule01
+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
state: absent
+ action: member
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule loginRule is absent again
+ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are absent again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: loginRule
+ name: hbacrule01
+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
state: absent
+ action: member
register: result
failed_when: result.changed
- - name: Ensure HBAC service sshd is absent in HBAC Rule sshd-pinky
+ # ADD MEMBERS BACK
+
+ - name: Ensure test HBAC rule hbacrule01 host members are present
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- hbacsvc: sshd
+ name: hbacrule01
+ host:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
action: member
- state: absent
register: result
failed_when: not result.changed
- - name: Ensure HBAC service sshd is absent in HBAC Rule sshd-pinky again
+ - name: Ensure test HBAC rule hbacrule01 host members are present again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- hbacsvc: sshd
+ name: hbacrule01
+ host:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
action: member
- state: absent
register: result
failed_when: result.changed
- - name: Ensure user pinky is absent in HBAC Rule sshd-pinky
+ - name: Ensure test HBAC rule hbacrule01 hostgroup members are present
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- user: pinky
+ name: hbacrule01
+ hostgroup: testhostgroup01,testhostgroup02
action: member
- state: absent
register: result
failed_when: not result.changed
- - name: Ensure user pinky is absent in HBAC Rule sshd-pinky again
+ - name: Ensure test HBAC rule hbacrule01 hostgroup members are present again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- user: pinky
+ name: hbacrule01
+ hostgroup: testhostgroup01,testhostgroup02
action: member
- state: absent
register: result
failed_when: result.changed
- - name: Ensure HBAC Rule sshd-pinky is disabled
+ - name: Ensure test HBAC rule hbacrule01 user members are present
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- state: disabled
+ name: hbacrule01
+ user: testuser01,testuser02
+ action: member
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule sshd-pinky is disabled again
+ - name: Ensure test HBAC rule hbacrule01 user members are present again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- state: disabled
+ name: hbacrule01
+ user: testuser01,testuser02
+ action: member
register: result
failed_when: result.changed
- - name: Ensure HBAC Rule sshd-pinky is enabled
+ - name: Ensure test HBAC rule hbacrule01 user group members are present
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- state: enabled
+ name: hbacrule01
+ group: testgroup01,testgroup02
+ action: member
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule sshd-pinky is enabled again
+ - name: Ensure test HBAC rule hbacrule01 user group members are present again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- state: enabled
+ name: hbacrule01
+ group: testgroup01,testgroup02
+ action: member
register: result
failed_when: result.changed
- - name: Ensure HBAC Rule sshd-pinky is absent
+ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are present
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- state: absent
+ name: hbacrule01
+ hbacsvc: testhbacsvc01,testhbacsvc02
+ action: member
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule sshd-pinky is absent again
+ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are present again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: sshd-pinky
- state: absent
+ name: hbacrule01
+ hbacsvc: testhbacsvc01,testhbacsvc02
+ action: member
register: result
failed_when: result.changed
- - name: Ensure host "{{ groups.ipaserver[0] }}" is absent in HBAC Rule allhosts
+ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are present
ipahbacrule:
ipaadmin_password: MyPassword123
- name: allhosts
- host: "{{ groups.ipaserver[0] }}"
+ name: hbacrule01
+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
action: member
- state: absent
register: result
failed_when: not result.changed
- - name: Ensure host "{{ groups.ipaserver[0] }}" is absent in HBAC Rule allhosts again
+ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are present again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: allhosts
- host: "{{ groups.ipaserver[0] }}"
+ name: hbacrule01
+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
action: member
+ register: result
+ failed_when: result.changed
+
+ # CHANGE TO DIFFERENT MEMBERS
+
+ - name: Ensure HBAC rule hbacrule01 is present with different hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups
+ ipahbacrule:
+ ipaadmin_password: MyPassword123
+ name: hbacrule01
+ host:
+ - "{{ 'testhost03.' + ipaserver_domain }}"
+ - "{{ 'testhost04.' + ipaserver_domain }}"
+ hostgroup: testhostgroup03,testhostgroup04
+ user: testuser03,testuser04
+ group: testgroup03,testgroup04
+ hbacsvc: testhbacsvc03,testhbacsvc04
+ hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure HBAC rule hbacrule01 is present with different hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups again
+ ipahbacrule:
+ ipaadmin_password: MyPassword123
+ name: hbacrule01
+ host:
+ - "{{ 'testhost03.' + ipaserver_domain }}"
+ - "{{ 'testhost04.' + ipaserver_domain }}"
+ hostgroup: testhostgroup03,testhostgroup04
+ user: testuser03,testuser04
+ group: testgroup03,testgroup04
+ hbacsvc: testhbacsvc03,testhbacsvc04
+ hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
+ register: result
+ failed_when: result.changed
+
+ # ENSURE OLD TEST MEMBERS ARE ABSENT
+
+ - name: Ensure HBAC rule hbacrule01 members (same) are present
+ ipahbacrule:
+ ipaadmin_password: MyPassword123
+ name: hbacrule01
+ host:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
+ hostgroup: testhostgroup01,testhostgroup02
+ user: testuser01,testuser02
+ group: testgroup01,testgroup02
+ hbacsvc: testhbacsvc01,testhbacsvc02
+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
state: absent
+ action: member
register: result
failed_when: result.changed
- - name: Ensure HBAC Rule allhosts is absent
+ # ENSURE NEW TEST MEMBERS ARE ABSENT
+
+ - name: Ensure HBAC rule hbacrule01 members are absent
ipahbacrule:
ipaadmin_password: MyPassword123
- name: allhosts
+ name: hbacrule01
+ host:
+ - "{{ 'testhost03.' + ipaserver_domain }}"
+ - "{{ 'testhost04.' + ipaserver_domain }}"
+ hostgroup: testhostgroup03,testhostgroup04
+ user: testuser03,testuser04
+ group: testgroup03,testgroup04
+ hbacsvc: testhbacsvc03,testhbacsvc04
+ hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
state: absent
+ action: member
register: result
failed_when: not result.changed
- - name: Ensure HBAC Rule allhosts is absent again
+ - name: Ensure HBAC rule hbacrule01 members are absent again
ipahbacrule:
ipaadmin_password: MyPassword123
- name: allhosts
+ name: hbacrule01
+ host:
+ - "{{ 'testhost03.' + ipaserver_domain }}"
+ - "{{ 'testhost04.' + ipaserver_domain }}"
+ hostgroup: testhostgroup03,testhostgroup04
+ user: testuser03,testuser04
+ group: testgroup03,testgroup04
+ hbacsvc: testhbacsvc03,testhbacsvc04
+ hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
state: absent
+ action: member
register: result
failed_when: result.changed
- - name: User pinky absent
+ # CLEANUP TEST ITEMS
+
+ - name: Ensure test HBAC rule hbacrule01 is absent
+ ipahbacrule:
+ ipaadmin_password: MyPassword123
+ name: hbacrule01
+ state: absent
+
+ - name: Ensure test hosts are absent
+ ipahostgroup:
+ ipaadmin_password: MyPassword123
+ name:
+ - "{{ 'testhost01.' + ipaserver_domain }}"
+ - "{{ 'testhost02.' + ipaserver_domain }}"
+ - "{{ 'testhost03.' + ipaserver_domain }}"
+ - "{{ 'testhost04.' + ipaserver_domain }}"
+ state: absent
+
+ - name: Ensure test hostgroups are absent
+ ipahostgroup:
+ ipaadmin_password: MyPassword123
+ name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04
+ state: absent
+
+ - name: Ensure test users are absent
ipauser:
ipaadmin_password: MyPassword123
- name: pinky
+ name: testuser01,testuser02,testuser03,testuser04
state: absent
- - name: User group login absent
+ - name: Ensure test user groups are absent
ipagroup:
ipaadmin_password: MyPassword123
- name: login
+ name: testgroup01,testgroup02,testgroup03,testgroup04
+ state: absent
+
+ - name: Ensure test HBAC Services are absent
+ ipahbacsvc:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04
+ state: absent
+
+ - name: Ensure test HBAC Service Groups are absent
+ ipahbacsvcgroup:
+ ipaadmin_password: MyPassword123
+ name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04
state: absent

View File

@ -0,0 +1,106 @@
From 22d8784da29dcfede0744ef6b691b4506eae5deb Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Thu, 20 Feb 2020 12:58:11 +0100
Subject: [PATCH] ipahost: Do not fail on missing DNS or zone when no IP
address given
If no IP address is given and either DNS is not configured or if the zone is
not found then ipahost may not fail in dnsrecord_find.
The error happened for example by ensuring the absence of a host that is not
part of the domain or for a host that has been added with force and is using
a domain that is not served by the DNS server in the domain. It also
happened if there was no DNS server in the domain at all.
A new test case has been added to test_host_ipaddresses.yml
The fix requires ipalib_errors provided by ansible_freeipa_module.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1804838
---
plugins/modules/ipahost.py | 17 +++++++++++++++--
tests/host/test_host_ipaddresses.yml | 9 +++++++++
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py
index 558560e..062f768 100644
--- a/plugins/modules/ipahost.py
+++ b/plugins/modules/ipahost.py
@@ -409,7 +409,7 @@
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa, \
module_params_get, gen_add_del_lists, encode_certificate, api_get_realm, \
- is_ipv4_addr, is_ipv6_addr
+ is_ipv4_addr, is_ipv6_addr, ipalib_errors
import six
@@ -871,7 +871,20 @@ def main():
# Make sure host exists
res_find = find_host(ansible_module, name)
- res_find_dnsrecord = find_dnsrecord(ansible_module, name)
+ try:
+ res_find_dnsrecord = find_dnsrecord(ansible_module, name)
+ except ipalib_errors.NotFound as e:
+ msg = str(e)
+ if ip_address is None and \
+ ("DNS is not configured" in msg or \
+ "DNS zone not found" in msg):
+ # IP address(es) not given and no DNS support in IPA
+ # -> Ignore failure
+ # IP address(es) not given and DNS zone is not found
+ # -> Ignore failure
+ res_find_dnsrecord = None
+ else:
+ ansible_module.fail_json(msg="%s: %s" % (host, msg))
# Create command
if state == "present":
diff --git a/tests/host/test_host_ipaddresses.yml b/tests/host/test_host_ipaddresses.yml
index 0a97dd5..136a610 100644
--- a/tests/host/test_host_ipaddresses.yml
+++ b/tests/host/test_host_ipaddresses.yml
@@ -301,6 +301,15 @@
register: result
failed_when: result.changed
+ - name: Absent host01.ihavenodns.info test
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: host01.ihavenodns.info
+ state: absent
+ register: result
+ failed_when: result.changed
+
- name: Host absent
ipahost:
ipaadmin_password: MyPassword123
From 4d94cb09a9fb09dd2576223b9be7f77d515202fb Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Thu, 20 Feb 2020 12:54:32 +0100
Subject: [PATCH] ansible_freeipa_module: Import ipalib.errors as ipalib_errors
For beeing able to catch ipalib.errors.NotFound errors in ipahost it is
needed to import ipalib.errors. ipalib.errors is now imported as
ipalib_errors to not have name conflicts with the errors list used in some
of the modules.
Related: https://bugzilla.redhat.com/show_bug.cgi?id=1804838
---
plugins/module_utils/ansible_freeipa_module.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
index 6acdbef..5066de3 100644
--- a/plugins/module_utils/ansible_freeipa_module.py
+++ b/plugins/module_utils/ansible_freeipa_module.py
@@ -28,6 +28,7 @@
import gssapi
from datetime import datetime
from ipalib import api
+from ipalib import errors as ipalib_errors
from ipalib.config import Env
from ipalib.constants import DEFAULT_CONFIG, LDAP_GENERALIZED_TIME_FORMAT
try:

View File

@ -0,0 +1,51 @@
From 24515e40ad289552d45bddd33c7a0dda93117a7f Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Wed, 18 Dec 2019 12:28:03 +0100
Subject: [PATCH] ipahost: Enhanced failure msg for member params used without
member action
The failure message if member parameters like certificate, managedby_host,
principal, allow_create_keytab_* and allow_retrieve_keytab_* are used
without member action for state absent has been enhanced to propose the
member action.
---
plugins/modules/ipahost.py | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py
index ec5e196..8ee9532 100644
--- a/plugins/modules/ipahost.py
+++ b/plugins/modules/ipahost.py
@@ -511,19 +511,25 @@ def check_parameters(
"userclass", "auth_ind", "requires_pre_auth",
"ok_as_delegate", "ok_to_auth_as_delegate", "force",
"reverse", "ip_address", "update_password"]
+ for x in invalid:
+ if vars()[x] is not None:
+ module.fail_json(
+ msg="Argument '%s' can not be used with state '%s'" %
+ (x, state))
if action == "host":
- invalid.extend([
+ invalid = [
"certificate", "managedby_host", "principal",
"allow_create_keytab_user", "allow_create_keytab_group",
"allow_create_keytab_host", "allow_create_keytab_hostgroup",
"allow_retrieve_keytab_user", "allow_retrieve_keytab_group",
"allow_retrieve_keytab_host",
- "allow_retrieve_keytab_hostgroup"])
- for x in invalid:
- if vars()[x] is not None:
- module.fail_json(
- msg="Argument '%s' can not be used with state '%s'" %
- (x, state))
+ "allow_retrieve_keytab_hostgroup"
+ ]
+ for x in invalid:
+ if vars()[x] is not None:
+ module.fail_json(
+ msg="Argument '%s' can only be used with action "
+ "'member' for state '%s'" % (x, state))
def main():

View File

@ -0,0 +1,57 @@
From 0816b0773b1535780c7c3e5f05bda39434ab6bac Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Fri, 14 Feb 2020 13:21:54 +0100
Subject: [PATCH] ipahost: Fail on action member for new hosts, fix
dnsrecord_add reverse flag
The check to make sure that member can not be used on non existing hosts
has bee missing. Also the reverse flag for the dnsrecord_add call was None
if the varaible was not set.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1803026
---
plugins/modules/ipahost.py | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py
index a5fd482..558560e 100644
--- a/plugins/modules/ipahost.py
+++ b/plugins/modules/ipahost.py
@@ -1005,6 +1005,11 @@ def main():
dnsrecord_args.get("aaaarecord"),
_dnsrec.get("aaaarecord"))
+ else:
+ if res_find is None:
+ ansible_module.fail_json(
+ msg="No host '%s'" % name)
+
if action != "host" or (action == "host" and res_find is None):
certificate_add = certificate or []
certificate_del = []
@@ -1178,15 +1183,17 @@ def main():
domain_name = name[name.find(".")+1:]
host_name = name[:name.find(".")]
+ _args = {"idnsname": host_name}
+ if reverse is not None:
+ _args["a_extra_create_reverse"] = reverse
+ _args["aaaa_extra_create_reverse"] = reverse
+ if len(dnsrecord_a_add) > 0:
+ _args["arecord"] = dnsrecord_a_add
+ if len(dnsrecord_aaaa_add) > 0:
+ _args["aaaarecord"] = dnsrecord_aaaa_add
+
commands.append([domain_name,
- "dnsrecord_add",
- {
- "idnsname": host_name,
- "arecord": dnsrecord_a_add,
- "a_extra_create_reverse": reverse,
- "aaaarecord": dnsrecord_aaaa_add,
- "aaaa_extra_create_reverse": reverse
- }])
+ "dnsrecord_add", _args])
if len(dnsrecord_a_del) > 0 or len(dnsrecord_aaaa_del) > 0:
domain_name = name[name.find(".")+1:]

View File

@ -0,0 +1,78 @@
From b6100f0c19e2caf73ab70bbc572d3e47e6066b48 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Tue, 17 Dec 2019 14:04:43 +0100
Subject: [PATCH] ipahost: Fix choices of auth_ind parameter, allow to reset
parameter
The choices for the auth_ind parameter have been wrong. The choices are now
['radius', 'otp', 'pkinit', 'hardened', '']. The empty string has been added
to be able to rest auth_ind for the host entry.
---
README-host.md | 2 +-
plugins/modules/ipahost.py | 15 ++++++++++++---
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/README-host.md b/README-host.md
index edec8d9..be5ad79 100644
--- a/README-host.md
+++ b/README-host.md
@@ -280,7 +280,7 @@ Variable | Description | Required
`mac_address` \| `macaddress` | List of hardware MAC addresses. | no
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys | no
`userclass` \| `class` | Host category (semantics placed on this attribute are for local interpretation) | no
-`auth_ind` \| `krbprincipalauthind` | Defines a whitelist for Authentication Indicators. Use 'otp' to allow OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA authentications. Other values may be used for custom configurations. choices: ["radius", "otp", "pkinit", "hardened"] | no
+`auth_ind` \| `krbprincipalauthind` | Defines a whitelist for Authentication Indicators. Use 'otp' to allow OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA authentications. Use empty string to reset auth_ind to the initial value. Other values may be used for custom configurations. choices: ["radius", "otp", "pkinit", "hardened", ""] | no
`requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service (bool) | no
`ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service (bool) | no
`ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client (bool) | no
diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py
index ec5e196..b130395 100644
--- a/plugins/modules/ipahost.py
+++ b/plugins/modules/ipahost.py
@@ -147,9 +147,10 @@
Defines a whitelist for Authentication Indicators. Use 'otp' to allow
OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA
authentications. Other values may be used for custom configurations.
+ Use empty string to reset auth_ind to the initial value.
type: list
aliases: ["krbprincipalauthind"]
- choices: ["radius", "otp", "pkinit", "hardened"]
+ choices: ["radius", "otp", "pkinit", "hardened", ""]
required: false
requires_pre_auth:
description: Pre-authentication is required for the service
@@ -277,9 +278,10 @@
Defines a whitelist for Authentication Indicators. Use 'otp' to allow
OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA
authentications. Other values may be used for custom configurations.
+ Use empty string to reset auth_ind to the initial value.
type: list
aliases: ["krbprincipalauthind"]
- choices: ["radius", "otp", "pkinit", "hardened"]
+ choices: ["radius", "otp", "pkinit", "hardened", ""]
required: false
requires_pre_auth:
description: Pre-authentication is required for the service
@@ -590,7 +592,7 @@ def main():
default=None),
auth_ind=dict(type='list', aliases=["krbprincipalauthind"],
default=None,
- choices=['password', 'radius', 'otp']),
+ choices=['radius', 'otp', 'pkinit', 'hardened', '']),
requires_pre_auth=dict(type="bool", aliases=["ipakrbrequirespreauth"],
default=None),
ok_as_delegate=dict(type="bool", aliases=["ipakrbokasdelegate"],
@@ -835,6 +837,13 @@ def main():
if x in args:
del args[x]
+ # Ignore auth_ind if it is empty (for resetting)
+ # and not set in for the host
+ if "krbprincipalauthind" not in res_find and \
+ "krbprincipalauthind" in args and \
+ args["krbprincipalauthind"] == ['']:
+ del args["krbprincipalauthind"]
+
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify

View File

@ -0,0 +1,179 @@
From 4dd1d25eacd1481be0a881a017144ff4d3396ccd Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Thu, 6 Feb 2020 15:38:00 +0100
Subject: [PATCH] ipapwpolicy: Use global_policy if name is not set
If the name is not set, the policy global_policy is now used. It was needed
before to explicitly name the global_policy. Also a check has been added
to fail early if global_policy is used with state absent.
The README for pwpolicy has been extended with an example for global_policy
and also the description of the name variable.
The test has also been extended to check a change of maxlife for
global_policy and that global_policy can not be used with state: absent
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1797532
---
README-pwpolicy.md | 19 +++++++++++--
plugins/modules/ipapwpolicy.py | 9 ++++--
tests/pwpolicy/test_pwpolicy.yml | 49 ++++++++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 4 deletions(-)
diff --git a/README-pwpolicy.md b/README-pwpolicy.md
index 16306b7..847b32d 100644
--- a/README-pwpolicy.md
+++ b/README-pwpolicy.md
@@ -56,7 +56,7 @@ Example playbook to ensure presence of pwpolicies for exisiting group ops:
maxfail: 3
```
-Example playbook to ensure absence of pwpolicies for group ops
+Example playbook to ensure absence of pwpolicies for group ops:
```yaml
---
@@ -72,6 +72,21 @@ Example playbook to ensure absence of pwpolicies for group ops
state: absent
```
+Example playbook to ensure maxlife is set to 49 in global policy:
+
+```yaml
+---
+- name: Playbook to handle pwpolicies
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ # Ensure absence of pwpolicies for group ops
+ - ipapwpolicy:
+ ipaadmin_password: MyPassword123
+ maxlife: 49
+```
+
Variables
=========
@@ -83,7 +98,7 @@ Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
-`name` \| `cn` | The list of pwpolicy name strings. | no
+`name` \| `cn` | The list of pwpolicy name strings. If name is not given, `global_policy` will be used automatically. | no
`maxlife` \| `krbmaxpwdlife` | Maximum password lifetime in days. (int) | no
`minlife` \| `krbminpwdlife` | Minimum password lifetime in hours. (int) | no
`history` \| `krbpwdhistorylength` | Password history size. (int) | no
diff --git a/plugins/modules/ipapwpolicy.py b/plugins/modules/ipapwpolicy.py
index 9437b59..f168703 100644
--- a/plugins/modules/ipapwpolicy.py
+++ b/plugins/modules/ipapwpolicy.py
@@ -167,7 +167,7 @@ def main():
ipaadmin_password=dict(type="str", required=False, no_log=True),
name=dict(type="list", aliases=["cn"], default=None,
- required=True),
+ required=False),
# present
maxlife=dict(type="int", aliases=["krbmaxpwdlife"], default=None),
@@ -218,6 +218,9 @@ def main():
# Check parameters
+ if names is None:
+ names = ["global_policy"]
+
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
@@ -225,8 +228,10 @@ def main():
if state == "absent":
if len(names) < 1:
+ ansible_module.fail_json(msg="No name given.")
+ if "global_policy" in names:
ansible_module.fail_json(
- msg="No name given.")
+ msg="'global_policy' can not be made absent.")
invalid = ["maxlife", "minlife", "history", "minclasses",
"minlength", "priority", "maxfail", "failinterval",
"lockouttime"]
diff --git a/tests/pwpolicy/test_pwpolicy.yml b/tests/pwpolicy/test_pwpolicy.yml
index 5c69345..f93f275 100644
--- a/tests/pwpolicy/test_pwpolicy.yml
+++ b/tests/pwpolicy/test_pwpolicy.yml
@@ -5,10 +5,30 @@
gather_facts: false
tasks:
+ - name: Ensure maxlife of 90 for global_policy
+ ipapwpolicy:
+ ipaadmin_password: SomeADMINpassword
+ maxlife: 90
+
+ - name: Ensure absence of group ops
+ ipagroup:
+ ipaadmin_password: SomeADMINpassword
+ name: ops
+ state: absent
+
+ - name: Ensure absence of pwpolicies for group ops
+ ipapwpolicy:
+ ipaadmin_password: SomeADMINpassword
+ name: ops
+ state: absent
+
- name: Ensure presence of group ops
ipagroup:
ipaadmin_password: SomeADMINpassword
name: ops
+ state: present
+ register: result
+ failed_when: not result.changed
- name: Ensure presence of pwpolicies for group ops
ipapwpolicy:
@@ -42,6 +62,28 @@
register: result
failed_when: result.changed
+ - name: Ensure maxlife of 49 for global_policy
+ ipapwpolicy:
+ ipaadmin_password: SomeADMINpassword
+ maxlife: 49
+ register: result
+ failed_when: not result.changed
+
+ - name: Ensure maxlife of 49 for global_policy again
+ ipapwpolicy:
+ ipaadmin_password: SomeADMINpassword
+ maxlife: 49
+ register: result
+ failed_when: result.changed
+
+ - name: Ensure absence of pwpoliciy global_policy will fail
+ ipapwpolicy:
+ ipaadmin_password: SomeADMINpassword
+ state: absent
+ register: result
+ ignore_errors: True
+ failed_when: result is defined and result
+
- name: Ensure absence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
@@ -50,6 +92,13 @@
register: result
failed_when: not result.changed
+ - name: Ensure maxlife of 90 for global_policy
+ ipapwpolicy:
+ ipaadmin_password: MyPassword123
+ maxlife: 90
+ register: result
+ failed_when: not result.changed
+
- name: Ensure absence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword

View File

@ -0,0 +1,116 @@
From 36c1c837086c42049f09cf689a1ebd61627abae0 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Tue, 17 Dec 2019 15:30:45 +0100
Subject: [PATCH] ipauser: Allow reset of userauthtype, do not depend on
first,last for mod
It was not possible to reset the userauthtype. The empty string has been
added to userauthtype for this.
Also ipauser will only depend on given first and last name if the user
does not exist yet. For the update operation these parameters are not
needed anymore.
---
README-user.md | 2 +-
plugins/modules/ipauser.py | 38 ++++++++++++++++++++++++++------------
2 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/README-user.md b/README-user.md
index 56772a7..991121c 100644
--- a/README-user.md
+++ b/README-user.md
@@ -408,7 +408,7 @@ Variable | Description | Required
`manager` | List of manager user names. | no
`carlicense` | List of car licenses. | no
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys. | no
-`userauthtype` | List of supported user authentication types. Choices: `password`, `radius` and `otp` | no
+`userauthtype` | List of supported user authentication types. Choices: `password`, `radius`, `otp` and ``. Use empty string to reset userauthtype to the initial value. | no
`userclass` | User category. (semantics placed on this attribute are for local interpretation). | no
`radius` | RADIUS proxy configuration | no
`radiususer` | RADIUS proxy username | no
diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py
index ac45295..36e8bae 100644
--- a/plugins/modules/ipauser.py
+++ b/plugins/modules/ipauser.py
@@ -153,9 +153,12 @@
required: false
aliases: ["ipasshpubkey"]
userauthtype:
- description: List of supported user authentication types
- choices=['password', 'radius', 'otp']
+ description:
+ List of supported user authentication types
+ Use empty string to reset userauthtype to the initial value.
+ choices=['password', 'radius', 'otp', '']
required: false
+ aliases: ["ipauserauthtype"]
userclass:
description:
- User category
@@ -310,9 +313,12 @@
required: false
aliases: ["ipasshpubkey"]
userauthtype:
- description: List of supported user authentication types
- choices=['password', 'radius', 'otp']
+ description:
+ List of supported user authentication types
+ Use empty string to reset userauthtype to the initial value.
+ choices=['password', 'radius', 'otp', '']
required: false
+ aliases: ["ipauserauthtype"]
userclass:
description:
- User category
@@ -701,7 +707,7 @@ def main():
default=None),
userauthtype=dict(type='list', aliases=["ipauserauthtype"],
default=None,
- choices=['password', 'radius', 'otp']),
+ choices=['password', 'radius', 'otp', '']),
userclass=dict(type="list", aliases=["class"],
default=None),
radius=dict(type="str", aliases=["ipatokenradiusconfiglink"],
@@ -845,13 +851,6 @@ def main():
if names is not None and len(names) != 1:
ansible_module.fail_json(
msg="Only one user can be added at a time using name.")
- if action != "member":
- # Only check first and last here if names is set
- if names is not None:
- if first is None:
- ansible_module.fail_json(msg="First name is needed")
- if last is None:
- ansible_module.fail_json(msg="Last name is needed")
check_parameters(
ansible_module, state, action,
@@ -1011,6 +1010,13 @@ def main():
if "noprivate" in args:
del args["noprivate"]
+ # Ignore userauthtype if it is empty (for resetting)
+ # and not set in for the user
+ if "ipauserauthtype" not in res_find and \
+ "ipauserauthtype" in args and \
+ args["ipauserauthtype"] == ['']:
+ del args["ipauserauthtype"]
+
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
@@ -1019,6 +1025,14 @@ def main():
commands.append([name, "user_mod", args])
else:
+ # Make sure we have a first and last name
+ if first is None:
+ ansible_module.fail_json(
+ msg="First name is needed")
+ if last is None:
+ ansible_module.fail_json(
+ msg="Last name is needed")
+
commands.append([name, "user_add", args])
# Handle members: principal, manager, certificate and

View File

@ -0,0 +1,915 @@
From 167c76311da72c2bfabf4b2bce9e128c11d519d0 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Wed, 12 Feb 2020 16:54:13 +0100
Subject: [PATCH] ipahost: Add support for several IP addresses and also to
change them
ipahost was so far ignoring IP addresses when the host already existed.
This happened because host_mod is not providing functionality to do this.
Now ipaddress is a list and it is possible to ensure a host with several
IP addresses (these can be IPv4 and IPv6). Also it is possible to ensure
presence and absence of IP addresses for an exising host using action
member.
There are no IP address conclict checks as this would lead into issues with
updating an existing host that already is using a duplicate IP address for
example for round-robin (RR). Also this might lead into issues with ensuring
a new host with several IP addresses in this case. Also to ensure a list of
hosts with changing the IP address of one host to another in the list would
result in issues here.
New example playbooks have been added:
playbooks/host/host-present-with-several-ip-addresses.yml
playbooks/host/host-member-ipaddresses-absent.yml
playbooks/host/host-member-ipaddresses-present.yml
A new test has been added for verification:
tests/host/test_host_ipaddresses.yml
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1783976
https://bugzilla.redhat.com/show_bug.cgi?id=1783979
---
README-host.md | 79 ++++-
.../host/host-member-ipaddresses-absent.yml | 17 +
.../host/host-member-ipaddresses-present.yml | 16 +
...host-present-with-several-ip-addresses.yml | 24 ++
.../module_utils/ansible_freeipa_module.py | 23 ++
plugins/modules/ipahost.py | 179 +++++++---
tests/host/test_host_ipaddresses.yml | 312 ++++++++++++++++++
7 files changed, 600 insertions(+), 50 deletions(-)
create mode 100644 playbooks/host/host-member-ipaddresses-absent.yml
create mode 100644 playbooks/host/host-member-ipaddresses-present.yml
create mode 100644 playbooks/host/host-present-with-several-ip-addresses.yml
create mode 100644 tests/host/test_host_ipaddresses.yml
diff --git a/README-host.md b/README-host.md
index be5ad79..ecc59a9 100644
--- a/README-host.md
+++ b/README-host.md
@@ -65,6 +65,79 @@ Example playbook to ensure host presence:
- "52:54:00:BD:97:1E"
state: present
```
+Compared to `ipa host-add` command no IP address conflict check is done as the ipahost module supports to have several IPv4 and IPv6 addresses for a host.
+
+
+Example playbook to ensure host presence with several IP addresses:
+
+```yaml
+---
+- name: Playbook to handle hosts
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ # Ensure host is present
+ - ipahost:
+ ipaadmin_password: MyPassword123
+ name: host01.example.com
+ description: Example host
+ ip_address:
+ - 192.168.0.123
+ - 192.168.0.124
+ - fe80::20c:29ff:fe02:a1b3
+ - fe80::20c:29ff:fe02:a1b4
+ locality: Lab
+ ns_host_location: Lab
+ ns_os_version: CentOS 7
+ ns_hardware_platform: Lenovo T61
+ mac_address:
+ - "08:00:27:E3:B1:2D"
+ - "52:54:00:BD:97:1E"
+ state: present
+```
+
+
+Example playbook to ensure IP addresses are present for a host:
+
+```yaml
+---
+- name: Playbook to handle hosts
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ # Ensure host is present
+ - ipahost:
+ ipaadmin_password: MyPassword123
+ name: host01.example.com
+ ip_address:
+ - 192.168.0.124
+ - fe80::20c:29ff:fe02:a1b4
+ action: member
+ state: present
+```
+
+
+Example playbook to ensure IP addresses are absent for a host:
+
+```yaml
+---
+- name: Playbook to handle hosts
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ # Ensure host is present
+ - ipahost:
+ ipaadmin_password: MyPassword123
+ name: host01.example.com
+ ip_address:
+ - 192.168.0.124
+ - fe80::20c:29ff:fe02:a1b4
+ action: member
+ state: absent
+```
Example playbook to ensure host presence without DNS:
@@ -215,7 +288,7 @@ Example playbook to disable a host:
update_dns: yes
state: disabled
```
-`update_dns` controls if the DNS entries will be updated.
+`update_dns` controls if the DNS entries will be updated in this case. For `state` present it is controlling the update of the DNS SSHFP records, but not the the other DNS records.
Example playbook to ensure a host is absent:
@@ -286,8 +359,8 @@ Variable | Description | Required
`ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client (bool) | no
`force` | Force host name even if not in DNS. | no
`reverse` | Reverse DNS detection. | no
-`ip_address` \| `ipaddress` | The host IP address. | no
-`update_dns` | Update DNS entries. | no
+`ip_address` \| `ipaddress` | The host IP address list. It can contain IPv4 and IPv6 addresses. No conflict check for IP addresses is done. | no
+`update_dns` | For existing hosts: DNS SSHFP records are updated with `state` present and all DNS entries for a host removed with `state` absent. | no
Return Values
diff --git a/playbooks/host/host-member-ipaddresses-absent.yml b/playbooks/host/host-member-ipaddresses-absent.yml
new file mode 100644
index 0000000..2466dbd
--- /dev/null
+++ b/playbooks/host/host-member-ipaddresses-absent.yml
@@ -0,0 +1,17 @@
+---
+- name: Host member IP addresses absent
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ - name: Ensure host01.example.com IP addresses absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: host01.example.com
+ ip_address:
+ - 192.168.0.123
+ - fe80::20c:29ff:fe02:a1b3
+ - 192.168.0.124
+ - fe80::20c:29ff:fe02:a1b4
+ action: member
+ state: absent
diff --git a/playbooks/host/host-member-ipaddresses-present.yml b/playbooks/host/host-member-ipaddresses-present.yml
new file mode 100644
index 0000000..f473993
--- /dev/null
+++ b/playbooks/host/host-member-ipaddresses-present.yml
@@ -0,0 +1,16 @@
+---
+- name: Host member IP addresses present
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ - name: Ensure host01.example.com IP addresses present
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: host01.example.com
+ ip_address:
+ - 192.168.0.123
+ - fe80::20c:29ff:fe02:a1b3
+ - 192.168.0.124
+ - fe80::20c:29ff:fe02:a1b4
+ action: member
diff --git a/playbooks/host/host-present-with-several-ip-addresses.yml b/playbooks/host/host-present-with-several-ip-addresses.yml
new file mode 100644
index 0000000..4956562
--- /dev/null
+++ b/playbooks/host/host-present-with-several-ip-addresses.yml
@@ -0,0 +1,24 @@
+---
+- name: Host present with several IP addresses
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ - name: Ensure host is present
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: host01.example.com
+ description: Example host
+ ip_address:
+ - 192.168.0.123
+ - fe80::20c:29ff:fe02:a1b3
+ - 192.168.0.124
+ - fe80::20c:29ff:fe02:a1b4
+ locality: Lab
+ ns_host_location: Lab
+ ns_os_version: CentOS 7
+ ns_hardware_platform: Lenovo T61
+ mac_address:
+ - "08:00:27:E3:B1:2D"
+ - "52:54:00:BD:97:1E"
+ state: present
diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
index 9e97b88..6acdbef 100644
--- a/plugins/module_utils/ansible_freeipa_module.py
+++ b/plugins/module_utils/ansible_freeipa_module.py
@@ -42,6 +42,7 @@
from ipalib.x509 import Encoding
except ImportError:
from cryptography.hazmat.primitives.serialization import Encoding
+import socket
import base64
import six
@@ -285,3 +286,25 @@ def encode_certificate(cert):
if not six.PY2:
encoded = encoded.decode('ascii')
return encoded
+
+
+def is_ipv4_addr(ipaddr):
+ """
+ Test if figen IP address is a valid IPv4 address
+ """
+ try:
+ socket.inet_pton(socket.AF_INET, ipaddr)
+ except socket.error:
+ return False
+ return True
+
+
+def is_ipv6_addr(ipaddr):
+ """
+ Test if figen IP address is a valid IPv6 address
+ """
+ try:
+ socket.inet_pton(socket.AF_INET6, ipaddr)
+ except socket.error:
+ return False
+ return True
diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py
index dba4181..a5fd482 100644
--- a/plugins/modules/ipahost.py
+++ b/plugins/modules/ipahost.py
@@ -176,11 +176,16 @@
default: true
required: false
ip_address:
- description: The host IP address
+ description:
+ The host IP address list (IPv4 and IPv6). No IP address conflict
+ check will be done.
aliases: ["ipaddress"]
required: false
update_dns:
- description: Update DNS entries
+ description:
+ Controls the update of the DNS SSHFP records for existing hosts and
+ the removal of all DNS entries if a host gets removed with state
+ absent.
required: false
description:
description: The host description
@@ -306,11 +311,16 @@
default: true
required: false
ip_address:
- description: The host IP address
+ description:
+ The host IP address list (IPv4 and IPv6). No IP address conflict
+ check will be done.
aliases: ["ipaddress"]
required: false
update_dns:
- description: Update DNS entries
+ description:
+ Controls the update of the DNS SSHFP records for existing hosts and
+ the removal of all DNS entries if a host gets removed with state
+ absent.
required: false
update_password:
description:
@@ -398,7 +408,8 @@
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa, \
- module_params_get, gen_add_del_lists, encode_certificate, api_get_realm
+ module_params_get, gen_add_del_lists, encode_certificate, api_get_realm, \
+ is_ipv4_addr, is_ipv6_addr
import six
@@ -428,6 +439,32 @@ def find_host(module, name):
return None
+def find_dnsrecord(module, name):
+ domain_name = name[name.find(".")+1:]
+ host_name = name[:name.find(".")]
+
+ _args = {
+ "all": True,
+ "idnsname": to_text(host_name),
+ }
+
+ _result = api_command(module, "dnsrecord_find", to_text(domain_name),
+ _args)
+
+ if len(_result["result"]) > 1:
+ module.fail_json(
+ msg="There is more than one host '%s'" % (name))
+ elif len(_result["result"]) == 1:
+ _res = _result["result"][0]
+ certs = _res.get("usercertificate")
+ if certs is not None:
+ _res["usercertificate"] = [encode_certificate(cert) for
+ cert in certs]
+ return _res
+ else:
+ return None
+
+
def show_host(module, name):
_result = api_command(module, "host_show", to_text(name), {})
return _result["result"]
@@ -470,16 +507,34 @@ def gen_args(description, locality, location, platform, os, password, random,
_args["ipakrboktoauthasdelegate"] = ok_to_auth_as_delegate
if force is not None:
_args["force"] = force
- if reverse is not None:
- _args["no_reverse"] = not reverse
if ip_address is not None:
- _args["ip_address"] = ip_address
+ # IP addresses are handed extra, therefore it is needed to set
+ # the force option here to make sure that host-add is able to
+ # add a host without IP address.
+ _args["force"] = True
if update_dns is not None:
_args["updatedns"] = update_dns
return _args
+def gen_dnsrecord_args(module, ip_address, reverse):
+ _args = {}
+ if reverse is not None:
+ _args["a_extra_create_reverse"] = reverse
+ _args["aaaa_extra_create_reverse"] = reverse
+ if ip_address is not None:
+ for ip in ip_address:
+ if is_ipv4_addr(ip):
+ _args.setdefault("arecord", []).append(ip)
+ elif is_ipv6_addr(ip):
+ _args.setdefault("aaaarecord", []).append(ip)
+ else:
+ module.fail_json(msg="'%s' is not a valid IP address." % ip)
+
+ return _args
+
+
def check_parameters(
module, state, action,
description, locality, location, platform, os, password, random,
@@ -499,8 +554,7 @@ def check_parameters(
"os", "password", "random", "mac_address", "sshpubkey",
"userclass", "auth_ind", "requires_pre_auth",
"ok_as_delegate", "ok_to_auth_as_delegate", "force",
- "reverse", "ip_address", "update_dns",
- "update_password"]
+ "reverse", "update_dns", "update_password"]
for x in invalid:
if vars()[x] is not None:
module.fail_json(
@@ -512,7 +566,7 @@ def check_parameters(
"password", "random", "mac_address", "sshpubkey",
"userclass", "auth_ind", "requires_pre_auth",
"ok_as_delegate", "ok_to_auth_as_delegate", "force",
- "reverse", "ip_address", "update_password"]
+ "reverse", "update_password"]
for x in invalid:
if vars()[x] is not None:
module.fail_json(
@@ -549,9 +603,6 @@ def main():
default=None, no_log=True),
random=dict(type="bool", aliases=["random_password"],
default=None),
-
-
-
certificate=dict(type="list", aliases=["usercertificate"],
default=None),
managedby_host=dict(type="list",
@@ -608,7 +659,7 @@ def main():
default=None),
force=dict(type='bool', default=None),
reverse=dict(type='bool', default=None),
- ip_address=dict(type="str", aliases=["ipaddress"],
+ ip_address=dict(type="list", aliases=["ipaddress"],
default=None),
update_dns=dict(type="bool", aliases=["updatedns"],
default=None),
@@ -820,6 +871,7 @@ def main():
# Make sure host exists
res_find = find_host(ansible_module, name)
+ res_find_dnsrecord = find_dnsrecord(ansible_module, name)
# Create command
if state == "present":
@@ -829,6 +881,8 @@ def main():
random, mac_address, sshpubkey, userclass, auth_ind,
requires_pre_auth, ok_as_delegate, ok_to_auth_as_delegate,
force, reverse, ip_address, update_dns)
+ dnsrecord_args = gen_dnsrecord_args(
+ ansible_module, ip_address, reverse)
if action == "host":
# Found the host
@@ -938,39 +992,20 @@ def main():
res_find.get(
"ipaallowedtoperform_read_keys_hostgroup"))
- else:
- certificate_add = certificate or []
- certificate_del = []
- managedby_host_add = managedby_host or []
- managedby_host_del = []
- principal_add = principal or []
- principal_del = []
- allow_create_keytab_user_add = \
- allow_create_keytab_user or []
- allow_create_keytab_user_del = []
- allow_create_keytab_group_add = \
- allow_create_keytab_group or []
- allow_create_keytab_group_del = []
- allow_create_keytab_host_add = \
- allow_create_keytab_host or []
- allow_create_keytab_host_del = []
- allow_create_keytab_hostgroup_add = \
- allow_create_keytab_hostgroup or []
- allow_create_keytab_hostgroup_del = []
- allow_retrieve_keytab_user_add = \
- allow_retrieve_keytab_user or []
- allow_retrieve_keytab_user_del = []
- allow_retrieve_keytab_group_add = \
- allow_retrieve_keytab_group or []
- allow_retrieve_keytab_group_del = []
- allow_retrieve_keytab_host_add = \
- allow_retrieve_keytab_host or []
- allow_retrieve_keytab_host_del = []
- allow_retrieve_keytab_hostgroup_add = \
- allow_retrieve_keytab_hostgroup or []
- allow_retrieve_keytab_hostgroup_del = []
+ # IP addresses are not really a member of hosts, but
+ # we will simply treat it as this to enable the
+ # addition and removal of IPv4 and IPv6 addresses in
+ # a simple way.
+ _dnsrec = res_find_dnsrecord or {}
+ dnsrecord_a_add, dnsrecord_a_del = gen_add_del_lists(
+ dnsrecord_args.get("arecord"),
+ _dnsrec.get("arecord"))
+ dnsrecord_aaaa_add, dnsrecord_aaaa_del = \
+ gen_add_del_lists(
+ dnsrecord_args.get("aaaarecord"),
+ _dnsrec.get("aaaarecord"))
- else:
+ if action != "host" or (action == "host" and res_find is None):
certificate_add = certificate or []
certificate_del = []
managedby_host_add = managedby_host or []
@@ -1001,6 +1036,10 @@ def main():
allow_retrieve_keytab_hostgroup_add = \
allow_retrieve_keytab_hostgroup or []
allow_retrieve_keytab_hostgroup_del = []
+ dnsrecord_a_add = dnsrecord_args.get("arecord") or []
+ dnsrecord_a_del = []
+ dnsrecord_aaaa_add = dnsrecord_args.get("aaaarecord") or []
+ dnsrecord_aaaa_del = []
# Remove canonical principal from principal_del
canonical_principal = "host/" + name + "@" + server_realm
@@ -1135,6 +1174,36 @@ def main():
"hostgroup": allow_retrieve_keytab_hostgroup_del,
}])
+ if len(dnsrecord_a_add) > 0 or len(dnsrecord_aaaa_add) > 0:
+ domain_name = name[name.find(".")+1:]
+ host_name = name[:name.find(".")]
+
+ commands.append([domain_name,
+ "dnsrecord_add",
+ {
+ "idnsname": host_name,
+ "arecord": dnsrecord_a_add,
+ "a_extra_create_reverse": reverse,
+ "aaaarecord": dnsrecord_aaaa_add,
+ "aaaa_extra_create_reverse": reverse
+ }])
+
+ if len(dnsrecord_a_del) > 0 or len(dnsrecord_aaaa_del) > 0:
+ domain_name = name[name.find(".")+1:]
+ host_name = name[:name.find(".")]
+
+ # There seems to be an issue with dnsrecord_del (not
+ # for dnsrecord_add) if aaaarecord is an empty list.
+ # Therefore this is done differently here:
+ _args = {"idnsname": host_name}
+ if len(dnsrecord_a_del) > 0:
+ _args["arecord"] = dnsrecord_a_del
+ if len(dnsrecord_aaaa_del) > 0:
+ _args["aaaarecord"] = dnsrecord_aaaa_del
+
+ commands.append([domain_name,
+ "dnsrecord_del", _args])
+
elif state == "absent":
if action == "host":
@@ -1215,6 +1284,17 @@ def main():
"hostgroup": allow_retrieve_keytab_hostgroup,
}])
+ dnsrecord_args = gen_dnsrecord_args(ansible_module,
+ ip_address, reverse)
+ if "arecord" in dnsrecord_args or \
+ "aaaarecord" in dnsrecord_args:
+ domain_name = name[name.find(".")+1:]
+ host_name = name[:name.find(".")]
+ dnsrecord_args["idnsname"] = host_name
+
+ commands.append([domain_name, "dnsrecord_del",
+ dnsrecord_args])
+
elif state == "disabled":
if res_find is not None:
commands.append([name, "host_disable", {}])
@@ -1259,6 +1339,11 @@ def main():
# Host is already disabled, ignore error
if "This entry is already disabled" in msg:
continue
+
+ # Ignore no modification error.
+ if "no modifications to be performed" in msg:
+ continue
+
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
msg))
diff --git a/tests/host/test_host_ipaddresses.yml b/tests/host/test_host_ipaddresses.yml
new file mode 100644
index 0000000..0a97dd5
--- /dev/null
+++ b/tests/host/test_host_ipaddresses.yml
@@ -0,0 +1,312 @@
+---
+- name: Test host IP addresses
+ hosts: ipaserver
+ become: true
+
+ tasks:
+ - name: Get Domain from server name
+ set_fact:
+ ipaserver_domain: "{{ groups.ipaserver[0].split('.')[1:] | join ('.') }}"
+ when: ipaserver_domain is not defined
+
+ - name: Set host1_fqdn .. host6_fqdn
+ set_fact:
+ host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
+ host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
+ host3_fqdn: "{{ 'host3.' + ipaserver_domain }}"
+
+ - name: Get IPv4 address prefix from server node
+ set_fact:
+ ipv4_prefix: "{{ ansible_default_ipv4.address.split('.')[:-1] |
+ join('.') }}"
+
+ - name: Host absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name:
+ - "{{ host1_fqdn }}"
+ - "{{ host2_fqdn }}"
+ - "{{ host3_fqdn }}"
+ update_dns: yes
+ state: absent
+
+ - name: Host "{{ host1_fqdn }}" present
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.201' }}"
+ - fe80::20c:29ff:fe02:a1b2
+ update_dns: yes
+ reverse: no
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" present again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.201' }}"
+ - fe80::20c:29ff:fe02:a1b2
+ update_dns: yes
+ reverse: no
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" present again with new IP address
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ update_dns: yes
+ reverse: no
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" present again with new IP address again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ update_dns: yes
+ reverse: no
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" member IPv4 address present
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address: "{{ ipv4_prefix + '.201' }}"
+ action: member
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" member IPv4 address present again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address: "{{ ipv4_prefix + '.201' }}"
+ action: member
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" member IPv4 address absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address: "{{ ipv4_prefix + '.201' }}"
+ action: member
+ state: absent
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" member IPv4 address absent again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address: "{{ ipv4_prefix + '.201' }}"
+ action: member
+ state: absent
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" member IPv6 address present
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address: fe80::20c:29ff:fe02:a1b2
+ action: member
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" member IPv6 address present again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address: fe80::20c:29ff:fe02:a1b2
+ action: member
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host1_fqdn }}" member IPv6 address absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address: fe80::20c:29ff:fe02:a1b2
+ action: member
+ state: absent
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" member IPv6 address absent again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address: fe80::20c:29ff:fe02:a1b2
+ action: member
+ state: absent
+ register: result
+
+ - name: Host "{{ host1_fqdn }}" member all ip-addresses absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ action: member
+ state: absent
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host1_fqdn }}" all member ip-addresses absent again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name: "{{ host1_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ action: member
+ state: absent
+ register: result
+ failed_when: result.changed
+
+ - name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" present with same IP addresses
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ host1_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ - name: "{{ host2_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ register: result
+ failed_when: not result.changed
+
+ - name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" present with same IP addresses again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ host1_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ - name: "{{ host2_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ register: result
+ failed_when: result.changed
+
+ - name: Hosts "{{ host3_fqdn }}" present with same IP addresses
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ host3_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ register: result
+ failed_when: not result.changed
+
+ - name: Hosts "{{ host3_fqdn }}" present with same IP addresses again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ host3_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host3_fqdn }}" present with differnt IP addresses
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ host3_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.111' }}"
+ - fe80::20c:29ff:fe02:a1b1
+ - "{{ ipv4_prefix + '.121' }}"
+ - fe80::20c:29ff:fe02:a1b2
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host3_fqdn }}" present with different IP addresses again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ host3_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.111' }}"
+ - fe80::20c:29ff:fe02:a1b1
+ - "{{ ipv4_prefix + '.121' }}"
+ - fe80::20c:29ff:fe02:a1b2
+ register: result
+ failed_when: result.changed
+
+ - name: Host "{{ host3_fqdn }}" present with old IP addresses
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ host3_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ register: result
+ failed_when: not result.changed
+
+ - name: Host "{{ host3_fqdn }}" present with old IP addresses again
+ ipahost:
+ ipaadmin_password: MyPassword123
+ hosts:
+ - name: "{{ host3_fqdn }}"
+ ip_address:
+ - "{{ ipv4_prefix + '.211' }}"
+ - fe80::20c:29ff:fe02:a1b3
+ - "{{ ipv4_prefix + '.221' }}"
+ - fe80::20c:29ff:fe02:a1b4
+ register: result
+ failed_when: result.changed
+
+ - name: Host absent
+ ipahost:
+ ipaadmin_password: MyPassword123
+ name:
+ - "{{ host1_fqdn }}"
+ - "{{ host2_fqdn }}"
+ - "{{ host3_fqdn }}"
+ update_dns: yes
+ state: absent
From 8f32cb04c1e161e1e3217f10413685a2cc9bf492 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Thu, 13 Feb 2020 14:10:38 +0100
Subject: [PATCH] tests/host/test_host: Fix use of wrong host in the host5 test
host1 was used instead of host5 in the repeated host5 test. This lead to an
error with the new IP address handling in ipahost. It was correctly
reporting a change for host1 which resulted in a failed test.
---
tests/host/test_host.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/host/test_host.yml b/tests/host/test_host.yml
index 1a555a1..f3ec11d 100644
--- a/tests/host/test_host.yml
+++ b/tests/host/test_host.yml
@@ -129,7 +129,7 @@
- name: Host "{{ host5_fqdn }}" present again
ipahost:
ipaadmin_password: MyPassword123
- name: "{{ host1_fqdn }}"
+ name: "{{ host5_fqdn }}"
ip_address: "{{ ipv4_prefix + '.205' }}"
update_dns: yes
reverse: no

View File

@ -5,22 +5,28 @@
Summary: Roles and playbooks to deploy FreeIPA servers, replicas and clients
Name: ansible-freeipa
Version: 0.1.6
Release: 4%{?dist}
Version: 0.1.8
Release: 3%{?dist}
URL: https://github.com/freeipa/ansible-freeipa
License: GPLv3+
Source: https://github.com/freeipa/ansible-freeipa/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
Patch1: ansible-freeipa-0.1.6-gen_module_docs-drop-key-dirserv_cert_files.patch
Patch2: ansible-freeipa-0.1.6-ipatopologysegment-command-suffix-e4497c18_rhbz#1733547.patch
Patch3: ansible-freeipa-0.1.6-ipatopologysegment-reinitialized-c212b435_rhbz#1733559.patch
Patch4: ansible-freeipa-0.1.6-ansible_ipa_client_Drop_import_of_configure_nsswitch_database_rhbz#1748905.patch
Patch1: ansible-freeipa-0.1.8-ipahost-Fix-choices-of-auth_ind-parameter-allow-to-reset-parameter_rhbz#1783992.patch
Patch2: ansible-freeipa-0.1.8-ipauser-Allow-reset-of-userauthtype-do-not-depend-on-first-last-for-mod_rhbz#1784474.patch
Patch3: ansible-freeipa-0.1.8-ipahost-Enhanced-failure-msg-for-member-params-used-without-member-action_rhbz#1783948.patch
Patch4: ansible-freeipa-0.1.8-Add-missing-attributes-to-ipasudorule_rhbz#1788168,1788035,1788024.patch
Patch5: ansible-freeipa-0.1.8-ipapwpolicy-Use-global_policy-if-name-is-not-set_rhbz#1797532.patch
Patch6: ansible-freeipa-0.1.8-ipahbacrule-Fix-handing-of-members-with-action-hbacrule_rhbz#1787996.patch
Patch7: ansible-freeipa-0.1.8-ansible_freeipa_module-Fix-comparison-of-bool-parameters-in-compare_args_ipa_rhbz#1784514.patch
Patch8: ansible-freeipa-ipahost-Add-support-for-several-IP-addresses-and-also-to-change-them_rhbz#1783979,1783976.patch
Patch9: ansible-freeipa-0.1.8-ipahost-Fail-on-action-member-for-new-hosts-fix-dnsrecord_add-reverse-flag_rhbz#1803026.patch
Patch10: ansible-freeipa-0.1.8-ipahost-Do-not-fail-on-missing-DNS-or-zone-when-no-IP-address-given_rhbz#1804838.patch
BuildArch: noarch
#Requires: ansible
%description
ansible-freeipa provides Ansible roles and playbooks to install and uninstall
FreeIPA servers, replicas and clients.
FreeIPA servers, replicas and clients also modules for management.
Note: The ansible playbooks and roles require a configured ansible environment
where the ansible nodes are reachable and are properly set up to have an IP
@ -32,6 +38,18 @@ Features
- Cluster deployments: Server, replicas and clients in one playbook
- One-time-password (OTP) support for client installation
- Repair mode for clients
- Modules for group management
- Modules for hbacrule management
- Modules for hbacsvc management
- Modules for hbacsvcgroup management
- Modules for host management
- Modules for hostgroup management
- Modules for pwpolicy management
- Modules for sudocmd management
- Modules for sudocmdgroup management
- Modules for sudorule management
- Modules for topology management
- Modules for user management
Supported FreeIPA Versions
@ -46,13 +64,16 @@ Supported Distributions
- RHEL/CentOS 7.4+
- Fedora 26+
- Ubuntu
- Debian 10+ (ipaclient only, no server or replica!)
Requirements
Controller
- Ansible version: 2.5+
- 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 to install the client.
is used with keytab to install the client.
Node
- Supported FreeIPA version (see above)
@ -73,6 +94,12 @@ or clients in one playbook.
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
# Fix python modules and module utils:
# - Remove shebang
# - Remove execute flag
@ -104,13 +131,103 @@ cp -rp plugins/* %{buildroot}%{_datadir}/ansible/plugins/
%{_datadir}/ansible/plugins/module_utils
%{_datadir}/ansible/plugins/modules
%doc README.md
%doc README-topology.md
%doc README-server.md
%doc README-replica.md
%doc README-client.md
%doc README-*.md
%doc playbooks
%changelog
* Thu Feb 20 2020 Thomas Woerner <twoerner@redhat.com> - 0.1.8-3
- ipahost: Do not fail on missing DNS or zone when no IP address given
Resolves: RHBZ#1804838
* Fri Feb 14 2020 Thomas Woerner <twoerner@redhat.com> - 0.1.8-2
- Updated RPM description for ansible-freeipa 0.1.8
Related: RHBZ#1748986
- ipahost: Fix choices of auth_ind parameter, allow to reset parameter
Resolves: RHBZ#1783992
- ipauser: Allow reset of userauthtype, do not depend on first,last for mod
Resolves: RHBZ#1784474
- ipahost: Enhanced failure msg for member params used without member action
Resolves: RHBZ#1783948
- Add missing attributes to ipasudorule
Resolves: RHBZ#1788168
Resolves: RHBZ#1788035
Resolves: RHBZ#1788024
- ipapwpolicy: Use global_policy if name is not set
Resolves: RHBZ#1797532
- ipahbacrule: Fix handing of members with action hbacrule
Resolves: RHBZ#1787996
- ansible_freeipa_module: Fix comparison of bool parameters in compare_args_isa
Resolves: RHBZ#1784514
- ipahost: Add support for several IP addresses and also to change them
Resolves: RHBZ#1783979
Resolves: RHBZ#1783976
- ipahost: Fail on action member for new hosts, fix dnsrecord_add reverse flag
Resolves: RHBZ#1803026
* Sat Dec 14 2019 Thomas Woerner <twoerner@redhat.com> - 0.1.8-1
- Update to version 0.1.8 (bug fix release)
- roles/ipaclient/README.md: Add information about ipaclient_otp
- Install and enable firewalld if it is configured for ipaserver and
ipareplica roles
- ipaserver_test: Do not use zone_overlap_check for domain name validation
- Allow execution of API commands that do not require a name
- Update README-host: Drop options from allow_*keytab parameters docs
- ipauser: Extend email addresses with default email domain if no domain is
given
Resolves: RHBZ#1747413
Related: RHBZ#1748986
* Mon Dec 2 2019 Thomas Woerner <twoerner@redhat.com> - 0.1.7-1
- Update to version 0.1.7
- Add debian support for ipaclient
- Added support for predefining client OTP using ipaclient_otp
- ipatopologysegment: Store suffix for commands in command list
- ipatopologysegment: Fail for missing entry with reinitialized
- Utils scripts: ansible-ipa-[server,replica,client]-install
- ipaserver_test,ipareplica_prepare: Do not return _pkcs12_file settings
- ansible_freeipa_module: Add support for GSSAPI
- ansible_ipa_client: Drop import of configure_nsswitch_database
- New host management module
- New hostgroup management module
- ipagroup: Remove unused member_[present,absent] states
- external-ca tests: Fix typo in inventory files
- tests/external-signed-ca tests: Fix external-ca.sh to use proper serials
- ipagroup: Rework to use same mechanisms as ipahostgroup module
- ansible_freeipa_module: api_command should not have extra try clause
- ansible_freeipa_module: compare_args_ipa needs to compare lists orderless
- ansible_freeipa_module: New function api_check_param
- ansible_freeipa_module: New functions module_params_get and _afm_convert
- ansible_freeipa_module: Add missing to_text import for _afm_convert
- ansible_freeipa_module: Convert tuple to list in compare_args_ipa
- ansible_freeipa_module: New function api_get_realm
- ipauser: User module extension
- New sudocmd management module
- New sudocmdgroup management module
- ansible_freeipa_module: Convert int to string in compare_args_ipa
- New pwpolicy management module
- New hbacsvc (HBAC Service) management module
- New hbacsvcgroup (HBAC Service Group) management module
- ipagroup: Properly support IPA versions 4.6 and RHEL-7
- ipagroup: Fix changed flag, new test cases
- ipauser: Add info about version limitation of passwordexpiration
- New hbacrule (HBAC Rule) management module
- ipahostgroup: Fix changed flag, support IPA 4.6 on RHEL-7, new test cases
- New sudorule (Sudo Rule) management module
- ipauser: Support 'sn' alias of 'last' for surname
- Update galaxy.yml: Update description, drop empty dependencies
- Update ipauser.py: Fix typo in users.name description
- ipaclient: Fix misspelled sssd options
- ipauser: Return generated random password
- ipahost: Return generated random password
- Added context configuration to api_connect
- ansible_freeipa_module: Better support for KRB5CCNAME environment variable
- ipa[server,replica,client]: Add support for CentOS-8
- ipahost: Extension to be able handle several hosts and all settings
- Flake8 fixes
- Documentation updates
- Cleanup
Resolves: RHBZ#1748986
* Fri Sep 6 2019 Thomas Woerner <twoerner@redhat.com> - 0.1.6-4
- ansible_ipa_client: Drop import of configure_nsswitch_database
(RHBZ#1748905)