import ansible-freeipa-0.3.2-2.el8
This commit is contained in:
parent
d2eec6cc08
commit
72314a0ec3
@ -1 +1 @@
|
||||
5d09d3b590e8568d04edb288c9c515e308f3168f SOURCES/ansible-freeipa-0.1.12.tar.gz
|
||||
7c66c505597de97501d68c81fc1495aa4d627879 SOURCES/ansible-freeipa-0.3.2.tar.gz
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
SOURCES/ansible-freeipa-0.1.12.tar.gz
|
||||
SOURCES/ansible-freeipa-0.3.2.tar.gz
|
||||
|
@ -1,556 +0,0 @@
|
||||
From abbd15e6f50718119b4dd0380913d2d646eb7638 Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Mon, 3 Aug 2020 19:23:07 -0300
|
||||
Subject: [PATCH] Add support for option `name_from_ip` in ipadnszone module.
|
||||
|
||||
IPA CLI has an option `name_from_ip` that provide a name for a zone
|
||||
from the reverse IP address, so that it can be used to, for example,
|
||||
manage PTR DNS records.
|
||||
|
||||
This patch adds a similar attribute to ipadnszone module, where it
|
||||
will try to find the proper zone name, using DNS resolve, or provide
|
||||
a sane default, if a the zone name cannot be resolved.
|
||||
|
||||
The option `name_from_ip` must be used instead of `name` in playbooks,
|
||||
and it is a string, and not a list.
|
||||
|
||||
A new example playbook was added:
|
||||
|
||||
playbooks/dnszone/dnszone-reverse-from-ip.yml
|
||||
|
||||
A new test playbook was added:
|
||||
|
||||
tests/dnszone/test_dnszone_name_from_ip.yml
|
||||
---
|
||||
README-dnszone.md | 3 +-
|
||||
playbooks/dnszone/dnszone-reverse-from-ip.yml | 10 ++
|
||||
plugins/modules/ipadnszone.py | 65 +++++++++-
|
||||
tests/dnszone/test_dnszone_name_from_ip.yml | 112 ++++++++++++++++++
|
||||
4 files changed, 186 insertions(+), 4 deletions(-)
|
||||
create mode 100644 playbooks/dnszone/dnszone-reverse-from-ip.yml
|
||||
create mode 100644 tests/dnszone/test_dnszone_name_from_ip.yml
|
||||
|
||||
diff --git a/README-dnszone.md b/README-dnszone.md
|
||||
index 9c9b12c..48b019a 100644
|
||||
--- a/README-dnszone.md
|
||||
+++ b/README-dnszone.md
|
||||
@@ -163,7 +163,8 @@ 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` \| `zone_name` | The zone name string or list of strings. | yes
|
||||
+`name` \| `zone_name` | The zone name string or list of strings. | no
|
||||
+`name_from_ip` | Derive zone name from reverse of IP (PTR). | no
|
||||
`forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
|
||||
| `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
|
||||
| `port` - The custom port that should be used on this server. | no
|
||||
diff --git a/playbooks/dnszone/dnszone-reverse-from-ip.yml b/playbooks/dnszone/dnszone-reverse-from-ip.yml
|
||||
new file mode 100644
|
||||
index 0000000..5693872
|
||||
--- /dev/null
|
||||
+++ b/playbooks/dnszone/dnszone-reverse-from-ip.yml
|
||||
@@ -0,0 +1,10 @@
|
||||
+---
|
||||
+- name: Playbook to ensure DNS zone exist
|
||||
+ hosts: ipaserver
|
||||
+ become: true
|
||||
+
|
||||
+ tasks:
|
||||
+ - name: Ensure zone exist, finding zone name from IP address.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 10.1.2.3
|
||||
diff --git a/plugins/modules/ipadnszone.py b/plugins/modules/ipadnszone.py
|
||||
index c5e812a..901bfef 100644
|
||||
--- a/plugins/modules/ipadnszone.py
|
||||
+++ b/plugins/modules/ipadnszone.py
|
||||
@@ -43,6 +43,10 @@ options:
|
||||
required: true
|
||||
type: list
|
||||
alises: ["zone_name"]
|
||||
+ name_from_ip:
|
||||
+ description: Derive zone name from reverse of IP (PTR).
|
||||
+ required: false
|
||||
+ type: str
|
||||
forwarders:
|
||||
description: The list of global DNS forwarders.
|
||||
required: false
|
||||
@@ -197,6 +201,12 @@ from ansible.module_utils.ansible_freeipa_module import (
|
||||
is_ipv6_addr,
|
||||
is_valid_port,
|
||||
) # noqa: E402
|
||||
+import netaddr
|
||||
+import six
|
||||
+
|
||||
+
|
||||
+if six.PY3:
|
||||
+ unicode = str
|
||||
|
||||
|
||||
class DNSZoneModule(FreeIPABaseModule):
|
||||
@@ -354,6 +364,31 @@ class DNSZoneModule(FreeIPABaseModule):
|
||||
if not zone and self.ipa_params.skip_nameserver_check is not None:
|
||||
return self.ipa_params.skip_nameserver_check
|
||||
|
||||
+ def __reverse_zone_name(self, ipaddress):
|
||||
+ """
|
||||
+ Infer reverse zone name from an ip address.
|
||||
+
|
||||
+ This function uses the same heuristics as FreeIPA to infer the zone
|
||||
+ name from ip.
|
||||
+ """
|
||||
+ try:
|
||||
+ ip = netaddr.IPAddress(str(ipaddress))
|
||||
+ except (netaddr.AddrFormatError, ValueError):
|
||||
+ net = netaddr.IPNetwork(ipaddress)
|
||||
+ items = net.ip.reverse_dns.split('.')
|
||||
+ prefixlen = net.prefixlen
|
||||
+ ip_version = net.version
|
||||
+ else:
|
||||
+ items = ip.reverse_dns.split('.')
|
||||
+ prefixlen = 24 if ip.version == 4 else 64
|
||||
+ ip_version = ip.version
|
||||
+ if ip_version == 4:
|
||||
+ return u'.'.join(items[4 - prefixlen // 8:])
|
||||
+ elif ip_version == 6:
|
||||
+ return u'.'.join(items[32 - prefixlen // 4:])
|
||||
+ else:
|
||||
+ self.fail_json(msg="Invalid IP version for reverse zone.")
|
||||
+
|
||||
def get_zone(self, zone_name):
|
||||
get_zone_args = {"idnsname": zone_name, "all": True}
|
||||
response = self.api_command("dnszone_find", args=get_zone_args)
|
||||
@@ -368,14 +403,33 @@ class DNSZoneModule(FreeIPABaseModule):
|
||||
return zone, is_zone_active
|
||||
|
||||
def get_zone_names(self):
|
||||
- if len(self.ipa_params.name) > 1 and self.ipa_params.state != "absent":
|
||||
+ zone_names = self.__get_zone_names_from_params()
|
||||
+ if len(zone_names) > 1 and self.ipa_params.state != "absent":
|
||||
self.fail_json(
|
||||
msg=("Please provide a single name. Multiple values for 'name'"
|
||||
"can only be supplied for state 'absent'.")
|
||||
)
|
||||
|
||||
+ return zone_names
|
||||
+
|
||||
+ def __get_zone_names_from_params(self):
|
||||
+ if not self.ipa_params.name:
|
||||
+ return [self.__reverse_zone_name(self.ipa_params.name_from_ip)]
|
||||
return self.ipa_params.name
|
||||
|
||||
+ def check_ipa_params(self):
|
||||
+ if not self.ipa_params.name and not self.ipa_params.name_from_ip:
|
||||
+ self.fail_json(
|
||||
+ msg="Either `name` or `name_from_ip` must be provided."
|
||||
+ )
|
||||
+ if self.ipa_params.state != "present" and self.ipa_params.name_from_ip:
|
||||
+ self.fail_json(
|
||||
+ msg=(
|
||||
+ "Cannot use argument `name_from_ip` with state `%s`."
|
||||
+ % self.ipa_params.state
|
||||
+ )
|
||||
+ )
|
||||
+
|
||||
def define_ipa_commands(self):
|
||||
for zone_name in self.get_zone_names():
|
||||
# Look for existing zone in IPA
|
||||
@@ -434,8 +488,9 @@ def get_argument_spec():
|
||||
ipaadmin_principal=dict(type="str", default="admin"),
|
||||
ipaadmin_password=dict(type="str", required=False, no_log=True),
|
||||
name=dict(
|
||||
- type="list", default=None, required=True, aliases=["zone_name"]
|
||||
+ type="list", default=None, required=False, aliases=["zone_name"]
|
||||
),
|
||||
+ name_from_ip=dict(type="str", default=None, required=False),
|
||||
forwarders=dict(
|
||||
type="list",
|
||||
default=None,
|
||||
@@ -475,7 +530,11 @@ def get_argument_spec():
|
||||
|
||||
|
||||
def main():
|
||||
- DNSZoneModule(argument_spec=get_argument_spec()).ipa_run()
|
||||
+ DNSZoneModule(
|
||||
+ argument_spec=get_argument_spec(),
|
||||
+ mutually_exclusive=[["name", "name_from_ip"]],
|
||||
+ required_one_of=[["name", "name_from_ip"]],
|
||||
+ ).ipa_run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
diff --git a/tests/dnszone/test_dnszone_name_from_ip.yml b/tests/dnszone/test_dnszone_name_from_ip.yml
|
||||
new file mode 100644
|
||||
index 0000000..9bd2eb0
|
||||
--- /dev/null
|
||||
+++ b/tests/dnszone/test_dnszone_name_from_ip.yml
|
||||
@@ -0,0 +1,112 @@
|
||||
+---
|
||||
+- name: Test dnszone
|
||||
+ hosts: ipaserver
|
||||
+ become: yes
|
||||
+ gather_facts: yes
|
||||
+
|
||||
+ tasks:
|
||||
+
|
||||
+ # Setup
|
||||
+ - name: Ensure zone is absent.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "{{ item }}"
|
||||
+ state: absent
|
||||
+ with_items:
|
||||
+ - 2.0.192.in-addr.arpa.
|
||||
+ - 0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f.ip6.arpa.
|
||||
+ - 1.0.0.0.e.f.a.c.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
+
|
||||
+ # tests
|
||||
+ - name: Ensure zone exists for reverse IP.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 192.0.2.3/24
|
||||
+ register: ipv4_zone
|
||||
+ failed_when: not ipv4_zone.changed or ipv4_zone.failed
|
||||
+
|
||||
+ - name: Ensure zone exists for reverse IP, again.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 192.0.2.3/24
|
||||
+ register: result
|
||||
+ failed_when: result.changed or result.failed
|
||||
+
|
||||
+ - name: Ensure zone exists for reverse IP, given the zone name.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "{{ ipv4_zone.dnszone.name }}"
|
||||
+ register: result
|
||||
+ failed_when: result.changed or result.failed
|
||||
+
|
||||
+ - name: Modify existing zone, using `name_from_ip`.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 192.0.2.3/24
|
||||
+ default_ttl: 1234
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Modify existing zone, using `name_from_ip`, again.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 192.0.2.3/24
|
||||
+ default_ttl: 1234
|
||||
+ register: result
|
||||
+ failed_when: result.changed or result.failed
|
||||
+
|
||||
+ - name: Ensure ipv6 zone exists for reverse IPv6.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: fd00::0001
|
||||
+ register: ipv6_zone
|
||||
+ failed_when: not ipv6_zone.changed or ipv6_zone.failed
|
||||
+
|
||||
+ # - debug:
|
||||
+ # msg: "{{ipv6_zone}}"
|
||||
+
|
||||
+ - name: Ensure ipv6 zone was created.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "{{ ipv6_zone.dnszone.name }}"
|
||||
+ register: result
|
||||
+ failed_when: result.changed or result.failed
|
||||
+
|
||||
+ - name: Ensure ipv6 zone exists for reverse IPv6, again.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: fd00::0001
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Ensure second ipv6 zone exists for reverse IPv6.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 2001:db8:cafe:1::1
|
||||
+ register: ipv6_sec_zone
|
||||
+ failed_when: not ipv6_sec_zone.changed or ipv6_zone.failed
|
||||
+
|
||||
+ - name: Ensure second ipv6 zone was created.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "{{ ipv6_sec_zone.dnszone.name }}"
|
||||
+ register: result
|
||||
+ failed_when: result.changed or result.failed
|
||||
+
|
||||
+ - name: Ensure second ipv6 zone exists for reverse IPv6, again.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 2001:db8:cafe:1::1
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ # Cleanup
|
||||
+ - name: Ensure zone is absent.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "{{ item }}"
|
||||
+ state: absent
|
||||
+ with_items:
|
||||
+ - "{{ ipv6_zone.dnszone.name }}"
|
||||
+ - "{{ ipv6_sec_zone.dnszone.name }}"
|
||||
+ - "{{ ipv4_zone.dnszone.name }}"
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From 531e544b30e69f436d14c4ce18c67998c1a0774b Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Wed, 5 Aug 2020 15:13:46 -0300
|
||||
Subject: [PATCH] Added support for client defined result data in
|
||||
FReeIPABaseModule
|
||||
|
||||
Modified support for processing result of IPA API commands so that
|
||||
client code can define its own processing and add return values to
|
||||
self.exit_args based on command result.
|
||||
|
||||
If a subclass need to process the result of IPA API commands it should
|
||||
override the method `process_command_result`. The default implementation
|
||||
will simply evaluate if `changed` should be true.
|
||||
---
|
||||
.../module_utils/ansible_freeipa_module.py | 22 +++++++++++++------
|
||||
plugins/modules/ipadnszone.py | 8 +++++++
|
||||
2 files changed, 23 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
|
||||
index 4799e5a..30302b4 100644
|
||||
--- a/plugins/module_utils/ansible_freeipa_module.py
|
||||
+++ b/plugins/module_utils/ansible_freeipa_module.py
|
||||
@@ -619,7 +619,7 @@ class FreeIPABaseModule(AnsibleModule):
|
||||
if exc_val:
|
||||
self.fail_json(msg=str(exc_val))
|
||||
|
||||
- self.exit_json(changed=self.changed, user=self.exit_args)
|
||||
+ self.exit_json(changed=self.changed, **self.exit_args)
|
||||
|
||||
def get_command_errors(self, command, result):
|
||||
"""Look for erros into command results."""
|
||||
@@ -658,14 +658,22 @@ class FreeIPABaseModule(AnsibleModule):
|
||||
except Exception as excpt:
|
||||
self.fail_json(msg="%s: %s: %s" % (command, name, str(excpt)))
|
||||
else:
|
||||
- if "completed" in result:
|
||||
- if result["completed"] > 0:
|
||||
- self.changed = True
|
||||
- else:
|
||||
- self.changed = True
|
||||
-
|
||||
+ self.process_command_result(name, command, args, result)
|
||||
self.get_command_errors(command, result)
|
||||
|
||||
+ def process_command_result(self, name, command, args, result):
|
||||
+ """
|
||||
+ Process an API command result.
|
||||
+
|
||||
+ This method can be overriden in subclasses, and change self.exit_values
|
||||
+ to return data in the result for the controller.
|
||||
+ """
|
||||
+ if "completed" in result:
|
||||
+ if result["completed"] > 0:
|
||||
+ self.changed = True
|
||||
+ else:
|
||||
+ self.changed = True
|
||||
+
|
||||
def require_ipa_attrs_change(self, command_args, ipa_attrs):
|
||||
"""
|
||||
Compare given args with current object attributes.
|
||||
diff --git a/plugins/modules/ipadnszone.py b/plugins/modules/ipadnszone.py
|
||||
index 901bfef..6a90fa2 100644
|
||||
--- a/plugins/modules/ipadnszone.py
|
||||
+++ b/plugins/modules/ipadnszone.py
|
||||
@@ -472,6 +472,14 @@ class DNSZoneModule(FreeIPABaseModule):
|
||||
}
|
||||
self.add_ipa_command("dnszone_mod", zone_name, args)
|
||||
|
||||
+ def process_command_result(self, name, command, args, result):
|
||||
+ super(DNSZoneModule, self).process_command_result(
|
||||
+ name, command, args, result
|
||||
+ )
|
||||
+ if command == "dnszone_add" and self.ipa_params.name_from_ip:
|
||||
+ dnszone_exit_args = self.exit_args.setdefault('dnszone', {})
|
||||
+ dnszone_exit_args['name'] = name
|
||||
+
|
||||
|
||||
def get_argument_spec():
|
||||
forwarder_spec = dict(
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From 41e8226d0c03e06816626d78cecbc2aebf547691 Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Wed, 5 Aug 2020 15:14:43 -0300
|
||||
Subject: [PATCH] Return the zone_name when adding a zone with name_from_ip.
|
||||
|
||||
When adding a zone using the option name_from_ip, the user have
|
||||
little control over the final name of the zone, and if this name
|
||||
is to be used in further processing in a playbook it might lead to
|
||||
errors if the inferred name does not match what the user wanted to.
|
||||
|
||||
By returning the actual inferred zone name, the name can be safely
|
||||
used for other tasks in the playbook.
|
||||
---
|
||||
README-dnszone.md | 11 +++++++++++
|
||||
playbooks/dnszone/dnszone-reverse-from-ip.yml | 7 ++++++-
|
||||
plugins/modules/ipadnszone.py | 8 ++++++++
|
||||
3 files changed, 25 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/README-dnszone.md b/README-dnszone.md
|
||||
index 48b019a..3f4827b 100644
|
||||
--- a/README-dnszone.md
|
||||
+++ b/README-dnszone.md
|
||||
@@ -190,6 +190,17 @@ Variable | Description | Required
|
||||
`skip_nameserver_check` | Force DNS zone creation even if nameserver is not resolvable | no
|
||||
|
||||
|
||||
+Return Values
|
||||
+=============
|
||||
+
|
||||
+ipadnszone
|
||||
+----------
|
||||
+
|
||||
+Variable | Description | Returned When
|
||||
+-------- | ----------- | -------------
|
||||
+`dnszone` | DNS Zone dict with zone name infered from `name_from_ip`. <br>Options: | If `state` is `present`, `name_from_ip` is used, and a zone was created.
|
||||
+ | `name` - The name of the zone created, inferred from `name_from_ip`. | Always
|
||||
+
|
||||
Authors
|
||||
=======
|
||||
|
||||
diff --git a/playbooks/dnszone/dnszone-reverse-from-ip.yml b/playbooks/dnszone/dnszone-reverse-from-ip.yml
|
||||
index 5693872..218a318 100644
|
||||
--- a/playbooks/dnszone/dnszone-reverse-from-ip.yml
|
||||
+++ b/playbooks/dnszone/dnszone-reverse-from-ip.yml
|
||||
@@ -7,4 +7,9 @@
|
||||
- name: Ensure zone exist, finding zone name from IP address.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
- name_from_ip: 10.1.2.3
|
||||
+ name_from_ip: 10.1.2.3/24
|
||||
+ register: result
|
||||
+
|
||||
+ - name: Zone name inferred from `name_from_ip`
|
||||
+ debug:
|
||||
+ msg: "Zone created: {{ result.dnszone.name }}"
|
||||
diff --git a/plugins/modules/ipadnszone.py b/plugins/modules/ipadnszone.py
|
||||
index 6a90fa2..93eac07 100644
|
||||
--- a/plugins/modules/ipadnszone.py
|
||||
+++ b/plugins/modules/ipadnszone.py
|
||||
@@ -192,6 +192,14 @@ EXAMPLES = """
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
+dnszone:
|
||||
+ description: DNS Zone dict with zone name infered from `name_from_ip`.
|
||||
+ returned:
|
||||
+ If `state` is `present`, `name_from_ip` is used, and a zone was created.
|
||||
+ options:
|
||||
+ name:
|
||||
+ description: The name of the zone created, inferred from `name_from_ip`.
|
||||
+ returned: always
|
||||
"""
|
||||
|
||||
from ipapython.dnsutil import DNSName # noqa: E402
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From 46bbc7bbd7a4e01d07b0390aee8c799aaa5ac895 Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Mon, 17 Aug 2020 15:52:38 -0300
|
||||
Subject: [PATCH] Document usage of `name_from_ip`.
|
||||
|
||||
Since `name_from_ip` has a similar, but not equal, behavior to `name`,
|
||||
and as the inferred DNS zone might depend on DNS configuration and
|
||||
can be different than the user expects, it has some limited usage,
|
||||
and the user must be aware of its effects.
|
||||
|
||||
This change to the documentation enhance the documentation including
|
||||
more details on the attribute usage.
|
||||
---
|
||||
README-dnszone.md | 42 ++++++++++++++++++++++++++++++++++-
|
||||
plugins/modules/ipadnszone.py | 4 +++-
|
||||
2 files changed, 44 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/README-dnszone.md b/README-dnszone.md
|
||||
index 3f4827b..c5a7ab3 100644
|
||||
--- a/README-dnszone.md
|
||||
+++ b/README-dnszone.md
|
||||
@@ -152,6 +152,46 @@ Example playbook to remove a zone:
|
||||
|
||||
```
|
||||
|
||||
+Example playbook to create a zone for reverse DNS lookup, from an IP address:
|
||||
+
|
||||
+```yaml
|
||||
+
|
||||
+---
|
||||
+- name: dnszone present
|
||||
+ hosts: ipaserver
|
||||
+ become: true
|
||||
+
|
||||
+ tasks:
|
||||
+ - name: Ensure zone for reverse DNS lookup is present.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 192.168.1.2
|
||||
+ state: present
|
||||
+```
|
||||
+
|
||||
+Note that, on the previous example the zone created with `name_from_ip` might be "1.168.192.in-addr.arpa.", "168.192.in-addr.arpa.", or "192.in-addr.arpa.", depending on the DNS response the system get while querying for zones, and for this reason, when creating a zone using `name_from_ip`, the inferred zone name is returned to the controller, in the attribute `dnszone.name`. Since the zone inferred might not be what a user expects, `name_from_ip` can only be used with `state: present`. To have more control over the zone name, the prefix length for the IP address can be provided.
|
||||
+
|
||||
+Example playbook to create a zone for reverse DNS lookup, from an IP address, given the prefix length and displaying the resulting zone name:
|
||||
+
|
||||
+```yaml
|
||||
+
|
||||
+---
|
||||
+- name: dnszone present
|
||||
+ hosts: ipaserver
|
||||
+ become: true
|
||||
+
|
||||
+ tasks:
|
||||
+ - name: Ensure zone for reverse DNS lookup is present.
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name_from_ip: 192.168.1.2/24
|
||||
+ state: present
|
||||
+ register: result
|
||||
+ - name: Display inferred zone name.
|
||||
+ debug:
|
||||
+ msg: "Zone name: {{ result.dnszone.name }}"
|
||||
+```
|
||||
+
|
||||
|
||||
Variables
|
||||
=========
|
||||
@@ -164,7 +204,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` \| `zone_name` | The zone name string or list of strings. | no
|
||||
-`name_from_ip` | Derive zone name from reverse of IP (PTR). | no
|
||||
+`name_from_ip` | Derive zone name from reverse of IP (PTR). Can only be used with `state: present`. | no
|
||||
`forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
|
||||
| `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
|
||||
| `port` - The custom port that should be used on this server. | no
|
||||
diff --git a/plugins/modules/ipadnszone.py b/plugins/modules/ipadnszone.py
|
||||
index 93eac07..ff6bfff 100644
|
||||
--- a/plugins/modules/ipadnszone.py
|
||||
+++ b/plugins/modules/ipadnszone.py
|
||||
@@ -44,7 +44,9 @@ options:
|
||||
type: list
|
||||
alises: ["zone_name"]
|
||||
name_from_ip:
|
||||
- description: Derive zone name from reverse of IP (PTR).
|
||||
+ description: |
|
||||
+ Derive zone name from reverse of IP (PTR).
|
||||
+ Can only be used with `state: present`.
|
||||
required: false
|
||||
type: str
|
||||
forwarders:
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,435 +0,0 @@
|
||||
From 78b635ae78346fdfb298dd0d0c82ae1ff34b754a Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Tue, 23 Jun 2020 17:53:47 -0300
|
||||
Subject: [PATCH] Add suppport for changing password of symmetric vaults.
|
||||
|
||||
Allows changing passwords of symmetric waults, using a new variable
|
||||
`new_password` (or the file-base version, `new_password_file`). The
|
||||
old password must be passed using the `password` or `password_file`
|
||||
variables that also received new aliases `old_password` and
|
||||
`old_password_file`, respectively.
|
||||
|
||||
Tests were modyfied to reflect the changes.
|
||||
---
|
||||
README-vault.md | 23 +++-
|
||||
.../vault/change-password-symmetric-vault.yml | 2 +-
|
||||
plugins/modules/ipavault.py | 129 +++++++++++++++---
|
||||
tests/vault/test_vault_symmetric.yml | 64 +++++++++
|
||||
4 files changed, 194 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/README-vault.md b/README-vault.md
|
||||
index c7ae6916..fa1d3e11 100644
|
||||
--- a/README-vault.md
|
||||
+++ b/README-vault.md
|
||||
@@ -165,6 +165,22 @@ Example playbook to make sure vault data is absent in a symmetric vault:
|
||||
state: absent
|
||||
```
|
||||
|
||||
+Example playbook to change the password of a symmetric:
|
||||
+
|
||||
+```yaml
|
||||
+---
|
||||
+- name: Playbook to handle vaults
|
||||
+ hosts: ipaserver
|
||||
+ become: true
|
||||
+
|
||||
+ tasks:
|
||||
+ - ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ old_password: SomeVAULTpassword
|
||||
+ new_password: SomeNEWpassword
|
||||
+```
|
||||
+
|
||||
Example playbook to make sure vault is absent:
|
||||
|
||||
```yaml
|
||||
@@ -197,8 +213,11 @@ Variable | Description | Required
|
||||
`name` \| `cn` | The list of vault name strings. | yes
|
||||
`description` | The vault description string. | no
|
||||
`nomembers` | Suppress processing of membership attributes. (bool) | no
|
||||
-`password ` \| `vault_password` \| `ipavaultpassword` | Vault password. | no
|
||||
-`public_key ` \| `vault_public_key` \| `ipavaultpublickey` | Base64 encoded vault public key. | no
|
||||
+`password` \| `vault_password` \| `ipavaultpassword` \| `old_password`| Vault password. | no
|
||||
+`password_file` \| `vault_password_file` \| `old_password_file`| File containing Base64 encoded Vault password. | no
|
||||
+`new_password` | Vault new password. | no
|
||||
+`new_password_file` | File containing Base64 encoded new Vault password. | no
|
||||
+`public_key ` \| `vault_public_key` \| `old_password_file` | Base64 encoded vault public key. | no
|
||||
`public_key_file` \| `vault_public_key_file` | Path to file with public key. | no
|
||||
`private_key `\| `vault_private_key` | Base64 encoded vault private key. Used only to retrieve data. | no
|
||||
`private_key_file` \| `vault_private_key_file` | Path to file with private key. Used only to retrieve data. | no
|
||||
diff --git a/playbooks/vault/change-password-symmetric-vault.yml b/playbooks/vault/change-password-symmetric-vault.yml
|
||||
index 3871f45d..396a79f6 100644
|
||||
--- a/playbooks/vault/change-password-symmetric-vault.yml
|
||||
+++ b/playbooks/vault/change-password-symmetric-vault.yml
|
||||
@@ -10,7 +10,7 @@
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: symvault
|
||||
password: SomeVAULTpassword
|
||||
- - name: Change vault passord.
|
||||
+ - name: Change vault password.
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: symvault
|
||||
diff --git a/plugins/modules/ipavault.py b/plugins/modules/ipavault.py
|
||||
index ad5dd413..46c6fcdb 100644
|
||||
--- a/plugins/modules/ipavault.py
|
||||
+++ b/plugins/modules/ipavault.py
|
||||
@@ -69,12 +69,20 @@
|
||||
description: password to be used on symmetric vault.
|
||||
required: false
|
||||
type: string
|
||||
- aliases: ["ipavaultpassword", "vault_password"]
|
||||
+ aliases: ["ipavaultpassword", "vault_password", "old_password"]
|
||||
password_file:
|
||||
description: file with password to be used on symmetric vault.
|
||||
required: false
|
||||
type: string
|
||||
- aliases: ["vault_password_file"]
|
||||
+ aliases: ["vault_password_file", "old_password_file"]
|
||||
+ new_password:
|
||||
+ description: new password to be used on symmetric vault.
|
||||
+ required: false
|
||||
+ type: string
|
||||
+ new_password_file:
|
||||
+ description: file with new password to be used on symmetric vault.
|
||||
+ required: false
|
||||
+ type: string
|
||||
salt:
|
||||
description: Vault salt.
|
||||
required: false
|
||||
@@ -235,7 +243,15 @@
|
||||
state: retrieved
|
||||
register: result
|
||||
- debug:
|
||||
- msg: "{{ result.data | b64decode }}"
|
||||
+ msg: "{{ result.data }}"
|
||||
+
|
||||
+# Change password of a symmetric vault
|
||||
+- ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ username: admin
|
||||
+ old_password: SomeVAULTpassword
|
||||
+ new_password: SomeNEWpassword
|
||||
|
||||
# Ensure vault symvault is absent
|
||||
- ipavault:
|
||||
@@ -416,18 +432,29 @@ def check_parameters(module, state, action, description, username, service,
|
||||
shared, users, groups, services, owners, ownergroups,
|
||||
ownerservices, vault_type, salt, password, password_file,
|
||||
public_key, public_key_file, private_key,
|
||||
- private_key_file, vault_data, datafile_in, datafile_out):
|
||||
+ private_key_file, vault_data, datafile_in, datafile_out,
|
||||
+ new_password, new_password_file):
|
||||
invalid = []
|
||||
if state == "present":
|
||||
invalid = ['private_key', 'private_key_file', 'datafile_out']
|
||||
|
||||
+ if all([password, password_file]) \
|
||||
+ or all([new_password, new_password_file]):
|
||||
+ module.fail_json(msg="Password specified multiple times.")
|
||||
+
|
||||
+ if any([new_password, new_password_file]) \
|
||||
+ and not any([password, password_file]):
|
||||
+ module.fail_json(
|
||||
+ msg="Either `password` or `password_file` must be provided to "
|
||||
+ "change symmetric vault password.")
|
||||
+
|
||||
if action == "member":
|
||||
invalid.extend(['description'])
|
||||
|
||||
elif state == "absent":
|
||||
invalid = ['description', 'salt', 'vault_type', 'private_key',
|
||||
'private_key_file', 'datafile_in', 'datafile_out',
|
||||
- 'vault_data']
|
||||
+ 'vault_data', 'new_password', 'new_password_file']
|
||||
|
||||
if action == "vault":
|
||||
invalid.extend(['users', 'groups', 'services', 'owners',
|
||||
@@ -437,7 +464,7 @@ def check_parameters(module, state, action, description, username, service,
|
||||
elif state == "retrieved":
|
||||
invalid = ['description', 'salt', 'datafile_in', 'users', 'groups',
|
||||
'owners', 'ownergroups', 'public_key', 'public_key_file',
|
||||
- 'vault_data']
|
||||
+ 'vault_data', 'new_password', 'new_password_file']
|
||||
if action == 'member':
|
||||
module.fail_json(
|
||||
msg="State `retrieved` do not support action `member`.")
|
||||
@@ -458,11 +485,17 @@ def check_parameters(module, state, action, description, username, service,
|
||||
def check_encryption_params(module, state, action, vault_type, salt,
|
||||
password, password_file, public_key,
|
||||
public_key_file, private_key, private_key_file,
|
||||
- vault_data, datafile_in, datafile_out, res_find):
|
||||
+ vault_data, datafile_in, datafile_out,
|
||||
+ new_password, new_password_file, res_find):
|
||||
vault_type_invalid = []
|
||||
+
|
||||
+ if res_find is not None:
|
||||
+ vault_type = res_find['ipavaulttype']
|
||||
+
|
||||
if vault_type == "standard":
|
||||
vault_type_invalid = ['public_key', 'public_key_file', 'password',
|
||||
- 'password_file', 'salt']
|
||||
+ 'password_file', 'salt', 'new_password',
|
||||
+ 'new_password_file']
|
||||
|
||||
if vault_type is None or vault_type == "symmetric":
|
||||
vault_type_invalid = ['public_key', 'public_key_file',
|
||||
@@ -473,8 +506,14 @@ def check_encryption_params(module, state, action, vault_type, salt,
|
||||
msg="Symmetric vault requires password or password_file "
|
||||
"to store data or change `salt`.")
|
||||
|
||||
+ if any([new_password, new_password_file]) and res_find is None:
|
||||
+ module.fail_json(
|
||||
+ msg="Cannot modify password of inexistent vault.")
|
||||
+
|
||||
if vault_type == "asymmetric":
|
||||
- vault_type_invalid = ['password', 'password_file']
|
||||
+ vault_type_invalid = [
|
||||
+ 'password', 'password_file', 'new_password', 'new_password_file'
|
||||
+ ]
|
||||
if not any([public_key, public_key_file]) and res_find is None:
|
||||
module.fail_json(
|
||||
msg="Assymmetric vault requires public_key "
|
||||
@@ -487,6 +526,43 @@ def check_encryption_params(module, state, action, vault_type, salt,
|
||||
(param, vault_type or 'symmetric'))
|
||||
|
||||
|
||||
+def change_password(module, res_find, password, password_file, new_password,
|
||||
+ new_password_file):
|
||||
+ """
|
||||
+ Change the password of a symmetric vault.
|
||||
+
|
||||
+ To change the password of a vault, it is needed to retrieve the stored
|
||||
+ data with the current password, and store the data again, with the new
|
||||
+ password, forcing it to override the old one.
|
||||
+ """
|
||||
+ # verify parameters.
|
||||
+ if not any([new_password, new_password_file]):
|
||||
+ return []
|
||||
+ if res_find["ipavaulttype"][0] != "symmetric":
|
||||
+ module.fail_json(msg="Cannot change password of `%s` vault."
|
||||
+ % res_find["ipavaulttype"])
|
||||
+
|
||||
+ # prepare arguments to retrieve data.
|
||||
+ name = res_find["cn"][0]
|
||||
+ args = {}
|
||||
+ if password:
|
||||
+ args["password"] = password
|
||||
+ if password_file:
|
||||
+ args["password"] = password_file
|
||||
+ # retrieve current stored data
|
||||
+ result = api_command(module, 'vault_retrieve', name, args)
|
||||
+ args['data'] = result['result']['data']
|
||||
+
|
||||
+ # modify arguments to store data with new password.
|
||||
+ if password:
|
||||
+ args["password"] = new_password
|
||||
+ if password_file:
|
||||
+ args["password"] = new_password_file
|
||||
+ args["override_password"] = True
|
||||
+ # return the command to store data with the new password.
|
||||
+ return [(name, "vault_archive", args)]
|
||||
+
|
||||
+
|
||||
def main():
|
||||
ansible_module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
@@ -533,10 +609,18 @@ def main():
|
||||
datafile_out=dict(type="str", required=False, default=None,
|
||||
aliases=['out']),
|
||||
vault_password=dict(type="str", required=False, default=None,
|
||||
- aliases=['ipavaultpassword', 'password'],
|
||||
- no_log=True),
|
||||
+ no_log=True,
|
||||
+ aliases=['ipavaultpassword', 'password',
|
||||
+ "old_password"]),
|
||||
vault_password_file=dict(type="str", required=False, default=None,
|
||||
- no_log=False, aliases=['password_file']),
|
||||
+ no_log=False,
|
||||
+ aliases=[
|
||||
+ 'password_file', "old_password_file"
|
||||
+ ]),
|
||||
+ new_password=dict(type="str", required=False, default=None,
|
||||
+ no_log=True),
|
||||
+ new_password_file=dict(type="str", required=False, default=None,
|
||||
+ no_log=False),
|
||||
# state
|
||||
action=dict(type="str", default="vault",
|
||||
choices=["vault", "data", "member"]),
|
||||
@@ -546,6 +630,7 @@ def main():
|
||||
supports_check_mode=True,
|
||||
mutually_exclusive=[['username', 'service', 'shared'],
|
||||
['datafile_in', 'vault_data'],
|
||||
+ ['new_password', 'new_password_file'],
|
||||
['vault_password', 'vault_password_file'],
|
||||
['vault_public_key', 'vault_public_key_file']],
|
||||
)
|
||||
@@ -576,6 +661,8 @@ def main():
|
||||
salt = module_params_get(ansible_module, "vault_salt")
|
||||
password = module_params_get(ansible_module, "vault_password")
|
||||
password_file = module_params_get(ansible_module, "vault_password_file")
|
||||
+ new_password = module_params_get(ansible_module, "new_password")
|
||||
+ new_password_file = module_params_get(ansible_module, "new_password_file")
|
||||
public_key = module_params_get(ansible_module, "vault_public_key")
|
||||
public_key_file = module_params_get(ansible_module,
|
||||
"vault_public_key_file")
|
||||
@@ -614,7 +701,8 @@ def main():
|
||||
service, shared, users, groups, services, owners,
|
||||
ownergroups, ownerservices, vault_type, salt, password,
|
||||
password_file, public_key, public_key_file, private_key,
|
||||
- private_key_file, vault_data, datafile_in, datafile_out)
|
||||
+ private_key_file, vault_data, datafile_in, datafile_out,
|
||||
+ new_password, new_password_file)
|
||||
# Init
|
||||
|
||||
changed = False
|
||||
@@ -660,7 +748,7 @@ def main():
|
||||
ansible_module, state, action, vault_type, salt, password,
|
||||
password_file, public_key, public_key_file, private_key,
|
||||
private_key_file, vault_data, datafile_in, datafile_out,
|
||||
- res_find)
|
||||
+ new_password, new_password_file, res_find)
|
||||
|
||||
# Found the vault
|
||||
if action == "vault":
|
||||
@@ -721,7 +809,6 @@ def main():
|
||||
owner_add_args = gen_member_args(
|
||||
args, owner_add, ownergroups_add, ownerservice_add)
|
||||
if owner_add_args is not None:
|
||||
- # ansible_module.warn("OWNER ADD: %s" % owner_add_args)
|
||||
commands.append(
|
||||
[name, 'vault_add_owner', owner_add_args])
|
||||
|
||||
@@ -729,7 +816,6 @@ def main():
|
||||
owner_del_args = gen_member_args(
|
||||
args, owner_del, ownergroups_del, ownerservice_del)
|
||||
if owner_del_args is not None:
|
||||
- # ansible_module.warn("OWNER DEL: %s" % owner_del_args)
|
||||
commands.append(
|
||||
[name, 'vault_remove_owner', owner_del_args])
|
||||
|
||||
@@ -758,19 +844,22 @@ def main():
|
||||
if any([vault_data, datafile_in]):
|
||||
commands.append([name, "vault_archive", pwdargs])
|
||||
|
||||
+ cmds = change_password(
|
||||
+ ansible_module, res_find, password, password_file,
|
||||
+ new_password, new_password_file)
|
||||
+ commands.extend(cmds)
|
||||
+
|
||||
elif state == "retrieved":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(
|
||||
msg="Vault `%s` not found to retrieve data." % name)
|
||||
|
||||
- vault_type = res_find['cn']
|
||||
-
|
||||
# verify data encription args
|
||||
check_encryption_params(
|
||||
ansible_module, state, action, vault_type, salt, password,
|
||||
password_file, public_key, public_key_file, private_key,
|
||||
private_key_file, vault_data, datafile_in, datafile_out,
|
||||
- res_find)
|
||||
+ new_password, new_password_file, res_find)
|
||||
|
||||
pwdargs = data_storage_args(
|
||||
args, vault_data, password, password_file, private_key,
|
||||
@@ -813,7 +902,6 @@ def main():
|
||||
errors = []
|
||||
for name, command, args in commands:
|
||||
try:
|
||||
- # ansible_module.warn("RUN: %s %s %s" % (command, name, args))
|
||||
result = api_command(ansible_module, command, name, args)
|
||||
|
||||
if command == 'vault_archive':
|
||||
@@ -829,7 +917,6 @@ def main():
|
||||
raise Exception("No data retrieved.")
|
||||
changed = False
|
||||
else:
|
||||
- # ansible_module.warn("RESULT: %s" % (result))
|
||||
if "completed" in result:
|
||||
if result["completed"] > 0:
|
||||
changed = True
|
||||
diff --git a/tests/vault/test_vault_symmetric.yml b/tests/vault/test_vault_symmetric.yml
|
||||
index c9429f4f..a6072d88 100644
|
||||
--- a/tests/vault/test_vault_symmetric.yml
|
||||
+++ b/tests/vault/test_vault_symmetric.yml
|
||||
@@ -178,6 +178,61 @@
|
||||
register: result
|
||||
failed_when: result.data != 'Hello World.' or result.changed
|
||||
|
||||
+ - name: Change vault password.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ password: SomeVAULTpassword
|
||||
+ new_password: SomeNEWpassword
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Retrieve data from symmetric vault, with wrong password.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ password: SomeVAULTpassword
|
||||
+ state: retrieved
|
||||
+ register: result
|
||||
+ failed_when: not result.failed or "Invalid credentials" not in result.msg
|
||||
+
|
||||
+ - name: Change vault password, with wrong `old_password`.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ password: SomeVAULTpassword
|
||||
+ new_password: SomeNEWpassword
|
||||
+ register: result
|
||||
+ failed_when: not result.failed or "Invalid credentials" not in result.msg
|
||||
+
|
||||
+ - name: Retrieve data from symmetric vault, with new password.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ password: SomeNEWpassword
|
||||
+ state: retrieved
|
||||
+ register: result
|
||||
+ failed_when: result.data != 'Hello World.' or result.changed
|
||||
+
|
||||
+ - name: Try to add vault with multiple passwords.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: inexistentvault
|
||||
+ password: SomeVAULTpassword
|
||||
+ password_file: "{{ ansible_env.HOME }}/password.txt"
|
||||
+ register: result
|
||||
+ failed_when: not result.failed or "parameters are mutually exclusive" not in result.msg
|
||||
+
|
||||
+ - name: Try to add vault with multiple new passwords.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: inexistentvault
|
||||
+ password: SomeVAULTpassword
|
||||
+ new_password: SomeVAULTpassword
|
||||
+ new_password_file: "{{ ansible_env.HOME }}/password.txt"
|
||||
+ register: result
|
||||
+ failed_when: not result.failed or "parameters are mutually exclusive" not in result.msg
|
||||
+
|
||||
- name: Ensure symmetric vault is absent
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -194,5 +249,14 @@
|
||||
register: result
|
||||
failed_when: result.changed
|
||||
|
||||
+ - name: Try to change password of inexistent vault.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: inexistentvault
|
||||
+ password: SomeVAULTpassword
|
||||
+ new_password: SomeNEWpassword
|
||||
+ register: result
|
||||
+ failed_when: not result.failed or "Cannot modify password of inexistent vault" not in result.msg
|
||||
+
|
||||
- name: Cleanup testing environment.
|
||||
import_tasks: env_cleanup.yml
|
@ -1,302 +0,0 @@
|
||||
From 75d16c2da4a5621943873a26343eb0f2acc2a925 Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Oliveira Campos <seocam@seocam.com>
|
||||
Date: Mon, 3 Aug 2020 11:54:44 -0300
|
||||
Subject: [PATCH] Allow multiple dns zones to be absent.
|
||||
|
||||
This PR allow ipadnszone module to ensure that multiple dns zones
|
||||
are absent at once, to be consistent with other ansible-freeipa
|
||||
modules.
|
||||
|
||||
To fix this issue, it was required that custom arguents must be
|
||||
passed using keyword arguments so that `get_ipa_command_args()`
|
||||
is kept generic.
|
||||
---
|
||||
README-dnszone.md | 2 +-
|
||||
.../module_utils/ansible_freeipa_module.py | 4 +-
|
||||
plugins/modules/ipadnszone.py | 126 ++++++++++--------
|
||||
tests/dnszone/test_dnszone.yml | 37 +++++
|
||||
4 files changed, 107 insertions(+), 62 deletions(-)
|
||||
|
||||
diff --git a/README-dnszone.md b/README-dnszone.md
|
||||
index 766efe5..9c9b12c 100644
|
||||
--- a/README-dnszone.md
|
||||
+++ b/README-dnszone.md
|
||||
@@ -163,7 +163,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` \| `zone_name` | The zone name string. | yes
|
||||
+`name` \| `zone_name` | The zone name string or list of strings. | yes
|
||||
`forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
|
||||
| `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
|
||||
| `port` - The custom port that should be used on this server. | no
|
||||
diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
|
||||
index 122ea2e..1e55693 100644
|
||||
--- a/plugins/module_utils/ansible_freeipa_module.py
|
||||
+++ b/plugins/module_utils/ansible_freeipa_module.py
|
||||
@@ -506,7 +506,7 @@ class FreeIPABaseModule(AnsibleModule):
|
||||
# when needed.
|
||||
self.ipa_params = AnsibleFreeIPAParams(self)
|
||||
|
||||
- def get_ipa_command_args(self):
|
||||
+ def get_ipa_command_args(self, **kwargs):
|
||||
"""
|
||||
Return a dict to be passed to an IPA command.
|
||||
|
||||
@@ -538,7 +538,7 @@ class FreeIPABaseModule(AnsibleModule):
|
||||
elif hasattr(self, param_name):
|
||||
method = getattr(self, param_name)
|
||||
if callable(method):
|
||||
- value = method()
|
||||
+ value = method(**kwargs)
|
||||
|
||||
# We don't have a way to guess the value so fail.
|
||||
else:
|
||||
diff --git a/plugins/modules/ipadnszone.py b/plugins/modules/ipadnszone.py
|
||||
index 717978e..c5e812a 100644
|
||||
--- a/plugins/modules/ipadnszone.py
|
||||
+++ b/plugins/modules/ipadnszone.py
|
||||
@@ -41,7 +41,7 @@ options:
|
||||
name:
|
||||
description: The zone name string.
|
||||
required: true
|
||||
- type: str
|
||||
+ type: list
|
||||
alises: ["zone_name"]
|
||||
forwarders:
|
||||
description: The list of global DNS forwarders.
|
||||
@@ -268,7 +268,7 @@ class DNSZoneModule(FreeIPABaseModule):
|
||||
|
||||
return True
|
||||
|
||||
- def get_ipa_nsec3paramrecord(self):
|
||||
+ def get_ipa_nsec3paramrecord(self, **kwargs):
|
||||
nsec3param_rec = self.ipa_params.nsec3param_rec
|
||||
if nsec3param_rec is not None:
|
||||
error_msg = (
|
||||
@@ -280,7 +280,7 @@ class DNSZoneModule(FreeIPABaseModule):
|
||||
self.fail_json(msg=error_msg)
|
||||
return nsec3param_rec
|
||||
|
||||
- def get_ipa_idnsforwarders(self):
|
||||
+ def get_ipa_idnsforwarders(self, **kwargs):
|
||||
if self.ipa_params.forwarders is not None:
|
||||
forwarders = []
|
||||
for forwarder in self.ipa_params.forwarders:
|
||||
@@ -304,14 +304,14 @@ class DNSZoneModule(FreeIPABaseModule):
|
||||
|
||||
return forwarders
|
||||
|
||||
- def get_ipa_idnsallowtransfer(self):
|
||||
+ def get_ipa_idnsallowtransfer(self, **kwargs):
|
||||
if self.ipa_params.allow_transfer is not None:
|
||||
error_msg = "Invalid ip_address for DNS allow_transfer: %s"
|
||||
self.validate_ips(self.ipa_params.allow_transfer, error_msg)
|
||||
|
||||
return (";".join(self.ipa_params.allow_transfer) or "none") + ";"
|
||||
|
||||
- def get_ipa_idnsallowquery(self):
|
||||
+ def get_ipa_idnsallowquery(self, **kwargs):
|
||||
if self.ipa_params.allow_query is not None:
|
||||
error_msg = "Invalid ip_address for DNS allow_query: %s"
|
||||
self.validate_ips(self.ipa_params.allow_query, error_msg)
|
||||
@@ -334,81 +334,89 @@ class DNSZoneModule(FreeIPABaseModule):
|
||||
|
||||
return ".".join((name, domain))
|
||||
|
||||
- def get_ipa_idnssoarname(self):
|
||||
+ def get_ipa_idnssoarname(self, **kwargs):
|
||||
if self.ipa_params.admin_email is not None:
|
||||
return DNSName(
|
||||
self._replace_at_symbol_in_rname(self.ipa_params.admin_email)
|
||||
)
|
||||
|
||||
- def get_ipa_idnssoamname(self):
|
||||
+ def get_ipa_idnssoamname(self, **kwargs):
|
||||
if self.ipa_params.name_server is not None:
|
||||
return DNSName(self.ipa_params.name_server)
|
||||
|
||||
- def get_ipa_skip_overlap_check(self):
|
||||
- if not self.zone and self.ipa_params.skip_overlap_check is not None:
|
||||
+ def get_ipa_skip_overlap_check(self, **kwargs):
|
||||
+ zone = kwargs.get('zone')
|
||||
+ if not zone and self.ipa_params.skip_overlap_check is not None:
|
||||
return self.ipa_params.skip_overlap_check
|
||||
|
||||
- def get_ipa_skip_nameserver_check(self):
|
||||
- if not self.zone and self.ipa_params.skip_nameserver_check is not None:
|
||||
+ def get_ipa_skip_nameserver_check(self, **kwargs):
|
||||
+ zone = kwargs.get('zone')
|
||||
+ if not zone and self.ipa_params.skip_nameserver_check is not None:
|
||||
return self.ipa_params.skip_nameserver_check
|
||||
|
||||
def get_zone(self, zone_name):
|
||||
get_zone_args = {"idnsname": zone_name, "all": True}
|
||||
response = self.api_command("dnszone_find", args=get_zone_args)
|
||||
|
||||
+ zone = None
|
||||
+ is_zone_active = False
|
||||
+
|
||||
if response["count"] == 1:
|
||||
- self.zone = response["result"][0]
|
||||
- self.is_zone_active = self.zone.get("idnszoneactive") == ["TRUE"]
|
||||
- return self.zone
|
||||
+ zone = response["result"][0]
|
||||
+ is_zone_active = zone.get("idnszoneactive") == ["TRUE"]
|
||||
|
||||
- # Zone doesn't exist yet
|
||||
- self.zone = None
|
||||
- self.is_zone_active = False
|
||||
+ return zone, is_zone_active
|
||||
+
|
||||
+ def get_zone_names(self):
|
||||
+ if len(self.ipa_params.name) > 1 and self.ipa_params.state != "absent":
|
||||
+ self.fail_json(
|
||||
+ msg=("Please provide a single name. Multiple values for 'name'"
|
||||
+ "can only be supplied for state 'absent'.")
|
||||
+ )
|
||||
|
||||
- @property
|
||||
- def zone_name(self):
|
||||
return self.ipa_params.name
|
||||
|
||||
def define_ipa_commands(self):
|
||||
- # Look for existing zone in IPA
|
||||
- self.get_zone(self.zone_name)
|
||||
- args = self.get_ipa_command_args()
|
||||
- just_added = False
|
||||
-
|
||||
- if self.ipa_params.state in ["present", "enabled", "disabled"]:
|
||||
- if not self.zone:
|
||||
- # Since the zone doesn't exist we just create it
|
||||
- # with given args
|
||||
- self.add_ipa_command("dnszone_add", self.zone_name, args)
|
||||
- self.is_zone_active = True
|
||||
- just_added = True
|
||||
-
|
||||
- else:
|
||||
- # Zone already exist so we need to verify if given args
|
||||
- # matches the current config. If not we updated it.
|
||||
- if self.require_ipa_attrs_change(args, self.zone):
|
||||
- self.add_ipa_command("dnszone_mod", self.zone_name, args)
|
||||
-
|
||||
- if self.ipa_params.state == "enabled" and not self.is_zone_active:
|
||||
- self.add_ipa_command("dnszone_enable", self.zone_name)
|
||||
-
|
||||
- if self.ipa_params.state == "disabled" and self.is_zone_active:
|
||||
- self.add_ipa_command("dnszone_disable", self.zone_name)
|
||||
-
|
||||
- if self.ipa_params.state == "absent":
|
||||
- if self.zone:
|
||||
- self.add_ipa_command("dnszone_del", self.zone_name)
|
||||
-
|
||||
- # Due to a bug in FreeIPA dnszone-add won't set
|
||||
- # SOA Serial. The good news is that dnszone-mod does the job.
|
||||
- # See: https://pagure.io/freeipa/issue/8227
|
||||
- # Because of that, if the zone was just added with a given serial
|
||||
- # we run mod just after to workaround the bug
|
||||
- if just_added and self.ipa_params.serial is not None:
|
||||
- args = {
|
||||
- "idnssoaserial": self.ipa_params.serial,
|
||||
- }
|
||||
- self.add_ipa_command("dnszone_mod", self.zone_name, args)
|
||||
+ for zone_name in self.get_zone_names():
|
||||
+ # Look for existing zone in IPA
|
||||
+ zone, is_zone_active = self.get_zone(zone_name)
|
||||
+ args = self.get_ipa_command_args(zone=zone)
|
||||
+ just_added = False
|
||||
+
|
||||
+ if self.ipa_params.state in ["present", "enabled", "disabled"]:
|
||||
+ if not zone:
|
||||
+ # Since the zone doesn't exist we just create it
|
||||
+ # with given args
|
||||
+ self.add_ipa_command("dnszone_add", zone_name, args)
|
||||
+ is_zone_active = True
|
||||
+ just_added = True
|
||||
+
|
||||
+ else:
|
||||
+ # Zone already exist so we need to verify if given args
|
||||
+ # matches the current config. If not we updated it.
|
||||
+ if self.require_ipa_attrs_change(args, zone):
|
||||
+ self.add_ipa_command("dnszone_mod", zone_name, args)
|
||||
+
|
||||
+ if self.ipa_params.state == "enabled" and not is_zone_active:
|
||||
+ self.add_ipa_command("dnszone_enable", zone_name)
|
||||
+
|
||||
+ if self.ipa_params.state == "disabled" and is_zone_active:
|
||||
+ self.add_ipa_command("dnszone_disable", zone_name)
|
||||
+
|
||||
+ if self.ipa_params.state == "absent":
|
||||
+ if zone:
|
||||
+ self.add_ipa_command("dnszone_del", zone_name)
|
||||
+
|
||||
+ # Due to a bug in FreeIPA dnszone-add won't set
|
||||
+ # SOA Serial. The good news is that dnszone-mod does the job.
|
||||
+ # See: https://pagure.io/freeipa/issue/8227
|
||||
+ # Because of that, if the zone was just added with a given serial
|
||||
+ # we run mod just after to workaround the bug
|
||||
+ if just_added and self.ipa_params.serial is not None:
|
||||
+ args = {
|
||||
+ "idnssoaserial": self.ipa_params.serial,
|
||||
+ }
|
||||
+ self.add_ipa_command("dnszone_mod", zone_name, args)
|
||||
|
||||
|
||||
def get_argument_spec():
|
||||
@@ -426,7 +434,7 @@ def get_argument_spec():
|
||||
ipaadmin_principal=dict(type="str", default="admin"),
|
||||
ipaadmin_password=dict(type="str", required=False, no_log=True),
|
||||
name=dict(
|
||||
- type="str", default=None, required=True, aliases=["zone_name"]
|
||||
+ type="list", default=None, required=True, aliases=["zone_name"]
|
||||
),
|
||||
forwarders=dict(
|
||||
type="list",
|
||||
diff --git a/tests/dnszone/test_dnszone.yml b/tests/dnszone/test_dnszone.yml
|
||||
index f7bd1f0..bd820df 100644
|
||||
--- a/tests/dnszone/test_dnszone.yml
|
||||
+++ b/tests/dnszone/test_dnszone.yml
|
||||
@@ -149,3 +149,40 @@
|
||||
forwarders: []
|
||||
register: result
|
||||
failed_when: not result.changed
|
||||
+
|
||||
+ - name: Create zones test1
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: test1.testzone.local
|
||||
+
|
||||
+ - name: Create zones test2
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: test2.testzone.local
|
||||
+
|
||||
+ - name: Create zones test3
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: test3.testzone.local
|
||||
+
|
||||
+ - name: Ensure multiple zones are absent
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - test1.testzone.local
|
||||
+ - test2.testzone.local
|
||||
+ - test3.testzone.local
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Ensure multiple zones are absent, again
|
||||
+ ipadnszone:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - test1.testzone.local
|
||||
+ - test2.testzone.local
|
||||
+ - test3.testzone.local
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,628 +0,0 @@
|
||||
# Skipping 3ab575bcac310166e7d29c5a5349d90482f4e629 as it is reorganizing
|
||||
# service module test test_service.yml and
|
||||
# test_service_without_skip_host_check.yml
|
||||
|
||||
From b5e93c705fc56f6592121aa09bfb9f6dce5cee35 Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Tue, 11 Aug 2020 16:23:15 -0300
|
||||
Subject: [PATCH] Fix `allow_retrieve_keytab_host` in service module.
|
||||
|
||||
The attribute `allow_retrieve_keytab_host` was not working due to
|
||||
wrong processing of the input and verification if the values should
|
||||
be updated. Both the issues are fixed by this change.
|
||||
|
||||
Tests were added to better verify service keytab members.
|
||||
---
|
||||
plugins/modules/ipaservice.py | 4 +-
|
||||
tests/service/env_cleanup.yml | 68 +++++
|
||||
tests/service/env_setup.yml | 73 +++++
|
||||
tests/service/env_vars.yml | 15 +
|
||||
tests/service/test_service_keytab.yml | 397 ++++++++++++++++++++++++++
|
||||
5 files changed, 555 insertions(+), 2 deletions(-)
|
||||
create mode 100644 tests/service/env_cleanup.yml
|
||||
create mode 100644 tests/service/env_setup.yml
|
||||
create mode 100644 tests/service/env_vars.yml
|
||||
create mode 100644 tests/service/test_service_keytab.yml
|
||||
|
||||
diff --git a/plugins/modules/ipaservice.py b/plugins/modules/ipaservice.py
|
||||
index b0d2535..8bc390d 100644
|
||||
--- a/plugins/modules/ipaservice.py
|
||||
+++ b/plugins/modules/ipaservice.py
|
||||
@@ -460,7 +460,7 @@ def main():
|
||||
allow_retrieve_keytab_group = module_params_get(
|
||||
ansible_module, "allow_retrieve_keytab_group")
|
||||
allow_retrieve_keytab_host = module_params_get(
|
||||
- ansible_module, "allow_create_keytab_host")
|
||||
+ ansible_module, "allow_retrieve_keytab_host")
|
||||
allow_retrieve_keytab_hostgroup = module_params_get(
|
||||
ansible_module, "allow_retrieve_keytab_hostgroup")
|
||||
delete_continue = module_params_get(ansible_module, "delete_continue")
|
||||
@@ -727,7 +727,7 @@ def main():
|
||||
# Allow retrieve keytab
|
||||
if len(allow_retrieve_keytab_user_add) > 0 or \
|
||||
len(allow_retrieve_keytab_group_add) > 0 or \
|
||||
- len(allow_retrieve_keytab_hostgroup_add) > 0 or \
|
||||
+ len(allow_retrieve_keytab_host_add) > 0 or \
|
||||
len(allow_retrieve_keytab_hostgroup_add) > 0:
|
||||
commands.append(
|
||||
[name, "service_allow_retrieve_keytab",
|
||||
diff --git a/tests/service/env_cleanup.yml b/tests/service/env_cleanup.yml
|
||||
new file mode 100644
|
||||
index 0000000..f96a75b
|
||||
--- /dev/null
|
||||
+++ b/tests/service/env_cleanup.yml
|
||||
@@ -0,0 +1,68 @@
|
||||
+---
|
||||
+# Cleanup tasks for the service module tests.
|
||||
+- name: Ensure services are absent.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - "HTTP/{{ svc_fqdn }}"
|
||||
+ - "HTTP/{{ nohost_fqdn }}"
|
||||
+ - HTTP/svc.ihavenodns.info
|
||||
+ - HTTP/no.idontexist.local
|
||||
+ - "cifs/{{ host1_fqdn }}"
|
||||
+ state: absent
|
||||
+
|
||||
+- name: Ensure host "{{ svc_fqdn }}" is absent
|
||||
+ ipahost:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "{{ svc_fqdn }}"
|
||||
+ update_dns: yes
|
||||
+ state: absent
|
||||
+
|
||||
+- name: Ensure host is absent
|
||||
+ ipahost:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ - "{{ nohost_fqdn }}"
|
||||
+ - svc.ihavenodns.info
|
||||
+ update_dns: no
|
||||
+ state: absent
|
||||
+
|
||||
+- name: Ensure testing users are absent.
|
||||
+ ipauser:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ state: absent
|
||||
+
|
||||
+- name: Ensure testing groups are absent.
|
||||
+ ipagroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ state: absent
|
||||
+
|
||||
+- name: Ensure testing hostgroup hostgroup01 is absent.
|
||||
+ ipagroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - hostgroup01
|
||||
+ state: absent
|
||||
+
|
||||
+- name: Ensure testing hostgroup hostgroup02 is absent.
|
||||
+ ipagroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - hostgroup02
|
||||
+ state: absent
|
||||
+
|
||||
+- name: Remove IP address for "nohost" host.
|
||||
+ ipadnsrecord:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ zone_name: "{{ test_domain }}."
|
||||
+ name: nohost
|
||||
+ del_all: yes
|
||||
+ state: absent
|
||||
diff --git a/tests/service/env_setup.yml b/tests/service/env_setup.yml
|
||||
new file mode 100644
|
||||
index 0000000..309cfc0
|
||||
--- /dev/null
|
||||
+++ b/tests/service/env_setup.yml
|
||||
@@ -0,0 +1,73 @@
|
||||
+# Setup environment for service module tests.
|
||||
+---
|
||||
+- name: Setup variables and facts.
|
||||
+ include_tasks: env_vars.yml
|
||||
+
|
||||
+# Cleanup before setup.
|
||||
+- name: Cleanup test environment.
|
||||
+ include_tasks: env_cleanup.yml
|
||||
+
|
||||
+- name: Add IP address for "nohost" host.
|
||||
+ ipadnsrecord:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ zone_name: "{{ test_domain }}."
|
||||
+ name: nohost
|
||||
+ a_ip_address: "{{ ipv4_prefix + '.100' }}"
|
||||
+
|
||||
+- name: Add hosts for tests.
|
||||
+ ipahost:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ hosts:
|
||||
+ - name: "{{ host1_fqdn }}"
|
||||
+ ip_address: "{{ ipv4_prefix + '.101' }}"
|
||||
+ - name: "{{ host2_fqdn }}"
|
||||
+ ip_address: "{{ ipv4_prefix + '.102' }}"
|
||||
+ - name: "{{ svc_fqdn }}"
|
||||
+ ip_address: "{{ ipv4_prefix + '.201' }}"
|
||||
+ - name: svc.ihavenodns.info
|
||||
+ force: yes
|
||||
+ update_dns: yes
|
||||
+
|
||||
+- name: Ensure testing user user01 is present.
|
||||
+ ipauser:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: user01
|
||||
+ first: user01
|
||||
+ last: last
|
||||
+
|
||||
+- name: Ensure testing user user02 is present.
|
||||
+ ipauser:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: user02
|
||||
+ first: user02
|
||||
+ last: last
|
||||
+
|
||||
+- name: Ensure testing group group01 is present.
|
||||
+ ipagroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: group01
|
||||
+
|
||||
+- name: Ensure testing group group02 is present.
|
||||
+ ipagroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: group02
|
||||
+
|
||||
+- name: Ensure testing hostgroup hostgroup01 is present.
|
||||
+ ipahostgroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: hostgroup01
|
||||
+
|
||||
+- name: Ensure testing hostgroup hostgroup02 is present.
|
||||
+ ipahostgroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: hostgroup02
|
||||
+
|
||||
+- name: Ensure services are absent.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name:
|
||||
+ - "HTTP/{{ svc_fqdn }}"
|
||||
+ - "HTTP/{{ nohost_fqdn }}"
|
||||
+ - HTTP/svc.ihavenodns.info
|
||||
+ - HTTP/no.idontexist.info
|
||||
+ state: absent
|
||||
diff --git a/tests/service/env_vars.yml b/tests/service/env_vars.yml
|
||||
new file mode 100644
|
||||
index 0000000..eb53c7a
|
||||
--- /dev/null
|
||||
+++ b/tests/service/env_vars.yml
|
||||
@@ -0,0 +1,15 @@
|
||||
+---
|
||||
+ - name: Get Domain from server name
|
||||
+ set_fact:
|
||||
+ test_domain: "{{ ansible_fqdn.split('.')[1:] | join('.') }}"
|
||||
+
|
||||
+ - name: Set host1, host2 and svc hosts fqdn
|
||||
+ set_fact:
|
||||
+ host1_fqdn: "{{ 'host1.' + test_domain }}"
|
||||
+ host2_fqdn: "{{ 'host2.' + test_domain }}"
|
||||
+ svc_fqdn: "{{ 'svc.' + test_domain }}"
|
||||
+ nohost_fqdn: "{{ 'nohost.' + test_domain }}"
|
||||
+
|
||||
+ - name: Get IPv4 address prefix from server node
|
||||
+ set_fact:
|
||||
+ ipv4_prefix: "{{ ansible_default_ipv4.address.split('.')[:-1] | join('.') }}"
|
||||
diff --git a/tests/service/test_service_keytab.yml b/tests/service/test_service_keytab.yml
|
||||
new file mode 100644
|
||||
index 0000000..0918802
|
||||
--- /dev/null
|
||||
+++ b/tests/service/test_service_keytab.yml
|
||||
@@ -0,0 +1,397 @@
|
||||
+---
|
||||
+- name: Test service
|
||||
+ hosts: ipaserver
|
||||
+ become: yes
|
||||
+
|
||||
+ tasks:
|
||||
+ # setup
|
||||
+ - name: Setup test envirnoment.
|
||||
+ include_tasks: env_setup.yml
|
||||
+
|
||||
+ # Add service to test keytab create/retrieve attributes.
|
||||
+ - name: Ensure test service is present
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ pac_type:
|
||||
+ - MS-PAC
|
||||
+ - PAD
|
||||
+ auth_ind: otp
|
||||
+ force: yes
|
||||
+ requires_pre_auth: yes
|
||||
+ ok_as_delegate: no
|
||||
+ ok_to_auth_as_delegate: no
|
||||
+
|
||||
+ # tests
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_user:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_user:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_user:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_user:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for group.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_group:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for group, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_group:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for group.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_group:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for group, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_group:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for host.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_host:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for host, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_host:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for host.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_host:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for host, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_host:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for hostgroup.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_hostgroup:
|
||||
+ - hostgroup01
|
||||
+ - hostgroup02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for hostgroup, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_hostgroup:
|
||||
+ - hostgroup01
|
||||
+ - hostgroup02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for hostgroup.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_hostgroup:
|
||||
+ - hostgroup01
|
||||
+ - hostgroup02
|
||||
+ state: absent
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for hostgroup, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_create_keytab_hostgroup:
|
||||
+ - hostgroup01
|
||||
+ - hostgroup02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_user:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_user:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_user:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_user:
|
||||
+ - user01
|
||||
+ - user02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for group.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_group:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for group, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_group:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for group.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_group:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for group, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_group:
|
||||
+ - group01
|
||||
+ - group02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for host.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_host:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for host, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_host:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for host.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_host:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for host, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_host:
|
||||
+ - "{{ host1_fqdn }}"
|
||||
+ - "{{ host2_fqdn }}"
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for hostgroup.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_hostgroup:
|
||||
+ - hostgroup01
|
||||
+ - hostgroup02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for hostgroup, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_hostgroup:
|
||||
+ - hostgroup01
|
||||
+ - hostgroup02
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for hostgroup.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_hostgroup:
|
||||
+ - hostgroup01
|
||||
+ - hostgroup02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for hostgroup, again.
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "HTTP/{{ svc_fqdn }}"
|
||||
+ allow_retrieve_keytab_hostgroup:
|
||||
+ - hostgroup01
|
||||
+ - hostgroup02
|
||||
+ action: member
|
||||
+ state: absent
|
||||
+ register: result
|
||||
+ failed_when: result.changed
|
||||
+
|
||||
+ # cleanup
|
||||
+ - name: Clean-up envirnoment.
|
||||
+ include_tasks: env_cleanup.yml
|
||||
--
|
||||
2.26.2
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,40 +0,0 @@
|
||||
From 563a03d94bfc29799ea964dab61a1ba35818b9bb Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Oliveira Campos <seocam@seocam.com>
|
||||
Date: Thu, 30 Jul 2020 09:50:24 -0300
|
||||
Subject: [PATCH] Fixed error msgs on FreeIPABaseModule subclasses
|
||||
|
||||
When a fail_json is called a SystemExit exeception is raised.
|
||||
Since the FreeIPABaseModule has an internal context manager to deal
|
||||
with exceptions this ContextManager captures the SystemExit. After
|
||||
dealing destroying the kinit session the SystemExit must be raised again
|
||||
to allow the fail_json to work properly.
|
||||
---
|
||||
plugins/module_utils/ansible_freeipa_module.py | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
|
||||
index 122ea2e..a59e6e2 100644
|
||||
--- a/plugins/module_utils/ansible_freeipa_module.py
|
||||
+++ b/plugins/module_utils/ansible_freeipa_module.py
|
||||
@@ -610,12 +610,15 @@ class FreeIPABaseModule(AnsibleModule):
|
||||
exit the module with proper arguments.
|
||||
|
||||
"""
|
||||
- if exc_val:
|
||||
- self.fail_json(msg=str(exc_val))
|
||||
-
|
||||
# TODO: shouldn't we also disconnect from api backend?
|
||||
temp_kdestroy(self.ccache_dir, self.ccache_name)
|
||||
|
||||
+ if exc_type == SystemExit:
|
||||
+ raise
|
||||
+
|
||||
+ if exc_val:
|
||||
+ self.fail_json(msg=str(exc_val))
|
||||
+
|
||||
self.exit_json(changed=self.changed, user=self.exit_args)
|
||||
|
||||
def get_command_errors(self, command, result):
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,327 +0,0 @@
|
||||
From 3e5c54d4fdb10deda9b7e4deaf2c537b132711c9 Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Fri, 31 Jul 2020 11:30:51 -0300
|
||||
Subject: [PATCH] Fix identification of existing vault type.
|
||||
|
||||
In some scenarios, the value of the vault type is returned as a tuple,
|
||||
rather than a string, this made some changes to existing vault to fail.
|
||||
With this change, the vault type is correctly retrieved, if it was not
|
||||
provided by the user.
|
||||
---
|
||||
plugins/modules/ipavault.py | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/plugins/modules/ipavault.py b/plugins/modules/ipavault.py
|
||||
index 6a3c73e..8562ff7 100644
|
||||
--- a/plugins/modules/ipavault.py
|
||||
+++ b/plugins/modules/ipavault.py
|
||||
@@ -494,8 +494,10 @@ def check_encryption_params(module, state, action, vault_type, salt,
|
||||
new_password, new_password_file, res_find):
|
||||
vault_type_invalid = []
|
||||
|
||||
- if res_find is not None:
|
||||
+ if vault_type is None and res_find is not None:
|
||||
vault_type = res_find['ipavaulttype']
|
||||
+ if isinstance(vault_type, (tuple, list)):
|
||||
+ vault_type = vault_type[0]
|
||||
|
||||
if vault_type == "standard":
|
||||
vault_type_invalid = ['public_key', 'public_key_file', 'password',
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From d52364bac923f2935b948882d5825e7488b0e9cf Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Fri, 31 Jul 2020 11:32:36 -0300
|
||||
Subject: [PATCH] Fix random salt generation.
|
||||
|
||||
The generation of a random salt, when one was not provided, was in the
|
||||
wrong place and being generated too late to be used properly. Also, the
|
||||
generation of the value was duplicated.
|
||||
---
|
||||
plugins/modules/ipavault.py | 13 +++++--------
|
||||
1 file changed, 5 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/plugins/modules/ipavault.py b/plugins/modules/ipavault.py
|
||||
index 8562ff7..dffd972 100644
|
||||
--- a/plugins/modules/ipavault.py
|
||||
+++ b/plugins/modules/ipavault.py
|
||||
@@ -768,7 +768,12 @@ def main():
|
||||
commands.append([name, "vault_mod_internal", args])
|
||||
|
||||
else:
|
||||
+ if vault_type == 'symmetric' \
|
||||
+ and 'ipavaultsalt' not in args:
|
||||
+ args['ipavaultsalt'] = os.urandom(32)
|
||||
+
|
||||
commands.append([name, "vault_add_internal", args])
|
||||
+
|
||||
if vault_type != 'standard' and vault_data is None:
|
||||
vault_data = ''
|
||||
|
||||
@@ -826,14 +831,6 @@ def main():
|
||||
commands.append(
|
||||
[name, 'vault_remove_owner', owner_del_args])
|
||||
|
||||
- if vault_type == 'symmetric' \
|
||||
- and 'ipavaultsalt' not in args:
|
||||
- args['ipavaultsalt'] = os.urandom(32)
|
||||
-
|
||||
- if vault_type == 'symmetric' \
|
||||
- and 'ipavaultsalt' not in args:
|
||||
- args['ipavaultsalt'] = os.urandom(32)
|
||||
-
|
||||
elif action in "member":
|
||||
# Add users and groups
|
||||
if any([users, groups, services]):
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From daee6a6c744a740329ca231a277229567619e10c Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Fri, 31 Jul 2020 11:33:47 -0300
|
||||
Subject: [PATCH] Fix verification of parameters for modifying `salt`
|
||||
attribute.
|
||||
|
||||
When modifying an existing vault to change the value of `salt`, the
|
||||
password must also change. It is fine to "change" the password to the
|
||||
same value, thus only changing the salt value.
|
||||
---
|
||||
plugins/modules/ipavault.py | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/plugins/modules/ipavault.py b/plugins/modules/ipavault.py
|
||||
index dffd972..a608e64 100644
|
||||
--- a/plugins/modules/ipavault.py
|
||||
+++ b/plugins/modules/ipavault.py
|
||||
@@ -517,6 +517,16 @@ def check_encryption_params(module, state, action, vault_type, salt,
|
||||
module.fail_json(
|
||||
msg="Cannot modify password of inexistent vault.")
|
||||
|
||||
+ if (
|
||||
+ salt is not None
|
||||
+ and not(
|
||||
+ any([password, password_file])
|
||||
+ and any([new_password, new_password_file])
|
||||
+ )
|
||||
+ ):
|
||||
+ module.fail_json(
|
||||
+ msg="Vault `salt` can only change when changing the password.")
|
||||
+
|
||||
if vault_type == "asymmetric":
|
||||
vault_type_invalid = [
|
||||
'password', 'password_file', 'new_password', 'new_password_file'
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From 4ef4e706b79fdbb43e462b1a7130fc2cad5894b2 Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Fri, 31 Jul 2020 11:42:13 -0300
|
||||
Subject: [PATCH] Modify tests to verify password was changed correctly.
|
||||
|
||||
Modify and add tests to verify that a password change has the correct
|
||||
effect on ipavault.
|
||||
---
|
||||
tests/vault/test_vault_symmetric.yml | 36 ++++++++++++++++++----------
|
||||
1 file changed, 23 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/tests/vault/test_vault_symmetric.yml b/tests/vault/test_vault_symmetric.yml
|
||||
index bedc221..9294331 100644
|
||||
--- a/tests/vault/test_vault_symmetric.yml
|
||||
+++ b/tests/vault/test_vault_symmetric.yml
|
||||
@@ -178,6 +178,15 @@
|
||||
register: result
|
||||
failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
+ - name: Retrieve data from symmetric vault, with wrong password.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ password: SomeWRONGpassword
|
||||
+ state: retrieved
|
||||
+ register: result
|
||||
+ failed_when: not result.failed or "Invalid credentials" not in result.msg
|
||||
+
|
||||
- name: Change vault password.
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -187,43 +196,44 @@
|
||||
register: result
|
||||
failed_when: not result.changed
|
||||
|
||||
- - name: Retrieve data from symmetric vault, with wrong password.
|
||||
+ - name: Retrieve data from symmetric vault, with new password.
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: symvault
|
||||
- password: SomeVAULTpassword
|
||||
+ password: SomeNEWpassword
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: not result.failed or "Invalid credentials" not in result.msg
|
||||
+ failed_when: result.data != 'Hello World.' or result.changed
|
||||
|
||||
- - name: Change vault password, with wrong `old_password`.
|
||||
+ - name: Retrieve data from symmetric vault, with old password.
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: symvault
|
||||
password: SomeVAULTpassword
|
||||
- new_password: SomeNEWpassword
|
||||
+ state: retrieved
|
||||
register: result
|
||||
failed_when: not result.failed or "Invalid credentials" not in result.msg
|
||||
|
||||
- - name: Retrieve data from symmetric vault, with new password.
|
||||
+ - name: Change symmetric vault salt, changing password
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: symvault
|
||||
password: SomeNEWpassword
|
||||
- state: retrieved
|
||||
+ new_password: SomeVAULTpassword
|
||||
+ salt: AAAAAAAAAAAAAAAAAAAAAAA=
|
||||
register: result
|
||||
- failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
+ failed_when: not result.changed
|
||||
|
||||
- - name: Try to add vault with multiple passwords.
|
||||
+ - name: Change symmetric vault salt, without changing password
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
- name: inexistentvault
|
||||
+ name: symvault
|
||||
password: SomeVAULTpassword
|
||||
- password_file: "{{ ansible_env.HOME }}/password.txt"
|
||||
+ new_password: SomeVAULTpassword
|
||||
+ salt: MTIzNDU2Nzg5MDEyMzQ1Ngo=
|
||||
register: result
|
||||
- failed_when: not result.failed or "parameters are mutually exclusive" not in result.msg
|
||||
+ failed_when: not result.changed
|
||||
|
||||
- - name: Try to add vault with multiple new passwords.
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: inexistentvault
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From 8ca282e276477b52d0850d4c01feb3d8e7a5be6d Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Fri, 31 Jul 2020 11:44:33 -0300
|
||||
Subject: [PATCH] Modified and added tests to verify correct `salt` update
|
||||
behavior.
|
||||
|
||||
---
|
||||
tests/vault/test_vault_symmetric.yml | 35 ++++++++++++++++++++++++----
|
||||
1 file changed, 31 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/tests/vault/test_vault_symmetric.yml b/tests/vault/test_vault_symmetric.yml
|
||||
index 9294331..1604a01 100644
|
||||
--- a/tests/vault/test_vault_symmetric.yml
|
||||
+++ b/tests/vault/test_vault_symmetric.yml
|
||||
@@ -234,14 +234,41 @@
|
||||
register: result
|
||||
failed_when: not result.changed
|
||||
|
||||
+ - name: Try to change symmetric vault salt, without providing any password
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
- name: inexistentvault
|
||||
- password: SomeVAULTpassword
|
||||
+ name: symvault
|
||||
+ salt: MTIzNDU2Nzg5MDEyMzQ1Ngo=
|
||||
+ register: result
|
||||
+ failed_when: not result.failed and "Vault `salt` can only change when changing the password." not in result.msg
|
||||
+
|
||||
+ - name: Try to change symmetric vault salt, without providing `password`
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ salt: MTIzNDU2Nzg5MDEyMzQ1Ngo=
|
||||
new_password: SomeVAULTpassword
|
||||
- new_password_file: "{{ ansible_env.HOME }}/password.txt"
|
||||
register: result
|
||||
- failed_when: not result.failed or "parameters are mutually exclusive" not in result.msg
|
||||
+ failed_when: not result.failed and "Vault `salt` can only change when changing the password." not in result.msg
|
||||
+
|
||||
+ - name: Try to change symmetric vault salt, without providing `new_password`
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ salt: MTIzNDU2Nzg5MDEyMzQ1Ngo=
|
||||
+ password: SomeVAULTpassword
|
||||
+ register: result
|
||||
+ failed_when: not result.failed and "Vault `salt` can only change when changing the password." not in result.msg
|
||||
+
|
||||
+ - name: Try to change symmetric vault salt, using wrong password.
|
||||
+ ipavault:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: symvault
|
||||
+ password: SomeWRONGpassword
|
||||
+ new_password: SomeWRONGpassword
|
||||
+ salt: MDEyMzQ1Njc4OTAxMjM0NQo=
|
||||
+ register: result
|
||||
+ failed_when: not result.failed
|
||||
|
||||
- name: Ensure symmetric vault is absent
|
||||
ipavault:
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From 3c2700f68beade3513e0e44415d8eb4fb23026e8 Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Fri, 14 Aug 2020 10:43:30 -0300
|
||||
Subject: [PATCH] Fixed Vault return value usage from `data` to `vault.data`.
|
||||
|
||||
A test was failing due to use of old ipavault module return structure
|
||||
and some places on the documentation were alse referring to it. All
|
||||
ocurrences were fixed.
|
||||
---
|
||||
README-vault.md | 2 +-
|
||||
plugins/modules/ipavault.py | 2 +-
|
||||
tests/vault/test_vault_symmetric.yml | 2 +-
|
||||
3 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/README-vault.md b/README-vault.md
|
||||
index 91d311d..e7a31a2 100644
|
||||
--- a/README-vault.md
|
||||
+++ b/README-vault.md
|
||||
@@ -197,7 +197,7 @@ Example playbook to make sure vault is absent:
|
||||
state: absent
|
||||
register: result
|
||||
- debug:
|
||||
- msg: "{{ result.data }}"
|
||||
+ msg: "{{ result.vault.data }}"
|
||||
```
|
||||
|
||||
Variables
|
||||
diff --git a/plugins/modules/ipavault.py b/plugins/modules/ipavault.py
|
||||
index a608e64..8060976 100644
|
||||
--- a/plugins/modules/ipavault.py
|
||||
+++ b/plugins/modules/ipavault.py
|
||||
@@ -243,7 +243,7 @@ EXAMPLES = """
|
||||
state: retrieved
|
||||
register: result
|
||||
- debug:
|
||||
- msg: "{{ result.data }}"
|
||||
+ msg: "{{ result.vault.data }}"
|
||||
|
||||
# Change password of a symmetric vault
|
||||
- ipavault:
|
||||
diff --git a/tests/vault/test_vault_symmetric.yml b/tests/vault/test_vault_symmetric.yml
|
||||
index 1604a01..5394c71 100644
|
||||
--- a/tests/vault/test_vault_symmetric.yml
|
||||
+++ b/tests/vault/test_vault_symmetric.yml
|
||||
@@ -203,7 +203,7 @@
|
||||
password: SomeNEWpassword
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Retrieve data from symmetric vault, with old password.
|
||||
ipavault:
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,112 +0,0 @@
|
||||
From e57e4908f936c524085fb5853fe4493c7711ab3f Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Thu, 25 Jun 2020 16:26:30 -0300
|
||||
Subject: [PATCH] Fixes service disable when service has no certificates
|
||||
attached.
|
||||
|
||||
Services without certificates, but with keytabs were not being
|
||||
disabled. This change allows execution of service_disable if
|
||||
there is a certificate or if has_keytab is true.
|
||||
|
||||
A new test was added to verify the issue:
|
||||
|
||||
tests/service/test_service_disable.yml
|
||||
---
|
||||
plugins/modules/ipaservice.py | 8 +--
|
||||
tests/service/test_service_disable.yml | 68 ++++++++++++++++++++++++++
|
||||
2 files changed, 73 insertions(+), 3 deletions(-)
|
||||
create mode 100644 tests/service/test_service_disable.yml
|
||||
|
||||
diff --git a/plugins/modules/ipaservice.py b/plugins/modules/ipaservice.py
|
||||
index 23a0d6b3..b0d25355 100644
|
||||
--- a/plugins/modules/ipaservice.py
|
||||
+++ b/plugins/modules/ipaservice.py
|
||||
@@ -812,9 +812,11 @@ def main():
|
||||
|
||||
elif state == "disabled":
|
||||
if action == "service":
|
||||
- if res_find is not None and \
|
||||
- len(res_find.get('usercertificate', [])) > 0:
|
||||
- commands.append([name, 'service_disable', {}])
|
||||
+ if res_find is not None:
|
||||
+ has_cert = bool(res_find.get('usercertificate'))
|
||||
+ has_keytab = res_find.get('has_keytab', False)
|
||||
+ if has_cert or has_keytab:
|
||||
+ commands.append([name, 'service_disable', {}])
|
||||
else:
|
||||
ansible_module.fail_json(
|
||||
msg="Invalid action '%s' for state '%s'" %
|
||||
diff --git a/tests/service/test_service_disable.yml b/tests/service/test_service_disable.yml
|
||||
new file mode 100644
|
||||
index 00000000..3b4a88fb
|
||||
--- /dev/null
|
||||
+++ b/tests/service/test_service_disable.yml
|
||||
@@ -0,0 +1,68 @@
|
||||
+---
|
||||
+- name: Playbook to manage IPA service.
|
||||
+ hosts: ipaserver
|
||||
+ become: yes
|
||||
+ gather_facts: yes
|
||||
+
|
||||
+ tasks:
|
||||
+ - name: Ensure service is absent
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "mysvc1/{{ ansible_fqdn }}"
|
||||
+
|
||||
+ - name: Ensure service is present
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "mysvc1/{{ ansible_fqdn }}"
|
||||
+ certificate:
|
||||
+ - MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVGFYpHVkcDfVnNInE1Y/pFciegdzqTjMwUWlRL4Zt3u96GhaMLRbtk+OfEkzLUAhWBOwEraELJzMLJOMvjYF3C+TiGO7dStFLikZmccuSsSIXjnzIPwBXa8KvgRVRyGLoVvGbLJvmjfMXp0nIToTx/i74KF9S++WEes9H5ErJ99CDhLKFgq0amnvsgparYXhypHaRLnikn0vQINt55YoEd1s4KrvEcD2VdZkIMPbLRu2zFvMprF3cjQQG4LT9ggfEXNIPZ1nQWAnAsu7OJEkNF+E4Mkmpcxj9aGUVt5bsq1D+Tzj3GsidSX0nSNcZ2JltXRnL/5v63g5cZyE+nAgMBAAGjUzBRMB0GA1UdDgQWBBRV0j7JYukuH/r/t9+QeNlRLXDlEDAfBgNVHSMEGDAWgBRV0j7JYukuH/r/t9+QeNlRLXDlEDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCgVy1+1kNwHs5y1Zp0WjMWGCJC6/zw7FDG4OW5r2GJiCXZYdJ0UonY9ZtoVLJPrp2/DAv1m5DtnDhBYqicuPgLzEkOS1KdTi20Otm/J4yxLLrZC5W4x0XOeSVPXOJuQWfwQ5pPvKkn6WxYUYkGwIt1OH2nSMngkbami3CbSmKZOCpgQIiSlQeDJ8oGjWFMLDymYSHoVOIXHwNoooyEiaio3693l6noobyGv49zyCVLVR1DC7i6RJ186ql0av+D4vPoiF5mX7+sKC2E8xEj9uKQ5GTWRh59VnRBVC/SiMJ/H78tJnBAvoBwXxSEvj8Z3Kjm/BQqZfv4IBsA5yqV7MVq
|
||||
+ force: no
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Obtain keytab
|
||||
+ shell: ipa-getkeytab -s "{{ ansible_fqdn }}" -p "mysvc1/{{ ansible_fqdn }}" -k mysvc1.keytab
|
||||
+
|
||||
+ - name: Verify keytab
|
||||
+ shell: ipa service-find "mysvc1/{{ ansible_fqdn }}"
|
||||
+ register: result
|
||||
+ failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
|
||||
+
|
||||
+ - name: Ensure service is disabled
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "mysvc1/{{ ansible_fqdn }}"
|
||||
+ state: disabled
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Verify keytab
|
||||
+ shell: ipa service-find "mysvc1/{{ ansible_fqdn }}"
|
||||
+ register: result
|
||||
+ failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
|
||||
+
|
||||
+ - name: Obtain keytab
|
||||
+ shell: ipa-getkeytab -s "{{ ansible_fqdn }}" -p "mysvc1/{{ ansible_fqdn }}" -k mysvc1.keytab
|
||||
+
|
||||
+ - name: Verify keytab
|
||||
+ shell: ipa service-find "mysvc1/{{ ansible_fqdn }}"
|
||||
+ register: result
|
||||
+ failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
|
||||
+
|
||||
+ - name: Ensure service is disabled
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "mysvc1/{{ ansible_fqdn }}"
|
||||
+ state: disabled
|
||||
+ register: result
|
||||
+ failed_when: not result.changed
|
||||
+
|
||||
+ - name: Verify keytab
|
||||
+ shell: ipa service-find "mysvc1/{{ ansible_fqdn }}"
|
||||
+ register: result
|
||||
+ failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
|
||||
+
|
||||
+ - name: Ensure service is absent
|
||||
+ ipaservice:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: "mysvc1/{{ ansible_fqdn }}"
|
@ -1,300 +0,0 @@
|
||||
From e96ef4e98e523f20c25777308c093ebbff272b2d Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Wed, 5 Aug 2020 15:24:15 -0300
|
||||
Subject: [PATCH] Updated documentation for ipavault module in the source code.
|
||||
|
||||
This change fixes a wrong parameter name in the documentation of
|
||||
RESULT_VALUES, and also provide a correct YAML snippet to ensure
|
||||
presence of an asymmetric vault with a formatted private key.
|
||||
---
|
||||
plugins/modules/ipavault.py | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/plugins/modules/ipavault.py b/plugins/modules/ipavault.py
|
||||
index 46c6fcd..84645c7 100644
|
||||
--- a/plugins/modules/ipavault.py
|
||||
+++ b/plugins/modules/ipavault.py
|
||||
@@ -267,7 +267,7 @@ EXAMPLES = """
|
||||
username: user01
|
||||
description: An asymmetric vault
|
||||
vault_type: asymmetric
|
||||
- public_key:
|
||||
+ public_key: |
|
||||
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTR
|
||||
HTkFEQ0JpUUtCZ1FDdGFudjRkK3ptSTZ0T3ova1RXdGowY3AxRAowUENoYy8vR0pJMTUzTi
|
||||
9CN3UrN0h3SXlRVlZoNUlXZG1UcCtkWXYzd09yeVpPbzYvbHN5eFJaZ2pZRDRwQ3VGCjlxM
|
||||
@@ -303,7 +303,7 @@ EXAMPLES = """
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
-user:
|
||||
+data:
|
||||
description: The vault data.
|
||||
returned: If state is retrieved.
|
||||
type: string
|
||||
--
|
||||
2.26.2
|
||||
|
||||
From 7dd0b547c47b4fd617960490b8553a5036e3b30c Mon Sep 17 00:00:00 2001
|
||||
From: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
Date: Mon, 10 Aug 2020 16:02:09 -0300
|
||||
Subject: [PATCH] Modified return value for ipavault module.
|
||||
|
||||
The ipavault module was returning a single string value when retrieving
|
||||
data. To keep consistency with other modules, it should return a dict
|
||||
with the `data` variable in it.
|
||||
|
||||
This change modifies the result of ipavault to be a dict and also fixes
|
||||
relevant tests, examples and documentation.
|
||||
---
|
||||
README-vault.md | 5 +++++
|
||||
.../vault/retrive-data-asymmetric-vault.yml | 2 +-
|
||||
.../vault/retrive-data-symmetric-vault.yml | 2 +-
|
||||
plugins/modules/ipavault.py | 19 +++++++++++++------
|
||||
tests/vault/test_vault_asymmetric.yml | 12 ++++++------
|
||||
tests/vault/test_vault_standard.yml | 8 ++++----
|
||||
tests/vault/test_vault_symmetric.yml | 14 +++++++-------
|
||||
7 files changed, 37 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/README-vault.md b/README-vault.md
|
||||
index fa1d3e1..91d311d 100644
|
||||
--- a/README-vault.md
|
||||
+++ b/README-vault.md
|
||||
@@ -248,6 +248,11 @@ Variable | Description | Returned When
|
||||
-------- | ----------- | -------------
|
||||
`data` | The data stored in the vault. | If `state` is `retrieved`.
|
||||
|
||||
+Variable | Description | Returned When
|
||||
+-------- | ----------- | -------------
|
||||
+`vault` | Vault dict with archived data. (dict) <br>Options: | If `state` is `retrieved`.
|
||||
+ | `data` - The vault data. | Always
|
||||
+
|
||||
|
||||
Notes
|
||||
=====
|
||||
diff --git a/playbooks/vault/retrive-data-asymmetric-vault.yml b/playbooks/vault/retrive-data-asymmetric-vault.yml
|
||||
index 5f67c59..f71f826 100644
|
||||
--- a/playbooks/vault/retrive-data-asymmetric-vault.yml
|
||||
+++ b/playbooks/vault/retrive-data-asymmetric-vault.yml
|
||||
@@ -14,4 +14,4 @@
|
||||
state: retrieved
|
||||
register: result
|
||||
- debug:
|
||||
- msg: "Data: {{ result.data }}"
|
||||
+ msg: "Data: {{ result.vault.data }}"
|
||||
diff --git a/playbooks/vault/retrive-data-symmetric-vault.yml b/playbooks/vault/retrive-data-symmetric-vault.yml
|
||||
index 163f8b9..24692a8 100644
|
||||
--- a/playbooks/vault/retrive-data-symmetric-vault.yml
|
||||
+++ b/playbooks/vault/retrive-data-symmetric-vault.yml
|
||||
@@ -14,4 +14,4 @@
|
||||
state: retrieved
|
||||
register: result
|
||||
- debug:
|
||||
- msg: "{{ result.data | b64decode }}"
|
||||
+ msg: "{{ result.vault.data }}"
|
||||
diff --git a/plugins/modules/ipavault.py b/plugins/modules/ipavault.py
|
||||
index 84645c7..6a3c73e 100644
|
||||
--- a/plugins/modules/ipavault.py
|
||||
+++ b/plugins/modules/ipavault.py
|
||||
@@ -303,10 +303,15 @@ EXAMPLES = """
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
-data:
|
||||
- description: The vault data.
|
||||
- returned: If state is retrieved.
|
||||
- type: string
|
||||
+vault:
|
||||
+ description: Vault dict with archived data.
|
||||
+ returned: If state is `retrieved`.
|
||||
+ type: dict
|
||||
+ options:
|
||||
+ data:
|
||||
+ description: The vault data.
|
||||
+ returned: always
|
||||
+ type: string
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -910,9 +915,11 @@ def main():
|
||||
if 'result' not in result:
|
||||
raise Exception("No result obtained.")
|
||||
if 'data' in result['result']:
|
||||
- exit_args['data'] = result['result']['data']
|
||||
+ data_return = exit_args.setdefault('vault', {})
|
||||
+ data_return['data'] = result['result']['data']
|
||||
elif 'vault_data' in result['result']:
|
||||
- exit_args['data'] = result['result']['vault_data']
|
||||
+ data_return = exit_args.setdefault('vault', {})
|
||||
+ data_return['data'] = result['result']['vault_data']
|
||||
else:
|
||||
raise Exception("No data retrieved.")
|
||||
changed = False
|
||||
diff --git a/tests/vault/test_vault_asymmetric.yml b/tests/vault/test_vault_asymmetric.yml
|
||||
index 1a1d3dc..268922c 100644
|
||||
--- a/tests/vault/test_vault_asymmetric.yml
|
||||
+++ b/tests/vault/test_vault_asymmetric.yml
|
||||
@@ -42,7 +42,7 @@
|
||||
private_key: "{{ lookup('file', 'private.pem') | b64encode }}"
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Retrieve data from asymmetric vault into file {{ ansible_env.HOME }}/data.txt.
|
||||
ipavault:
|
||||
@@ -75,7 +75,7 @@
|
||||
private_key: "{{ lookup('file', 'private.pem') | b64encode }}"
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'The world of π is half rounded.' or result.changed
|
||||
+ failed_when: result.vault.data != 'The world of π is half rounded.' or result.changed
|
||||
|
||||
- name: Archive data in asymmetric vault, from file.
|
||||
ipavault:
|
||||
@@ -93,7 +93,7 @@
|
||||
private_key: "{{ lookup('file', 'private.pem') | b64encode }}"
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Another World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Another World.' or result.changed
|
||||
|
||||
- name: Archive data with single character to asymmetric vault
|
||||
ipavault:
|
||||
@@ -110,7 +110,7 @@
|
||||
private_key: "{{ lookup('file', 'private.pem') | b64encode }}"
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'c' or result.changed
|
||||
+ failed_when: result.vault.data != 'c' or result.changed
|
||||
|
||||
- name: Ensure asymmetric vault is absent
|
||||
ipavault:
|
||||
@@ -161,7 +161,7 @@
|
||||
private_key: "{{ lookup('file', 'private.pem') | b64encode }}"
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Retrieve data from asymmetric vault, with password file.
|
||||
ipavault:
|
||||
@@ -170,7 +170,7 @@
|
||||
private_key_file: "{{ ansible_env.HOME }}/private.pem"
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Ensure asymmetric vault is absent
|
||||
ipavault:
|
||||
diff --git a/tests/vault/test_vault_standard.yml b/tests/vault/test_vault_standard.yml
|
||||
index 5e0da98..6ccb0d5 100644
|
||||
--- a/tests/vault/test_vault_standard.yml
|
||||
+++ b/tests/vault/test_vault_standard.yml
|
||||
@@ -39,7 +39,7 @@
|
||||
name: stdvault
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Retrieve data from standard vault into file {{ ansible_env.HOME }}/data.txt.
|
||||
ipavault:
|
||||
@@ -70,7 +70,7 @@
|
||||
name: stdvault
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'The world of π is half rounded.' or result.changed
|
||||
+ failed_when: result.vault.data != 'The world of π is half rounded.' or result.changed
|
||||
|
||||
- name: Archive data in standard vault, from file.
|
||||
ipavault:
|
||||
@@ -87,7 +87,7 @@
|
||||
name: stdvault
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Another World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Another World.' or result.changed
|
||||
|
||||
- name: Archive data with single character to standard vault
|
||||
ipavault:
|
||||
@@ -103,7 +103,7 @@
|
||||
name: stdvault
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'c' or result.changed
|
||||
+ failed_when: result.vault.data != 'c' or result.changed
|
||||
|
||||
- name: Ensure standard vault is absent
|
||||
ipavault:
|
||||
diff --git a/tests/vault/test_vault_symmetric.yml b/tests/vault/test_vault_symmetric.yml
|
||||
index a6072d8..bedc221 100644
|
||||
--- a/tests/vault/test_vault_symmetric.yml
|
||||
+++ b/tests/vault/test_vault_symmetric.yml
|
||||
@@ -43,7 +43,7 @@
|
||||
password: SomeVAULTpassword
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Retrieve data from symmetric vault into file {{ ansible_env.HOME }}/data.txt.
|
||||
ipavault:
|
||||
@@ -77,7 +77,7 @@
|
||||
password: SomeVAULTpassword
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'The world of π is half rounded.' or result.changed
|
||||
+ failed_when: result.vault.data != 'The world of π is half rounded.' or result.changed
|
||||
|
||||
- name: Archive data in symmetric vault, from file.
|
||||
ipavault:
|
||||
@@ -95,7 +95,7 @@
|
||||
password: SomeVAULTpassword
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Another World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Another World.' or result.changed
|
||||
|
||||
- name: Archive data with single character to symmetric vault
|
||||
ipavault:
|
||||
@@ -113,7 +113,7 @@
|
||||
password: SomeVAULTpassword
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'c' or result.changed
|
||||
+ failed_when: result.vault.data != 'c' or result.changed
|
||||
|
||||
- name: Ensure symmetric vault is absent
|
||||
ipavault:
|
||||
@@ -167,7 +167,7 @@
|
||||
password: SomeVAULTpassword
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Retrieve data from symmetric vault, with password file.
|
||||
ipavault:
|
||||
@@ -176,7 +176,7 @@
|
||||
password_file: "{{ ansible_env.HOME }}/password.txt"
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Change vault password.
|
||||
ipavault:
|
||||
@@ -212,7 +212,7 @@
|
||||
password: SomeNEWpassword
|
||||
state: retrieved
|
||||
register: result
|
||||
- failed_when: result.data != 'Hello World.' or result.changed
|
||||
+ failed_when: result.vault.data != 'Hello World.' or result.changed
|
||||
|
||||
- name: Try to add vault with multiple passwords.
|
||||
ipavault:
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,49 +0,0 @@
|
||||
From 80aac15de9026055ae2b9972859939cf7925b813 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Woerner <twoerner@redhat.com>
|
||||
Date: Tue, 30 Jun 2020 17:32:19 +0200
|
||||
Subject: [PATCH] action_plugins/ipaclient_get_otp: Discovered python needed in
|
||||
task_vars
|
||||
|
||||
Ansible is now also supporting discovered_python_interpreter for
|
||||
action_plugins. task_vars needs to be non Null and contain a setting for
|
||||
discovered_python_interpreter. The ipaclient_get_otp action_plugin
|
||||
therefore needed to be adapted.
|
||||
---
|
||||
roles/ipaclient/action_plugins/ipaclient_get_otp.py | 4 ++--
|
||||
roles/ipaclient/tasks/install.yml | 1 -
|
||||
2 files changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/roles/ipaclient/action_plugins/ipaclient_get_otp.py b/roles/ipaclient/action_plugins/ipaclient_get_otp.py
|
||||
index dcddc0a..8e04ad9 100644
|
||||
--- a/roles/ipaclient/action_plugins/ipaclient_get_otp.py
|
||||
+++ b/roles/ipaclient/action_plugins/ipaclient_get_otp.py
|
||||
@@ -164,7 +164,8 @@ class ActionModule(ActionBase):
|
||||
return result
|
||||
|
||||
data = self._execute_module(module_name='ipaclient_get_facts',
|
||||
- module_args=dict(), task_vars=None)
|
||||
+ module_args=dict(), task_vars=task_vars)
|
||||
+
|
||||
try:
|
||||
domain = data['ansible_facts']['ipa']['domain']
|
||||
realm = data['ansible_facts']['ipa']['realm']
|
||||
@@ -245,4 +246,3 @@ class ActionModule(ActionBase):
|
||||
finally:
|
||||
# delete the local temp directory
|
||||
shutil.rmtree(local_temp_dir, ignore_errors=True)
|
||||
- run_cmd(['/usr/bin/kdestroy', '-c', tmp_ccache])
|
||||
diff --git a/roles/ipaclient/tasks/install.yml b/roles/ipaclient/tasks/install.yml
|
||||
index 0de3dea..4421f0c 100644
|
||||
--- a/roles/ipaclient/tasks/install.yml
|
||||
+++ b/roles/ipaclient/tasks/install.yml
|
||||
@@ -134,7 +134,6 @@
|
||||
"Password cannot be set on enrolled host" not
|
||||
in result_ipaclient_get_otp.msg
|
||||
delegate_to: "{{ result_ipaclient_test.servers[0] }}"
|
||||
- delegate_facts: yes
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Install - Report error for OTP generation
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,132 +0,0 @@
|
||||
From 6132a947e65fb9c3a1ec5c059aed34afb06a67df Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Woerner <twoerner@redhat.com>
|
||||
Date: Mon, 29 Jun 2020 13:12:12 +0200
|
||||
Subject: [PATCH] ipa[host]group: Fix membermanager unknow user issue
|
||||
|
||||
If a unknown membermanager user presence will be ensured, the unknown user
|
||||
error was ignored. This has been fixed in ipagroup. The code for the error
|
||||
handling in ipagroup and ipahostgroup has been adapted because of this.
|
||||
|
||||
New tests for tests/[host]group/test_[host]group_membermnager.yml have been
|
||||
added.
|
||||
---
|
||||
plugins/modules/ipagroup.py | 19 +++++++++----------
|
||||
plugins/modules/ipahostgroup.py | 13 +++++++------
|
||||
tests/group/test_group_membermanager.yml | 11 ++++++++++-
|
||||
.../test_hostgroup_membermanager.yml | 11 ++++++++++-
|
||||
4 files changed, 36 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/plugins/modules/ipagroup.py b/plugins/modules/ipagroup.py
|
||||
index 915bc499..903c256d 100644
|
||||
--- a/plugins/modules/ipagroup.py
|
||||
+++ b/plugins/modules/ipagroup.py
|
||||
@@ -507,16 +507,15 @@ def main():
|
||||
# All "already a member" and "not a member" failures in the
|
||||
# result are ignored. All others are reported.
|
||||
errors = []
|
||||
- if "failed" in result and len(result["failed"]) > 0:
|
||||
- for item in result["failed"]:
|
||||
- failed_item = result["failed"][item]
|
||||
- for member_type in failed_item:
|
||||
- for member, failure in failed_item[member_type]:
|
||||
- if "already a member" in failure \
|
||||
- or "not a member" in failure:
|
||||
- continue
|
||||
- errors.append("%s: %s %s: %s" % (
|
||||
- command, member_type, member, failure))
|
||||
+ for failed_item in result.get("failed", []):
|
||||
+ failed = result["failed"][failed_item]
|
||||
+ for member_type in failed:
|
||||
+ for member, failure in failed[member_type]:
|
||||
+ if "already a member" in failure \
|
||||
+ or "not a member" in failure:
|
||||
+ continue
|
||||
+ errors.append("%s: %s %s: %s" % (
|
||||
+ command, member_type, member, failure))
|
||||
if len(errors) > 0:
|
||||
ansible_module.fail_json(msg=", ".join(errors))
|
||||
|
||||
diff --git a/plugins/modules/ipahostgroup.py b/plugins/modules/ipahostgroup.py
|
||||
index 4c18e940..5f615160 100644
|
||||
--- a/plugins/modules/ipahostgroup.py
|
||||
+++ b/plugins/modules/ipahostgroup.py
|
||||
@@ -423,14 +423,15 @@ def main():
|
||||
# All "already a member" and "not a member" failures in the
|
||||
# result are ignored. All others are reported.
|
||||
errors = []
|
||||
- if "failed" in result and "member" in result["failed"]:
|
||||
- failed = result["failed"]["member"]
|
||||
+ for failed_item in result.get("failed", []):
|
||||
+ failed = result["failed"][failed_item]
|
||||
for member_type in failed:
|
||||
for member, failure in failed[member_type]:
|
||||
- if "already a member" not in failure \
|
||||
- and "not a member" not in failure:
|
||||
- errors.append("%s: %s %s: %s" % (
|
||||
- command, member_type, member, failure))
|
||||
+ if "already a member" in failure \
|
||||
+ or "not a member" in failure:
|
||||
+ continue
|
||||
+ errors.append("%s: %s %s: %s" % (
|
||||
+ command, member_type, member, failure))
|
||||
if len(errors) > 0:
|
||||
ansible_module.fail_json(msg=", ".join(errors))
|
||||
|
||||
diff --git a/tests/group/test_group_membermanager.yml b/tests/group/test_group_membermanager.yml
|
||||
index 1d38654f..661f26d6 100644
|
||||
--- a/tests/group/test_group_membermanager.yml
|
||||
+++ b/tests/group/test_group_membermanager.yml
|
||||
@@ -8,7 +8,7 @@
|
||||
- name: Ensure user manangeruser1 and manageruser2 is absent
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
- name: manageruser1,manageruser2
|
||||
+ name: manageruser1,manageruser2,unknown_user
|
||||
state: absent
|
||||
|
||||
- name: Ensure group testgroup, managergroup1 and managergroup2 are absent
|
||||
@@ -185,6 +185,15 @@
|
||||
register: result
|
||||
failed_when: not result.changed
|
||||
|
||||
+ - name: Ensure unknown membermanager_user member failure
|
||||
+ ipagroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: testgroup
|
||||
+ membermanager_user: unknown_user
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed or "no such entry" not in result.msg
|
||||
+
|
||||
- name: Ensure group testgroup, managergroup1 and managergroup2 are absent
|
||||
ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
diff --git a/tests/hostgroup/test_hostgroup_membermanager.yml b/tests/hostgroup/test_hostgroup_membermanager.yml
|
||||
index c32d1088..c0f65460 100644
|
||||
--- a/tests/hostgroup/test_hostgroup_membermanager.yml
|
||||
+++ b/tests/hostgroup/test_hostgroup_membermanager.yml
|
||||
@@ -15,7 +15,7 @@
|
||||
- name: Ensure user manangeruser1 and manageruser2 is absent
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
- name: manageruser1,manageruser2
|
||||
+ name: manageruser1,manageruser2,unknown_user
|
||||
state: absent
|
||||
|
||||
- name: Ensure group managergroup1 and managergroup2 are absent
|
||||
@@ -200,6 +200,15 @@
|
||||
register: result
|
||||
failed_when: not result.changed
|
||||
|
||||
+ - name: Ensure unknown membermanager_user member failure
|
||||
+ ipahostgroup:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ name: testhostgroup
|
||||
+ membermanager_user: unknown_user
|
||||
+ action: member
|
||||
+ register: result
|
||||
+ failed_when: result.changed or "no such entry" not in result.msg
|
||||
+
|
||||
- name: Ensure host-group testhostgroup is absent
|
||||
ipahostgroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
@ -1,150 +0,0 @@
|
||||
From 8ce5fd147aafc34e43dbe4246565c48eace2e115 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Woerner <twoerner@redhat.com>
|
||||
Date: Thu, 2 Jul 2020 12:02:33 +0200
|
||||
Subject: [PATCH] ipa[server,replica]: Fix pkcs12 info regressions introduced
|
||||
with CA-less
|
||||
|
||||
With the CA-less patches the types for the pkcs12 infos have been changed
|
||||
to lists in the modules. This is resulting in a bad conversion from None
|
||||
to [''] for the parameters. Because of this a normal replica deployment is
|
||||
failing as [''] is not a valid value.
|
||||
|
||||
The install.yml files for ipareplica and also ipaserver have been changed
|
||||
in the way that the pkcs12 values are checked if they are None. The
|
||||
parameter will simply be omitted in this case and the parameter in the
|
||||
module will become None by default.
|
||||
---
|
||||
roles/ipareplica/tasks/install.yml | 18 +++++++++---------
|
||||
roles/ipaserver/tasks/install.yml | 10 +++++-----
|
||||
2 files changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/roles/ipareplica/tasks/install.yml b/roles/ipareplica/tasks/install.yml
|
||||
index fc7f83e..c2a6222 100644
|
||||
--- a/roles/ipareplica/tasks/install.yml
|
||||
+++ b/roles/ipareplica/tasks/install.yml
|
||||
@@ -281,7 +281,7 @@
|
||||
ccache: "{{ result_ipareplica_prepare.ccache }}"
|
||||
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
|
||||
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
|
||||
- _dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info }}"
|
||||
+ _dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info if result_ipareplica_prepare._dirsrv_pkcs12_info != None else omit }}"
|
||||
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
|
||||
@@ -345,7 +345,7 @@
|
||||
config_master_host_name:
|
||||
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
|
||||
ccache: "{{ result_ipareplica_prepare.ccache }}"
|
||||
- _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
|
||||
+ _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
|
||||
# We need to point to the master in ipa default conf when certmonger
|
||||
@@ -407,8 +407,8 @@
|
||||
ccache: "{{ result_ipareplica_prepare.ccache }}"
|
||||
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
|
||||
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
|
||||
- _dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info }}"
|
||||
- _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
|
||||
+ _dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info if result_ipareplica_prepare._dirsrv_pkcs12_info != None else omit }}"
|
||||
+ _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
ds_ca_subject: "{{ result_ipareplica_setup_ds.ds_ca_subject }}"
|
||||
@@ -429,7 +429,7 @@
|
||||
ccache: "{{ result_ipareplica_prepare.ccache }}"
|
||||
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
|
||||
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
|
||||
- _http_pkcs12_info: "{{ result_ipareplica_prepare._http_pkcs12_info }}"
|
||||
+ _http_pkcs12_info: "{{ result_ipareplica_prepare._http_pkcs12_info if result_ipareplica_prepare._http_pkcs12_info != None else omit }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
|
||||
@@ -507,7 +507,7 @@
|
||||
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
|
||||
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
|
||||
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
|
||||
- _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
|
||||
+ _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
|
||||
@@ -529,7 +529,7 @@
|
||||
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
|
||||
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
|
||||
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
|
||||
- _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
|
||||
+ _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
|
||||
@@ -554,7 +554,7 @@
|
||||
ccache: "{{ result_ipareplica_prepare.ccache }}"
|
||||
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
|
||||
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
|
||||
- _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
|
||||
+ _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
|
||||
@@ -574,7 +574,7 @@
|
||||
ccache: "{{ result_ipareplica_prepare.ccache }}"
|
||||
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
|
||||
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
|
||||
- _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
|
||||
+ _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
ds_ca_subject: "{{ result_ipareplica_setup_ds.ds_ca_subject }}"
|
||||
diff --git a/roles/ipaserver/tasks/install.yml b/roles/ipaserver/tasks/install.yml
|
||||
index 30f9da2..687f72d 100644
|
||||
--- a/roles/ipaserver/tasks/install.yml
|
||||
+++ b/roles/ipaserver/tasks/install.yml
|
||||
@@ -203,7 +203,7 @@
|
||||
# no_host_dns: "{{ result_ipaserver_test.no_host_dns }}"
|
||||
dirsrv_config_file: "{{ ipaserver_dirsrv_config_file | default(omit) }}"
|
||||
dirsrv_cert_files: "{{ ipaserver_dirsrv_cert_files | default(omit) }}"
|
||||
- _dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info }}"
|
||||
+ _dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info if result_ipaserver_test._dirsrv_pkcs12_info != None else omit }}"
|
||||
external_cert_files:
|
||||
"{{ ipaserver_external_cert_files | default(omit) }}"
|
||||
subject_base: "{{ result_ipaserver_prepare.subject_base }}"
|
||||
@@ -240,7 +240,7 @@
|
||||
no_hbac_allow: "{{ ipaserver_no_hbac_allow }}"
|
||||
idstart: "{{ result_ipaserver_test.idstart }}"
|
||||
idmax: "{{ result_ipaserver_test.idmax }}"
|
||||
- _pkinit_pkcs12_info: "{{ result_ipaserver_test._pkinit_pkcs12_info }}"
|
||||
+ _pkinit_pkcs12_info: "{{ result_ipaserver_test._pkinit_pkcs12_info if result_ipaserver_test._pkinit_pkcs12_info != None else omit }}"
|
||||
|
||||
- name: Install - Setup custodia
|
||||
ipaserver_setup_custodia:
|
||||
@@ -270,7 +270,7 @@
|
||||
no_pkinit: "{{ result_ipaserver_test.no_pkinit }}"
|
||||
dirsrv_config_file: "{{ ipaserver_dirsrv_config_file | default(omit) }}"
|
||||
dirsrv_cert_files: "{{ ipaserver_dirsrv_cert_files | default([]) }}"
|
||||
- _dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info }}"
|
||||
+ _dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info if result_ipaserver_test._dirsrv_pkcs12_info != None else omit }}"
|
||||
external_ca: "{{ ipaserver_external_ca }}"
|
||||
external_ca_type: "{{ ipaserver_external_ca_type | default(omit) }}"
|
||||
external_ca_profile:
|
||||
@@ -334,7 +334,7 @@
|
||||
idmax: "{{ result_ipaserver_test.idmax }}"
|
||||
http_cert_files: "{{ ipaserver_http_cert_files | default([]) }}"
|
||||
no_ui_redirect: "{{ ipaserver_no_ui_redirect }}"
|
||||
- _http_pkcs12_info: "{{ result_ipaserver_test._http_pkcs12_info }}"
|
||||
+ _http_pkcs12_info: "{{ result_ipaserver_test._http_pkcs12_info if result_ipaserver_test._http_pkcs12_info != None else omit }}"
|
||||
|
||||
- name: Install - Setup KRA
|
||||
ipaserver_setup_kra:
|
||||
@@ -394,7 +394,7 @@
|
||||
idstart: "{{ result_ipaserver_test.idstart }}"
|
||||
idmax: "{{ result_ipaserver_test.idmax }}"
|
||||
dirsrv_config_file: "{{ ipaserver_dirsrv_config_file | default(omit) }}"
|
||||
- _dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info }}"
|
||||
+ _dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info if result_ipaserver_test._dirsrv_pkcs12_info != None else omit }}"
|
||||
|
||||
- name: Install - Setup client
|
||||
include_role:
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,132 +0,0 @@
|
||||
From 1d7fb31b8bfa00babd7c753b354d7344b531cd77 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Woerner <twoerner@redhat.com>
|
||||
Date: Mon, 29 Jun 2020 14:50:56 +0200
|
||||
Subject: [PATCH] ipa[user,host]: Fail on duplucate names in the users and
|
||||
hosts lists
|
||||
|
||||
It was possible to have several entries for names with the hosts and users
|
||||
lists. This resulted sometimes in errors but also unexpected changes. A new
|
||||
check has been added to make sure that the names in the users and hosts
|
||||
lists are unique.
|
||||
|
||||
New tests have been added to verify this in the existing files:
|
||||
- tests/host/test_hosts.yml
|
||||
- tests/user/test_users.yml
|
||||
---
|
||||
plugins/modules/ipahost.py | 7 +++++++
|
||||
plugins/modules/ipauser.py | 7 +++++++
|
||||
tests/host/test_hosts.yml | 15 +++++++++++++++
|
||||
tests/user/test_users.yml | 19 +++++++++++++++++++
|
||||
4 files changed, 48 insertions(+)
|
||||
|
||||
diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py
|
||||
index 7a981f16..1fe11dc5 100644
|
||||
--- a/plugins/modules/ipahost.py
|
||||
+++ b/plugins/modules/ipahost.py
|
||||
@@ -799,10 +799,15 @@ def main():
|
||||
server_realm = api_get_realm()
|
||||
|
||||
commands = []
|
||||
+ host_set = set()
|
||||
|
||||
for host in names:
|
||||
if isinstance(host, dict):
|
||||
name = host.get("name")
|
||||
+ if name in host_set:
|
||||
+ ansible_module.fail_json(
|
||||
+ msg="host '%s' is used more than once" % name)
|
||||
+ host_set.add(name)
|
||||
description = host.get("description")
|
||||
locality = host.get("locality")
|
||||
location = host.get("location")
|
||||
@@ -1337,6 +1342,8 @@ def main():
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
+ del host_set
|
||||
+
|
||||
# Execute commands
|
||||
|
||||
errors = []
|
||||
diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py
|
||||
index b8152ee4..03713a41 100644
|
||||
--- a/plugins/modules/ipauser.py
|
||||
+++ b/plugins/modules/ipauser.py
|
||||
@@ -958,10 +958,15 @@ def main():
|
||||
# commands
|
||||
|
||||
commands = []
|
||||
+ user_set = set()
|
||||
|
||||
for user in names:
|
||||
if isinstance(user, dict):
|
||||
name = user.get("name")
|
||||
+ if name in user_set:
|
||||
+ ansible_module.fail_json(
|
||||
+ msg="user '%s' is used more than once" % name)
|
||||
+ user_set.add(name)
|
||||
# present
|
||||
first = user.get("first")
|
||||
last = user.get("last")
|
||||
@@ -1370,6 +1375,8 @@ def main():
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
+ del user_set
|
||||
+
|
||||
# Execute commands
|
||||
|
||||
errors = []
|
||||
diff --git a/tests/host/test_hosts.yml b/tests/host/test_hosts.yml
|
||||
index 30fd6538..f82cc612 100644
|
||||
--- a/tests/host/test_hosts.yml
|
||||
+++ b/tests/host/test_hosts.yml
|
||||
@@ -96,3 +96,18 @@
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed
|
||||
+
|
||||
+ - name: Duplicate names in hosts failure test
|
||||
+ ipahost:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ hosts:
|
||||
+ - name: "{{ host1_fqdn }}"
|
||||
+ force: yes
|
||||
+ - name: "{{ host2_fqdn }}"
|
||||
+ force: yes
|
||||
+ - name: "{{ host3_fqdn }}"
|
||||
+ force: yes
|
||||
+ - name: "{{ host3_fqdn }}"
|
||||
+ force: yes
|
||||
+ register: result
|
||||
+ failed_when: result.changed or "is used more than once" not in result.msg
|
||||
diff --git a/tests/user/test_users.yml b/tests/user/test_users.yml
|
||||
index 5b5d4538..81c7b608 100644
|
||||
--- a/tests/user/test_users.yml
|
||||
+++ b/tests/user/test_users.yml
|
||||
@@ -85,6 +85,25 @@
|
||||
register: result
|
||||
failed_when: result.changed
|
||||
|
||||
+ - name: Duplicate names in users failure test
|
||||
+ ipauser:
|
||||
+ ipaadmin_password: SomeADMINpassword
|
||||
+ users:
|
||||
+ - name: user1
|
||||
+ givenname: user1
|
||||
+ last: Last
|
||||
+ - name: user2
|
||||
+ first: user2
|
||||
+ last: Last
|
||||
+ - name: user3
|
||||
+ first: user3
|
||||
+ last: Last
|
||||
+ - name: user3
|
||||
+ first: user3
|
||||
+ last: Last
|
||||
+ register: result
|
||||
+ failed_when: result.changed or "is used more than once" not in result.msg
|
||||
+
|
||||
- name: Remove test users
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
@ -1,271 +0,0 @@
|
||||
From 7a2eaa6f535b1353d46bcfa8b0b2484b15ff3863 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Woerner <twoerner@redhat.com>
|
||||
Date: Tue, 7 Jul 2020 17:13:09 +0200
|
||||
Subject: [PATCH] ipareplica: Fix missing parameters for several modules
|
||||
|
||||
The parameters master_host_name, config_setup_ca, dirman_password have not
|
||||
been set for some modules. Also there was no ldap2 connection within
|
||||
ipareplica_setup_kra. All this resulted in improper configuration where
|
||||
for example KRA deployment failed in the end.
|
||||
|
||||
A conversion warning in ipareplica_setup_adtrust has also been fixed for
|
||||
the setup_ca parameter.
|
||||
|
||||
Fixes #314 (IPA replica installation failure - DS enabled SSL - second part)
|
||||
---
|
||||
.../library/ipareplica_create_ipa_conf.py | 1 +
|
||||
.../library/ipareplica_ds_apply_updates.py | 1 +
|
||||
.../library/ipareplica_ds_enable_ssl.py | 1 +
|
||||
.../library/ipareplica_setup_adtrust.py | 2 +-
|
||||
.../library/ipareplica_setup_custodia.py | 1 +
|
||||
.../library/ipareplica_setup_http.py | 2 +-
|
||||
.../ipareplica/library/ipareplica_setup_kra.py | 18 ++++++++++++++++++
|
||||
.../ipareplica/library/ipareplica_setup_krb.py | 7 +++++++
|
||||
roles/ipareplica/tasks/install.yml | 8 ++++++++
|
||||
9 files changed, 39 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/roles/ipareplica/library/ipareplica_create_ipa_conf.py b/roles/ipareplica/library/ipareplica_create_ipa_conf.py
|
||||
index 3a85a6f..c475469 100644
|
||||
--- a/roles/ipareplica/library/ipareplica_create_ipa_conf.py
|
||||
+++ b/roles/ipareplica/library/ipareplica_create_ipa_conf.py
|
||||
@@ -262,6 +262,7 @@ def main():
|
||||
config.subject_base = options.subject_base
|
||||
config.dirman_password = dirman_password
|
||||
config.ca_host_name = ca_host_name
|
||||
+ config.setup_ca = options.setup_ca
|
||||
|
||||
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
|
||||
installer._remote_api = remote_api
|
||||
diff --git a/roles/ipareplica/library/ipareplica_ds_apply_updates.py b/roles/ipareplica/library/ipareplica_ds_apply_updates.py
|
||||
index 3796874..71008b3 100644
|
||||
--- a/roles/ipareplica/library/ipareplica_ds_apply_updates.py
|
||||
+++ b/roles/ipareplica/library/ipareplica_ds_apply_updates.py
|
||||
@@ -177,6 +177,7 @@ def main():
|
||||
config = gen_ReplicaConfig()
|
||||
config.dirman_password = dirman_password
|
||||
config.subject_base = options.subject_base
|
||||
+ config.master_host_name = master_host_name
|
||||
|
||||
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
|
||||
|
||||
diff --git a/roles/ipareplica/library/ipareplica_ds_enable_ssl.py b/roles/ipareplica/library/ipareplica_ds_enable_ssl.py
|
||||
index a1b638e..3e4090d 100644
|
||||
--- a/roles/ipareplica/library/ipareplica_ds_enable_ssl.py
|
||||
+++ b/roles/ipareplica/library/ipareplica_ds_enable_ssl.py
|
||||
@@ -173,6 +173,7 @@ def main():
|
||||
config = gen_ReplicaConfig()
|
||||
config.dirman_password = dirman_password
|
||||
config.subject_base = options.subject_base
|
||||
+ config.master_host_name = master_host_name
|
||||
|
||||
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
|
||||
# installer._remote_api = remote_api
|
||||
diff --git a/roles/ipareplica/library/ipareplica_setup_adtrust.py b/roles/ipareplica/library/ipareplica_setup_adtrust.py
|
||||
index c830ebf..734e56d 100644
|
||||
--- a/roles/ipareplica/library/ipareplica_setup_adtrust.py
|
||||
+++ b/roles/ipareplica/library/ipareplica_setup_adtrust.py
|
||||
@@ -110,7 +110,7 @@ def main():
|
||||
# additional
|
||||
ccache=dict(required=True),
|
||||
_top_dir=dict(required=True),
|
||||
- setup_ca=dict(required=True),
|
||||
+ setup_ca=dict(required=True, type='bool'),
|
||||
config_master_host_name=dict(required=True),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
diff --git a/roles/ipareplica/library/ipareplica_setup_custodia.py b/roles/ipareplica/library/ipareplica_setup_custodia.py
|
||||
index 5a74e87..2e95c26 100644
|
||||
--- a/roles/ipareplica/library/ipareplica_setup_custodia.py
|
||||
+++ b/roles/ipareplica/library/ipareplica_setup_custodia.py
|
||||
@@ -169,6 +169,7 @@ def main():
|
||||
config.promote = installer.promote
|
||||
config.kra_enabled = kra_enabled
|
||||
config.kra_host_name = kra_host_name
|
||||
+ config.setup_ca = options.setup_ca
|
||||
|
||||
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
|
||||
|
||||
diff --git a/roles/ipareplica/library/ipareplica_setup_http.py b/roles/ipareplica/library/ipareplica_setup_http.py
|
||||
index 987ea95..3fa4807 100644
|
||||
--- a/roles/ipareplica/library/ipareplica_setup_http.py
|
||||
+++ b/roles/ipareplica/library/ipareplica_setup_http.py
|
||||
@@ -164,7 +164,7 @@ def main():
|
||||
config.subject_base = options.subject_base
|
||||
config.dirman_password = dirman_password
|
||||
config.setup_ca = options.setup_ca
|
||||
- # config.master_host_name = master_host_name
|
||||
+ config.master_host_name = master_host_name
|
||||
config.ca_host_name = ca_host_name
|
||||
config.promote = installer.promote
|
||||
|
||||
diff --git a/roles/ipareplica/library/ipareplica_setup_kra.py b/roles/ipareplica/library/ipareplica_setup_kra.py
|
||||
index 3149c10..0b2f681 100644
|
||||
--- a/roles/ipareplica/library/ipareplica_setup_kra.py
|
||||
+++ b/roles/ipareplica/library/ipareplica_setup_kra.py
|
||||
@@ -120,6 +120,9 @@ options:
|
||||
_subject_base:
|
||||
description: The installer _subject_base setting
|
||||
required: no
|
||||
+ dirman_password:
|
||||
+ description: Directory Manager (master) password
|
||||
+ required: no
|
||||
author:
|
||||
- Thomas Woerner
|
||||
'''
|
||||
@@ -173,10 +176,12 @@ def main():
|
||||
_ca_enabled=dict(required=False, type='bool'),
|
||||
_kra_enabled=dict(required=False, type='bool'),
|
||||
_kra_host_name=dict(required=False),
|
||||
+ _ca_host_name=dict(required=False),
|
||||
_top_dir=dict(required=True),
|
||||
_add_to_ipaservers=dict(required=True, type='bool'),
|
||||
_ca_subject=dict(required=True),
|
||||
_subject_base=dict(required=True),
|
||||
+ dirman_password=dict(required=True, no_log=True),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
@@ -233,6 +238,7 @@ def main():
|
||||
ca_enabled = ansible_module.params.get('_ca_enabled')
|
||||
kra_enabled = ansible_module.params.get('_kra_enabled')
|
||||
kra_host_name = ansible_module.params.get('_kra_host_name')
|
||||
+ ca_host_name = ansible_module.params.get('_ca_host_name')
|
||||
|
||||
options.subject_base = ansible_module.params.get('subject_base')
|
||||
if options.subject_base is not None:
|
||||
@@ -243,6 +249,7 @@ def main():
|
||||
|
||||
options._ca_subject = ansible_module.params.get('_ca_subject')
|
||||
options._subject_base = ansible_module.params.get('_subject_base')
|
||||
+ dirman_password = ansible_module.params.get('dirman_password')
|
||||
|
||||
# init #
|
||||
|
||||
@@ -254,14 +261,25 @@ def main():
|
||||
constants.DEFAULT_CONFIG)
|
||||
api_bootstrap_finalize(env)
|
||||
config = gen_ReplicaConfig()
|
||||
+ config.dirman_password = dirman_password
|
||||
config.subject_base = options.subject_base
|
||||
config.promote = installer.promote
|
||||
config.kra_enabled = kra_enabled
|
||||
config.kra_host_name = kra_host_name
|
||||
+ config.ca_host_name = ca_host_name
|
||||
+ config.master_host_name = master_host_name
|
||||
|
||||
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
|
||||
installer._remote_api = remote_api
|
||||
|
||||
+ conn = remote_api.Backend.ldap2
|
||||
+ ccache = os.environ['KRB5CCNAME']
|
||||
+
|
||||
+ # There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
|
||||
+ # ntpinstance
|
||||
+ api.Backend.ldap2.connect()
|
||||
+ conn.connect(ccache=ccache)
|
||||
+
|
||||
with redirect_stdout(ansible_log):
|
||||
ansible_log.debug("-- INSTALL KRA --")
|
||||
|
||||
diff --git a/roles/ipareplica/library/ipareplica_setup_krb.py b/roles/ipareplica/library/ipareplica_setup_krb.py
|
||||
index c8d09f7..4500a6f 100644
|
||||
--- a/roles/ipareplica/library/ipareplica_setup_krb.py
|
||||
+++ b/roles/ipareplica/library/ipareplica_setup_krb.py
|
||||
@@ -63,6 +63,9 @@ options:
|
||||
_top_dir:
|
||||
description: The installer _top_dir setting
|
||||
required: no
|
||||
+ dirman_password:
|
||||
+ description: Directory Manager (master) password
|
||||
+ required: no
|
||||
author:
|
||||
- Thomas Woerner
|
||||
'''
|
||||
@@ -98,6 +101,7 @@ def main():
|
||||
ccache=dict(required=True),
|
||||
_pkinit_pkcs12_info=dict(required=False, type='list'),
|
||||
_top_dir=dict(required=True),
|
||||
+ dirman_password=dict(required=True, no_log=True),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
@@ -126,6 +130,7 @@ def main():
|
||||
'_pkinit_pkcs12_info')
|
||||
|
||||
options._top_dir = ansible_module.params.get('_top_dir')
|
||||
+ dirman_password = ansible_module.params.get('dirman_password')
|
||||
|
||||
# init #
|
||||
|
||||
@@ -141,8 +146,10 @@ def main():
|
||||
constants.DEFAULT_CONFIG)
|
||||
api_bootstrap_finalize(env)
|
||||
config = gen_ReplicaConfig()
|
||||
+ config.dirman_password = dirman_password
|
||||
config.master_host_name = config_master_host_name
|
||||
config.subject_base = options.subject_base
|
||||
+ config.setup_ca = options.setup_ca
|
||||
|
||||
ccache = os.environ['KRB5CCNAME']
|
||||
|
||||
diff --git a/roles/ipareplica/tasks/install.yml b/roles/ipareplica/tasks/install.yml
|
||||
index c2a6222..ddb3f85 100644
|
||||
--- a/roles/ipareplica/tasks/install.yml
|
||||
+++ b/roles/ipareplica/tasks/install.yml
|
||||
@@ -226,6 +226,8 @@
|
||||
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
|
||||
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
|
||||
setup_dns: "{{ ipareplica_setup_dns }}"
|
||||
+ ### server ###
|
||||
+ setup_ca: "{{ ipareplica_setup_ca }}"
|
||||
### ssl certificate ###
|
||||
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
|
||||
### client ###
|
||||
@@ -332,6 +334,7 @@
|
||||
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
|
||||
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
+ setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
|
||||
|
||||
- name: Install - Setup KRB
|
||||
ipareplica_setup_krb:
|
||||
@@ -347,6 +350,7 @@
|
||||
ccache: "{{ result_ipareplica_prepare.ccache }}"
|
||||
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
+ dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
|
||||
# We need to point to the master in ipa default conf when certmonger
|
||||
# asks for HTTP certificate in newer ipa versions. In these versions
|
||||
@@ -388,6 +392,7 @@
|
||||
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
|
||||
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
+ setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
|
||||
master:
|
||||
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
|
||||
when: result_ipareplica_test.change_master_for_certmonger
|
||||
@@ -471,6 +476,7 @@
|
||||
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
|
||||
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
|
||||
dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
+ setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
|
||||
when: result_ipareplica_test.change_master_for_certmonger
|
||||
|
||||
- name: Install - Setup otpd
|
||||
@@ -611,10 +617,12 @@
|
||||
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
|
||||
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
|
||||
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
|
||||
+ _ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
|
||||
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
|
||||
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
|
||||
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
|
||||
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
|
||||
+ dirman_password: "{{ ipareplica_dirman_password }}"
|
||||
when: result_ipareplica_test.setup_kra
|
||||
|
||||
- name: Install - Restart KDC
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,39 @@
|
||||
From 976cd1baa70b3ac1a271a362163e469b8d54d04a Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Woerner <twoerner@redhat.com>
|
||||
Date: Mon, 22 Feb 2021 13:28:04 +0100
|
||||
Subject: [PATCH] ipaclient: Do not fail on rmkeytab error #7
|
||||
|
||||
Due to commit f3f9672d527008dc741ac90aa465bac842eea08d (ipa-rmkeytab: Check
|
||||
return value of krb5_kt_(start|end)_seq_get) in IPA 4.9.2 there is a new
|
||||
error reported for ipa-rmkeytab in case of a non existing keytab file.
|
||||
Using ipa-rmkeytab now results in the error #7 in this case.
|
||||
|
||||
The client role is using ipa-rmkeytab and needs to ignore error #7 also.
|
||||
|
||||
Fixes: #510 (ipa-client installation with OTP is failed with error code 7
|
||||
(keytab: /usr/sbin/ipa-rmkeytab returned 7))
|
||||
---
|
||||
roles/ipaclient/tasks/install.yml | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/roles/ipaclient/tasks/install.yml b/roles/ipaclient/tasks/install.yml
|
||||
index fccc72e..23f9529 100644
|
||||
--- a/roles/ipaclient/tasks/install.yml
|
||||
+++ b/roles/ipaclient/tasks/install.yml
|
||||
@@ -181,8 +181,12 @@
|
||||
# Do not fail on error codes 3 and 5:
|
||||
# 3 - Unable to open keytab
|
||||
# 5 - Principal name or realm not found in keytab
|
||||
+ # 7 - Failed to set cursor, typically when errcode
|
||||
+ # would be issued in past
|
||||
failed_when: result_ipa_rmkeytab.rc != 0 and
|
||||
- result_ipa_rmkeytab.rc != 3 and result_ipa_rmkeytab.rc != 5
|
||||
+ result_ipa_rmkeytab.rc != 3 and
|
||||
+ result_ipa_rmkeytab.rc != 5 and
|
||||
+ result_ipa_rmkeytab.rc != 7
|
||||
when: (ipaclient_use_otp | bool or ipaclient_force_join | bool) and not ipaclient_on_master | bool
|
||||
|
||||
- name: Install - Backup and set hostname
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,37 +1,24 @@
|
||||
# Turn off automatic python byte compilation because these are Ansible
|
||||
# roles and the files are transferred to the node and compiled there with
|
||||
# the python verison used in the node
|
||||
# the python version used in the node
|
||||
%define __brp_python_bytecompile %{nil}
|
||||
|
||||
%global python %{__python3}
|
||||
|
||||
Summary: Roles and playbooks to deploy FreeIPA servers, replicas and clients
|
||||
Name: ansible-freeipa
|
||||
Version: 0.1.12
|
||||
Release: 6%{?dist}
|
||||
Version: 0.3.2
|
||||
Release: 2%{?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.12-Fixes-service-disable-when-service-has-no-certificates-attached_rhbz#1836294.patch
|
||||
Patch2: ansible-freeipa-0.1.12-Add-suppport-for-changing-password-of-symmetric-vaults_rhbz#1839197.patch
|
||||
Patch3: ansible-freeipa-0.1.12-Fix-forwardzone-issues_rhbz#1843826,1843828,1843829,1843830,1843831.patch
|
||||
Patch4: ansible-freeipa-0.1.12-ipa-host-group-Fix-membermanager-unknow-user-issue_rhbz#1848426.patch
|
||||
Patch5: ansible-freeipa-0.1.12-ipa-user,host-Fail-on-duplucate-names-in-the-users-and-hosts-lists_rhbz#1822683.patch
|
||||
Patch6: ansible-freeipa-0.1.12-action_plugins-ipaclient_get_otp-Discovered-python-n_rhbz#1852714.patch
|
||||
Patch7: ansible-freeipa-0.1.12-ipa-server-replica-Fix-pkcs12-info-regressions-intro_rhbz#1853284.patch
|
||||
Patch8: ansible-freeipa-0.1.12-ipareplica-Fix-missing-parameters-for-several-module_hbz#1855299.patch
|
||||
Patch9: ansible-freeipa-0.1.12-Allow-multiple-dns-zones-to-be-absent_rhbz#1845058.patch
|
||||
Patch10: ansible-freeipa-0.1.12-Fixed-error-msgs-on-FreeIPABaseModule-subclasses_rhbz#1845051.patch
|
||||
Patch11: ansible-freeipa-0.1.12-Fix-allow_retrieve_keytab_host-in-service-module_rhbz#1868020.patch
|
||||
Patch12: ansible-freeipa-0.1.12-Modified-return-value-for-ipavault-module_rhbz#1867909.patch
|
||||
Patch13: ansible-freeipa-0.1.12-Add-support-for-option-name_from_ip-in-ipadnszone-mo_rhbz#1845056.patch
|
||||
Patch14: ansible-freeipa-0.1.12-Fixes-password-behavior-on-Vault-module_rhbz#1839200.patch
|
||||
Patch0: ansible-freeipa-0.3.2-ipaclient-Do-not-fail-on-rmkeytab-error-7_rhbz#1931381.patch
|
||||
BuildArch: noarch
|
||||
|
||||
#Requires: ansible
|
||||
|
||||
%description
|
||||
ansible-freeipa provides Ansible roles and playbooks to install and uninstall
|
||||
FreeIPA servers, replicas and clients. Also modules for group, host, topology
|
||||
and user management.
|
||||
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
|
||||
@ -43,6 +30,10 @@ Features
|
||||
- Cluster deployments: Server, replicas and clients in one playbook
|
||||
- One-time-password (OTP) support for client installation
|
||||
- Repair mode for clients
|
||||
- Backup and restore, also to and from controller
|
||||
- Modules for config management
|
||||
- Modules for delegation management
|
||||
- Modules for dns config management
|
||||
- Modules for dns forwarder management
|
||||
- Modules for dns record management
|
||||
- Modules for dns zone management
|
||||
@ -52,12 +43,18 @@ Features
|
||||
- Modules for hbacsvcgroup management
|
||||
- Modules for host management
|
||||
- Modules for hostgroup management
|
||||
- Modules for location management
|
||||
- Modules for permission management
|
||||
- Modules for privilege management
|
||||
- Modules for pwpolicy management
|
||||
- Modules for role management
|
||||
- Modules for self service management
|
||||
- Modules for service management
|
||||
- Modules for sudocmd management
|
||||
- Modules for sudocmdgroup management
|
||||
- Modules for sudorule management
|
||||
- Modules for topology management
|
||||
- Modules fot trust management
|
||||
- Modules for user management
|
||||
- Modules for vault management
|
||||
|
||||
@ -99,32 +96,36 @@ Work is planned to have a new method to handle CSR for external signed CAs in
|
||||
a separate step before starting the server installation.
|
||||
|
||||
|
||||
%package tests
|
||||
Summary: ansible-freeipa tests
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description tests
|
||||
ansible-freeipa tests.
|
||||
|
||||
Please have a look at %{_datadir}/ansible-freeipa/requirements-tests.txt
|
||||
to get the needed requrements to run the tests.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%patch0 -p1
|
||||
# Do not create backup files with patches
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
%patch7 -p1
|
||||
%patch8 -p1
|
||||
%patch9 -p1
|
||||
%patch10 -p1
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
|
||||
# Fix python modules and module utils:
|
||||
# - Remove shebang
|
||||
# - Remove execute flag
|
||||
for i in roles/ipa*/library/*.py roles/ipa*/module_utils/*.py plugins/*/*.py; do
|
||||
sed -i '/\/usr\/bin\/python*/d' $i
|
||||
sed -i '1{/\/usr\/bin\/python*/d;}' $i
|
||||
chmod a-x $i
|
||||
done
|
||||
# Add execute flag to py3test.py scripts
|
||||
chmod a+x roles/ipa*/files/py3test.py
|
||||
|
||||
for i in utils/*.py utils/ansible-ipa-*-install utils/new_module \
|
||||
utils/changelog utils/ansible-doc-test;
|
||||
do
|
||||
sed -i '{s@/usr/bin/python*@%{python}@}' $i
|
||||
done
|
||||
|
||||
|
||||
%build
|
||||
|
||||
@ -136,20 +137,119 @@ cp -rp roles/ipareplica %{buildroot}%{_datadir}/ansible/roles/
|
||||
cp -rp roles/ipareplica/README.md README-replica.md
|
||||
cp -rp roles/ipaclient %{buildroot}%{_datadir}/ansible/roles/
|
||||
cp -rp roles/ipaclient/README.md README-client.md
|
||||
cp -rp roles/ipabackup %{buildroot}%{_datadir}/ansible/roles/
|
||||
cp -rp roles/ipabackup/README.md README-backup.md
|
||||
install -m 755 -d %{buildroot}%{_datadir}/ansible/plugins/
|
||||
cp -rp plugins/* %{buildroot}%{_datadir}/ansible/plugins/
|
||||
|
||||
install -m 755 -d %{buildroot}%{_datadir}/ansible-freeipa
|
||||
cp requirements*.txt %{buildroot}%{_datadir}/ansible-freeipa/
|
||||
cp -rp utils %{buildroot}%{_datadir}/ansible-freeipa/
|
||||
install -m 755 -d %{buildroot}%{_datadir}/ansible-freeipa/tests
|
||||
cp -rp tests %{buildroot}%{_datadir}/ansible-freeipa/
|
||||
|
||||
%files
|
||||
%license COPYING
|
||||
%{_datadir}/ansible/roles/ipaserver
|
||||
%{_datadir}/ansible/roles/ipareplica
|
||||
%{_datadir}/ansible/roles/ipaclient
|
||||
%{_datadir}/ansible/roles/ipabackup
|
||||
%{_datadir}/ansible/plugins/module_utils
|
||||
%{_datadir}/ansible/plugins/modules
|
||||
%doc README*.md
|
||||
%doc playbooks
|
||||
%{_datadir}/ansible-freeipa/requirements.txt
|
||||
%{_datadir}/ansible-freeipa/requirements-dev.txt
|
||||
%{_datadir}/ansible-freeipa/utils
|
||||
|
||||
%files tests
|
||||
%{_datadir}/ansible-freeipa/tests
|
||||
%{_datadir}/ansible-freeipa/requirements-tests.txt
|
||||
|
||||
%changelog
|
||||
* Thu Mar 4 2021 Thomas Woerner <twoerner@redhat.com> - 0.3.2-2
|
||||
- Fix ipaclient: Do not fail on rmkeytab error 7
|
||||
Resolves: RHBZ#1931381
|
||||
|
||||
* Mon Jan 18 2021 Thomas Woerner <twoerner@redhat.com> - 0.3.2-1
|
||||
- Update to version 0.3.2
|
||||
https://github.com/freeipa/ansible-freeipa/releases/tag/v0.3.2
|
||||
Related: RHBZ#1891826
|
||||
- Not able to add additional privileges with existing privilege in role module
|
||||
Resolves: RHBZ#1893678
|
||||
- Required error message while adding non-existing members in role handling
|
||||
Resolves: RHBZ#1893679
|
||||
- Not able to add new members with existing members role handling
|
||||
Resolves: RHBZ#1893684
|
||||
- service members are removed while updating other members in role handling
|
||||
Resolves: RHBZ#1893685
|
||||
- after changing the vault type from standard to symmetric, Salt is missing
|
||||
Resolves: RHBZ#1880367
|
||||
- After changing the vault type from symmetric to asymmetric, Salt is present
|
||||
in the asymmetric vault
|
||||
Resolves: RHBZ#1880377
|
||||
- After changing the vault type from asymmetric to the standard vault, the
|
||||
Public key is present in the standard vault
|
||||
Resolves: RHBZ#1880378
|
||||
- Not able to replace public-key-file to the public-key in asymmetric vault
|
||||
type
|
||||
Resolves: RHBZ#1880862
|
||||
- ipauser module does not seem to support --check flag to ansible-playbook
|
||||
Resolves: RHBZ#1893675
|
||||
- Not able to add additional attributes with existing attributes in permission
|
||||
handling
|
||||
Resolves: RHBZ#1893687
|
||||
- Privilege variable is removed from permission handling
|
||||
Resolves: RHBZ#1893688
|
||||
|
||||
* Wed Dec 2 2020 Thomas Woerner <twoerner@redhat.com> - 0.3.1-1
|
||||
- Update to version 0.3.1
|
||||
https://github.com/freeipa/ansible-freeipa/releases/tag/v0.3.1
|
||||
Related: RHBZ#1891826
|
||||
- ipabackup: Fix undefined vars for conditions in shell tasks without else
|
||||
Related: RHBZ#1894494
|
||||
|
||||
* Tue Dec 1 2020 Thomas Woerner <twoerner@redhat.com> - 0.3.0-2
|
||||
- Ship ipabackup role for backup and restore
|
||||
Related: RHBZ#1894494
|
||||
|
||||
* Thu Nov 26 2020 Thomas Woerner <twoerner@redhat.com> - 0.3.0-1
|
||||
- Update to version 0.3.0
|
||||
https://github.com/freeipa/ansible-freeipa/releases/tag/v0.3.0
|
||||
With tests sub package
|
||||
Resolves: RHBZ#1891826
|
||||
- Support for firewalld zone in ipaserver and ipareplica roles
|
||||
Resolves: RHBZ#1894488
|
||||
- ipagroup: Add support for the IPA CLI option `posix`
|
||||
Resolves: RHBZ#1894493
|
||||
- New ipabackup role for backup and restore
|
||||
Resolves: RHBZ#1894494
|
||||
- New management module ipadelegation
|
||||
Resolves: RHBZ#1894496
|
||||
- New management module ipalocation
|
||||
Resolves: RHBZ#1894497
|
||||
- New management module ipaprivilege
|
||||
Resolves: RHBZ#1894498
|
||||
- New management module ipapermission
|
||||
Resolves: RHBZ#1894499
|
||||
- New management module iparole
|
||||
Resolves: RHBZ#1894500
|
||||
- New management module ipaselfservice
|
||||
Resolves: RHBZ#1894501
|
||||
- New management module ipatrust
|
||||
Resolves: RHBZ#1894502
|
||||
- Fixed log of vault data return when retrieving to a file
|
||||
Resolves: RHBZ#1875378
|
||||
- ipadnszone: Fix modification o SOA serial with other attributes
|
||||
Resolves: RHBZ#1876896
|
||||
- Fix symmetric vault password change when using password_files
|
||||
Resolves: RHBZ#1879004
|
||||
- ipadnsrecord: fix record modification behavior
|
||||
Resolves: RHBZ#1880409
|
||||
Resolves: RHBZ#1881452
|
||||
- ipadnsrecord: fix record update when multiple records exist
|
||||
Resolves: RHBZ#1881436
|
||||
|
||||
* Tue Aug 18 2020 Thomas Woerner <twoerner@redhat.com> - 0.1.12-6
|
||||
- Allow to manage multiple dnszone entries
|
||||
Resolves: RHBZ#1845058
|
||||
|
Loading…
Reference in New Issue
Block a user