Skip to content

Commit cd440a2

Browse files
committed
ipareplica: Add support for DNS over TLS
This change adds support for DNS over TLS to the ipareplica role. New variables ipareplica_dot_forwarders List of DNS over TLS forwarders. Required if ipareplica_dns_over_tls is enabled. (list of strings) required: false ipareplica_dns_over_tls | ipaclient_dns_over_tls Configure DNS over TLS. Requires FreeIPA version 4.12.5 or later. (bool, default: false) required: false ipareplica_dns_over_tls_cert Certificate to use for DNS over TLS. If empty, a new certificate will be requested from IPA CA. (string) required: false ipareplica_dns_over_tls_key Key for certificate specified in ipareplica_dns_over_tls_cert. (string) required: false ipareplica_dns_policy Encrypted DNS policy. Only usable if `ipareplica_dns_over_tls` is enabled. (choice: relaxed, enforced, default: relaxed) required: false New distribution specific variable ipareplica_packages_dot List of IPA packages needed for DNS over TLS.
1 parent e2317f3 commit cd440a2

File tree

12 files changed

+234
-26
lines changed

12 files changed

+234
-26
lines changed

roles/ipareplica/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ Variable | Description | Required
270270
`ipareplica_auto_forwarders` | Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS. (bool, default: false) | no
271271
`ipareplica_forward_policy` | DNS forwarding policy for global forwarders specified using other options. (choice: first,only) | no
272272
`ipareplica_no_dnssec_validation` | Disable DNSSEC validation on this server. (bool, default: false) | no
273+
`ipareplica_dot_forwarders` | List of DNS over TLS forwarders. Required if `ipareplica_dns_over_tls` is enabled. (list of strings) | no
274+
`ipareplica_dns_over_tls` \| `ipaclient_dns_over_tls` | Configure DNS over TLS. Requires FreeIPA version 4.12.5 or later. (bool, default: false) | no
275+
`ipareplica_dns_over_tls_cert` | Certificate to use for DNS over TLS. If empty, a new certificate will be requested from IPA CA. (string) | no
276+
`ipareplica_dns_over_tls_key` | Key for certificate specified in `ipareplica_dns_over_tls_cert`. (string) | no
277+
`ipareplica_dns_policy` | Encrypted DNS policy. Only usable if `ipareplica_dns_over_tls` is enabled. (choice: relaxed, enforced, default: relaxed) | no
273278

274279
AD trust Variables
275280
------------------

roles/ipareplica/library/ipareplica_prepare.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,32 @@
224224
type: bool
225225
default: no
226226
required: no
227+
dot_forwarders:
228+
description: List of DNS over TLS forwarders
229+
type: list
230+
elements: str
231+
default: []
232+
required: no
233+
dns_over_tls:
234+
description: Configure DNS over TLS
235+
type: bool
236+
default: no
237+
required: no
238+
dns_over_tls_cert:
239+
description:
240+
Certificate to use for DNS over TLS. If empty, a new
241+
certificate will be requested from IPA CA
242+
type: str
243+
required: no
244+
dns_over_tls_key:
245+
description: Key for certificate specified in dns_over_tls_cert
246+
type: str
247+
required: no
248+
dns_policy:
249+
description: Encrypted DNS policy
250+
type: str
251+
choices: ['relaxed', 'enforced']
252+
default: 'relaxed'
227253
enable_compat:
228254
description: Enable support for trusted domains for old clients
229255
type: bool
@@ -354,6 +380,15 @@ def main():
354380
choices=['first', 'only'], default=None),
355381
no_dnssec_validation=dict(required=False, type='bool',
356382
default=False),
383+
dot_forwarders=dict(required=False, type='list', elements='str',
384+
default=[]),
385+
dns_over_tls=dict(required=False, type='bool',
386+
default=False),
387+
dns_over_tls_cert=dict(required=False, type='str'),
388+
dns_over_tls_key=dict(required=False, type='str'),
389+
dns_policy=dict(required=False, type='str',
390+
choices=['relaxed', 'enforced'],
391+
default='relaxed'),
357392
# ad trust
358393
enable_compat=dict(required=False, type='bool', default=False),
359394
netbios_name=dict(required=False, type='str'),
@@ -430,6 +465,11 @@ def main():
430465
options.forward_policy = ansible_module.params.get('forward_policy')
431466
options.no_dnssec_validation = ansible_module.params.get(
432467
'no_dnssec_validation')
468+
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
469+
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
470+
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
471+
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
472+
options.dns_policy = ansible_module.params.get('dns_policy')
433473
# ad trust
434474
options.enable_compat = ansible_module.params.get('enable_compat')
435475
options.netbios_name = ansible_module.params.get('netbios_name')

roles/ipareplica/library/ipareplica_setup_dns.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,32 @@
7272
type: bool
7373
default: no
7474
required: no
75+
dot_forwarders:
76+
description: List of DNS over TLS forwarders
77+
type: list
78+
elements: str
79+
default: []
80+
required: no
81+
dns_over_tls:
82+
description: Configure DNS over TLS
83+
type: bool
84+
default: no
85+
required: no
86+
dns_over_tls_cert:
87+
description:
88+
Certificate to use for DNS over TLS. If empty, a new
89+
certificate will be requested from IPA CA
90+
type: str
91+
required: no
92+
dns_over_tls_key:
93+
description: Key for certificate specified in dns_over_tls_cert
94+
type: str
95+
required: no
96+
dns_policy:
97+
description: Encrypted DNS policy
98+
type: str
99+
choices: ['relaxed', 'enforced']
100+
default: 'relaxed'
75101
dns_ip_addresses:
76102
description: The dns ip_addresses setting
77103
type: list
@@ -117,6 +143,9 @@
117143
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, dns,
118144
ansible_module_get_parsed_ip_addresses
119145
)
146+
# pylint: disable=unused-import
147+
from ansible.module_utils.ansible_ipa_replica import bindinstance # noqa: F401
148+
# pylint: enable=unused-import
120149

121150

122151
def main():
@@ -135,6 +164,14 @@ def main():
135164
choices=['first', 'only'], default=None),
136165
no_dnssec_validation=dict(required=False, type='bool',
137166
default=False),
167+
dot_forwarders=dict(required=False, type='list', elements='str',
168+
default=[]),
169+
dns_over_tls=dict(required=False, type='bool', default=False),
170+
dns_over_tls_cert=dict(required=False, type='str'),
171+
dns_over_tls_key=dict(required=False, type='str'),
172+
dns_policy=dict(required=False, type='str',
173+
choices=['relaxed', 'enforced'],
174+
default='relaxed'),
138175
# additional
139176
dns_ip_addresses=dict(required=True, type='list', elements='str'),
140177
dns_reverse_zones=dict(required=True, type='list', elements='str'),
@@ -167,6 +204,11 @@ def main():
167204
options.forward_policy = ansible_module.params.get('forward_policy')
168205
options.no_dnssec_validation = ansible_module.params.get(
169206
'no_dnssec_validation')
207+
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
208+
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
209+
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
210+
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
211+
options.dns_policy = ansible_module.params.get('dns_policy')
170212
# additional
171213
dns.ip_addresses = ansible_module_get_parsed_ip_addresses(
172214
ansible_module, 'dns_ip_addresses')

roles/ipareplica/library/ipareplica_test.py

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,32 @@
181181
type: bool
182182
default: no
183183
required: no
184+
dot_forwarders:
185+
description: List of DNS over TLS forwarders
186+
type: list
187+
elements: str
188+
default: []
189+
required: no
190+
dns_over_tls:
191+
description: Configure DNS over TLS
192+
type: bool
193+
default: no
194+
required: no
195+
dns_over_tls_cert:
196+
description:
197+
Certificate to use for DNS over TLS. If empty, a new
198+
certificate will be requested from IPA CA
199+
type: str
200+
required: no
201+
dns_over_tls_key:
202+
description: Key for certificate specified in dns_over_tls_cert
203+
type: str
204+
required: no
205+
dns_policy:
206+
description: Encrypted DNS policy
207+
type: str
208+
choices: ['relaxed', 'enforced']
209+
default: 'relaxed'
184210
author:
185211
- Thomas Woerner (@t-woerner)
186212
'''
@@ -199,7 +225,8 @@
199225
paths, sysrestore, ansible_module_get_parsed_ip_addresses, service,
200226
redirect_stdout, create_ipa_conf, ipautil,
201227
x509, validate_domain_name, common_check,
202-
IPA_PYTHON_VERSION, getargspec, adtrustinstance, install_ca_cert
228+
IPA_PYTHON_VERSION, getargspec, adtrustinstance, install_ca_cert,
229+
services, CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION
203230
)
204231

205232

@@ -250,6 +277,14 @@ def main():
250277
choices=['first', 'only'], default=None),
251278
no_dnssec_validation=dict(required=False, type='bool',
252279
default=False),
280+
dot_forwarders=dict(required=False, type='list', elements='str',
281+
default=[]),
282+
dns_over_tls=dict(required=False, type='bool', default=False),
283+
dns_over_tls_cert=dict(required=False, type='str'),
284+
dns_over_tls_key=dict(required=False, type='str'),
285+
dns_policy=dict(required=False, type='str',
286+
choices=['relaxed', 'enforced'],
287+
default='relaxed'),
253288
),
254289
)
255290

@@ -298,6 +333,11 @@ def main():
298333
options.forward_policy = ansible_module.params.get('forward_policy')
299334
options.no_dnssec_validation = ansible_module.params.get(
300335
'no_dnssec_validation')
336+
options.dot_forwarders = ansible_module.params.get('dot_forwarders')
337+
options.dns_over_tls = ansible_module.params.get('dns_over_tls')
338+
options.dns_over_tls_cert = ansible_module.params.get('dns_over_tls_cert')
339+
options.dns_over_tls_key = ansible_module.params.get('dns_over_tls_key')
340+
options.dns_policy = ansible_module.params.get('dns_policy')
301341

302342
##########################################################################
303343
# replica init ###########################################################
@@ -419,6 +459,14 @@ def main():
419459
ansible_module.fail_json(
420460
msg="You cannot specify a --no-dnssec-validation option "
421461
"without the --setup-dns option")
462+
if installer.dns_over_tls_cert:
463+
ansible_module.fail_json(
464+
msg="You cannot specify a --dns-over-tls-cert option "
465+
"without the --setup-dns option")
466+
if installer.dns_over_tls_key:
467+
ansible_module.fail_json(
468+
msg="You cannot specify a --dns-over-tls-key option "
469+
"without the --setup-dns option")
422470
elif installer.forwarders and installer.no_forwarders:
423471
ansible_module.fail_json(
424472
msg="You cannot specify a --forwarder option together with "
@@ -435,6 +483,31 @@ def main():
435483
ansible_module.fail_json(
436484
msg="You cannot specify a --auto-reverse option together with "
437485
"--no-reverse")
486+
elif installer.dot_forwarders and not installer.dns_over_tls:
487+
ansible_module.fail_json(
488+
msg="You cannot specify a --dot-forwarder option "
489+
"without the --dns-over-tls option")
490+
elif (installer.dns_over_tls
491+
and not services.knownservices["unbound"].is_installed()):
492+
ansible_module.fail_json(
493+
msg="To enable DNS over TLS, package ipa-server-encrypted-dns "
494+
"must be installed.")
495+
elif installer.dns_policy == "enforced" and not installer.dns_over_tls:
496+
ansible_module.fail_json(
497+
msg="You cannot specify a --dns-policy option "
498+
"without the --dns-over-tls option")
499+
elif installer.dns_over_tls_cert and not installer.dns_over_tls:
500+
ansible_module.fail_json(
501+
msg="You cannot specify a --dns-over-tls-cert option "
502+
"without the --dns-over-tls option")
503+
elif installer.dns_over_tls_key and not installer.dns_over_tls:
504+
ansible_module.fail_json(
505+
msg="You cannot specify a --dns-over-tls-key option "
506+
"without the --dns-over-tls option")
507+
elif bool(installer.dns_over_tls_key) != bool(installer.dns_over_tls_cert):
508+
ansible_module.fail_json(
509+
msg="You cannot specify a --dns-over-tls-key option "
510+
"without the --dns-over-tls-cert option and vice versa")
438511

439512
# replica installers
440513
if installer.servers and not installer.domain_name:
@@ -449,6 +522,10 @@ def main():
449522
ansible_module.fail_json(
450523
msg="You must specify at least one of --forwarder, "
451524
"--auto-forwarders, or --no-forwarders options")
525+
if installer.dns_over_tls and not installer.dot_forwarders:
526+
ansible_module.fail_json(
527+
msg="You must specify --dot-forwarder "
528+
"when enabling DNS over TLS")
452529

453530
if installer.dirsrv_config_file is not None and \
454531
not os.path.exists(installer.dirsrv_config_file):
@@ -486,6 +563,11 @@ def main():
486563
if installer.domain_name is not None:
487564
validate_domain_name(installer.domain_name)
488565

566+
if installer.dns_over_tls and not CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION:
567+
ansible_module.fail_json(
568+
msg="Important patches for DNS over TLS are missing in your "
569+
"IPA version.")
570+
489571
##########################################################################
490572
# replica promote_check excerpts #########################################
491573
##########################################################################

roles/ipareplica/module_utils/ansible_ipa_replica.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ def getargspec(func):
187187
from ipaserver.install import ntpinstance
188188
time_service = "ntpd" # pylint: disable=invalid-name
189189

190+
try:
191+
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = False
192+
from ipaclient.install.client import ClientInstallInterface
193+
except ImportError:
194+
pass
195+
else:
196+
if hasattr(ClientInstallInterface, "no_dnssec_validation"):
197+
CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = True
190198
else:
191199
# IPA version < 4.6
192200
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
@@ -337,12 +345,6 @@ def knobs(self):
337345
options.subject_base = None
338346
options.ca_subject = None
339347

340-
# Hotfix for https://github.com/freeipa/freeipa/pull/7343
341-
options.dns_over_tls = False
342-
options.dns_over_tls_key = None
343-
options.dns_over_tls_cert = None
344-
options.dot_forwarders = None
345-
options.dns_policy = None
346348
# pylint: enable=attribute-defined-outside-init
347349

348350

0 commit comments

Comments
 (0)