mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-26 21:33:05 +00:00
ipadnszone: Add support for per-zone privilege delegation
IPA DNS Zones management can be delegated by adding a "Manage DNS zone" permission. The CLI commands that manage these permissions are dnszone-add-permission and dnszone-remove-permission. The ansible-freeipa module ipadnszone did not have this capability, and it now support dnszone per-zone management delegation by setting the module parameter 'permission'. If set to 'true' the permission will be assigned to the zone, if set to false the permission will be removed.
This commit is contained in:
@@ -133,6 +133,22 @@ Example playbook to enable a zone:
|
||||
state: enabled
|
||||
```
|
||||
|
||||
Example playbook to allow per-zone privilege delegation:
|
||||
|
||||
``` yaml
|
||||
---
|
||||
- name: Playbook to enable per-zone privilege delegation
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Enable privilege delegation.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: testzone.local
|
||||
permission: true
|
||||
```
|
||||
|
||||
|
||||
Example playbook to remove a zone:
|
||||
```yaml
|
||||
@@ -223,6 +239,7 @@ Variable | Description | Required
|
||||
`ttl`| Time to live for records at zone apex | no
|
||||
`default_ttl`| Time to live for records without explicit TTL definition | no
|
||||
`nsec3param_rec`| NSEC3PARAM record for zone in format: hash_algorithm flags iterations salt | no
|
||||
`permission` \| `managedby` | Set per-zone access delegation permission. | no
|
||||
`skip_overlap_check`| Force DNS zone creation even if it will overlap with an existing zone | no
|
||||
`skip_nameserver_check` | Force DNS zone creation even if nameserver is not resolvable | no
|
||||
|
||||
@@ -238,4 +255,6 @@ Variable | Description | Returned When
|
||||
Authors
|
||||
=======
|
||||
|
||||
Sergio Oliveira Campos
|
||||
- Sergio Oliveira Campos
|
||||
- Thomas Woerner
|
||||
- Rafael Jeffman
|
||||
|
||||
@@ -142,6 +142,11 @@ options:
|
||||
salt.
|
||||
required: false
|
||||
type: str
|
||||
permission:
|
||||
description: Set per-zone access delegation permission.
|
||||
required: false
|
||||
type: bool
|
||||
aliases: ["managedby"]
|
||||
skip_overlap_check:
|
||||
description: |
|
||||
Force DNS zone creation even if it will overlap with an existing zone
|
||||
@@ -154,6 +159,7 @@ options:
|
||||
author:
|
||||
- Sergio Oliveira Campos (@seocam)
|
||||
- Thomas Woerner (@t-woerner)
|
||||
- Rafael Jeffman (@rjeffman)
|
||||
""" # noqa: E501
|
||||
|
||||
EXAMPLES = """
|
||||
@@ -253,6 +259,9 @@ class DNSZoneModule(IPAAnsibleModule):
|
||||
"idnsallowdynupdate": "dynamic_update",
|
||||
"idnssecinlinesigning": "dnssec",
|
||||
"idnsupdatepolicy": "update_policy",
|
||||
# FreeIPA uses 'managedby' for dnszone and dnsforwardzone
|
||||
# to manage 'permissions'.
|
||||
"managedby": "permission",
|
||||
# Mapping by method
|
||||
"idnsforwarders": self.get_ipa_idnsforwarders,
|
||||
"idnsallowtransfer": self.get_ipa_idnsallowtransfer,
|
||||
@@ -434,7 +443,7 @@ class DNSZoneModule(IPAAnsibleModule):
|
||||
is_zone_active = False
|
||||
else:
|
||||
zone = response["result"]
|
||||
# FreeIPA 4.9.10+ and 4.10 use proper mapping for boolean vaalues.
|
||||
# FreeIPA 4.9.10+ and 4.10 use proper mapping for boolean values.
|
||||
# See: https://github.com/freeipa/freeipa/pull/6294
|
||||
is_zone_active = (
|
||||
str(zone.get("idnszoneactive")[0]).upper() == "TRUE"
|
||||
@@ -462,18 +471,24 @@ class DNSZoneModule(IPAAnsibleModule):
|
||||
self.fail_json(
|
||||
msg="Either `name` or `name_from_ip` must be provided."
|
||||
)
|
||||
# check invalid parameters
|
||||
invalid = []
|
||||
if self.ipa_params.state != "present":
|
||||
invalid = ["name_from_ip"]
|
||||
|
||||
self.params_fail_used_invalid(invalid, self.ipa_params.state)
|
||||
invalid .extend(["name_from_ip"])
|
||||
if self.ipa_params.state == "absent":
|
||||
invalid.extend(["permission"])
|
||||
self.params_fail_used_invalid(invalid, self.ipa_params.state)
|
||||
|
||||
def define_ipa_commands(self):
|
||||
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.ipa_params.get_ipa_command_args(zone=zone)
|
||||
|
||||
if self.ipa_params.state in ["present", "enabled", "disabled"]:
|
||||
args = self.ipa_params.get_ipa_command_args(zone=zone)
|
||||
# We'll handle "managedby" after dnszone add/mod.
|
||||
args.pop("managedby", None)
|
||||
|
||||
if not zone:
|
||||
# Since the zone doesn't exist we just create it
|
||||
# with given args
|
||||
@@ -487,6 +502,16 @@ class DNSZoneModule(IPAAnsibleModule):
|
||||
if not compare_args_ipa(self, args, zone):
|
||||
self.commands.append((zone_name, "dnszone_mod", args))
|
||||
|
||||
# Permissions must be set on existing zones.
|
||||
if self.ipa_params.permission is not None:
|
||||
is_managed = zone.get("managedby")
|
||||
if self.ipa_params.permission and not is_managed:
|
||||
self.commands.append(
|
||||
(zone_name, "dnszone_add_permission", {}))
|
||||
if not self.ipa_params.permission and is_managed:
|
||||
self.commands.append(
|
||||
(zone_name, "dnszone_remove_permission", {}))
|
||||
|
||||
if self.ipa_params.state == "enabled" and not is_zone_active:
|
||||
self.commands.append((zone_name, "dnszone_enable", {}))
|
||||
|
||||
@@ -555,6 +580,8 @@ def get_argument_spec():
|
||||
ttl=dict(type="int", required=False, default=None),
|
||||
default_ttl=dict(type="int", required=False, default=None),
|
||||
nsec3param_rec=dict(type="str", required=False, default=None),
|
||||
permission=dict(type="bool", required=False, default=None,
|
||||
aliases=["managedby"]),
|
||||
skip_nameserver_check=dict(type="bool", required=False, default=None),
|
||||
skip_overlap_check=dict(type="bool", required=False, default=None),
|
||||
)
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
hosts: "{{ ipa_test_host | default('ipaserver') }}"
|
||||
become: true
|
||||
gather_facts: true
|
||||
module_defaults:
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
|
||||
tasks:
|
||||
|
||||
@@ -13,8 +17,6 @@
|
||||
# Tests
|
||||
- name: Check if zone is present, when it shouldn't be.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: present
|
||||
check_mode: yes
|
||||
@@ -23,8 +25,6 @@
|
||||
|
||||
- name: Check if zone is present again, when it shouldn't be.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: present
|
||||
check_mode: yes
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
- name: Ensure zone is present.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: present
|
||||
register: result
|
||||
@@ -42,8 +40,6 @@
|
||||
|
||||
- name: Check if zone is present, when it should be.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: present
|
||||
check_mode: yes
|
||||
@@ -52,8 +48,6 @@
|
||||
|
||||
- name: Ensure zone is present, again.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: present
|
||||
register: result
|
||||
@@ -61,8 +55,6 @@
|
||||
|
||||
- name: Ensure zone is disabled.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: disabled
|
||||
register: result
|
||||
@@ -70,8 +62,6 @@
|
||||
|
||||
- name: Ensure zone is disabled, again.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: disabled
|
||||
register: result
|
||||
@@ -79,8 +69,6 @@
|
||||
|
||||
- name: Ensure zone is enabled.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: enabled
|
||||
register: result
|
||||
@@ -88,8 +76,6 @@
|
||||
|
||||
- name: Ensure zone is enabled, again.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
state: enabled
|
||||
register: result
|
||||
@@ -97,8 +83,6 @@
|
||||
|
||||
- name: Ensure forward_policy is none.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forward_policy: none
|
||||
register: result
|
||||
@@ -106,8 +90,6 @@
|
||||
|
||||
- name: Ensure forward_policy is none, again.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forward_policy: none
|
||||
register: result
|
||||
@@ -115,8 +97,6 @@
|
||||
|
||||
- name: Ensure forward_policy is first.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forward_policy: first
|
||||
register: result
|
||||
@@ -124,8 +104,6 @@
|
||||
|
||||
- name: Ensure forward_policy is first, again.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forward_policy: first
|
||||
register: result
|
||||
@@ -133,8 +111,6 @@
|
||||
|
||||
- name: Ensure first forwarder is set.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forwarders:
|
||||
- ip_address: 8.8.8.8
|
||||
@@ -144,8 +120,6 @@
|
||||
|
||||
- name: Ensure first and second forwarder are set.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forwarders:
|
||||
- ip_address: 8.8.8.8
|
||||
@@ -156,8 +130,6 @@
|
||||
|
||||
- name: Ensure first and second forwarder are set, again.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forwarders:
|
||||
- ip_address: 8.8.8.8
|
||||
@@ -168,8 +140,6 @@
|
||||
|
||||
- name: Ensure only second forwarder is set.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forwarders:
|
||||
- ip_address: 2001:4860:4860::8888
|
||||
@@ -178,16 +148,12 @@
|
||||
|
||||
- name: Nothing changes.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure no forwarders are set.
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: testzone.local
|
||||
forwarders: []
|
||||
register: result
|
||||
@@ -195,56 +161,70 @@
|
||||
|
||||
- name: Create zones test1
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: test1.testzone.local
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Create zones test1, again
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: test1.testzone.local
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Create zones test2
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: test2.testzone.local
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Create zones test2, again
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: test2.testzone.local
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Create zones test3
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: test3.testzone.local
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Create zones test3, again
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: test3.testzone.local
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure zone test1.testzone.local has management permissioon
|
||||
ipadnszone:
|
||||
name: test1.testzone.local
|
||||
permission: true
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure zone test1.testzone.local has management permissioon
|
||||
ipadnszone:
|
||||
name: test1.testzone.local
|
||||
permission: true
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure zone test1.testzone.local don't have management permissioon
|
||||
ipadnszone:
|
||||
name: test1.testzone.local
|
||||
permission: false
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure zone test1.testzone.local don't have management permissioon
|
||||
ipadnszone:
|
||||
name: test1.testzone.local
|
||||
permission: false
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure multiple zones are absent
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name:
|
||||
- test1.testzone.local
|
||||
- test2.testzone.local
|
||||
@@ -255,8 +235,6 @@
|
||||
|
||||
- name: Ensure multiple zones are absent, again
|
||||
ipadnszone:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name:
|
||||
- test1.testzone.local
|
||||
- test2.testzone.local
|
||||
|
||||
Reference in New Issue
Block a user