diff --git a/roles/ipaclient/README.md b/roles/ipaclient/README.md index 726856c7..3c09d129 100644 --- a/roles/ipaclient/README.md +++ b/roles/ipaclient/README.md @@ -202,6 +202,8 @@ Variable | Description | Required `ipaclient_request_cert` | The bool value defines if the certificate for the machine wil be requested. The certificate will be stored in /etc/ipa/nssdb under the nickname "Local IPA host". . `ipaclient_request_cert` defaults to `no`. The option is deprecated and will be removed in a future release. | no `ipaclient_keytab` | The string value contains the path on the node of a backup host keytab from a previous enrollment. | no `ipaclient_automount_location` | Automount location | no +`ipaclient_dns_over_tls` | Configure DNS over TLS. Requires FreeIPA version 4.12.5 or later. (bool, default: false) | no +`ipaclient_no_dnssec_validation` | Disable DNSSEC validation for DNS over TLS. This turns off DNSSEC validation for unbound. Ignored if `ipaserver_dns_over_tls` is not enabled. (bool, default: false) | no Server Variables diff --git a/roles/ipaclient/defaults/main.yml b/roles/ipaclient/defaults/main.yml index b6e912f2..ab8f3f02 100644 --- a/roles/ipaclient/defaults/main.yml +++ b/roles/ipaclient/defaults/main.yml @@ -26,6 +26,8 @@ ipasssd_enable_dns_updates: no ipasssd_no_krb5_offline_passwords: no ipasssd_preserve_sssd: no ipaclient_request_cert: no +ipaclient_dns_over_tls: no +ipaclient_no_dnssec_validation: no ### packages ### ipaclient_install_packages: yes diff --git a/roles/ipaclient/library/ipaclient_setup_nss.py b/roles/ipaclient/library/ipaclient_setup_nss.py index d9fdda68..6ab4186d 100644 --- a/roles/ipaclient/library/ipaclient_setup_nss.py +++ b/roles/ipaclient/library/ipaclient_setup_nss.py @@ -86,6 +86,16 @@ options: type: bool required: no default: no + dns_over_tls: + description: Configure DNS over TLS + type: bool + default: no + required: no + no_dnssec_validation: + description: Disable DNSSEC validation for DNS over TLS + type: bool + default: no + required: no enable_dns_updates: description: | Configures the machine to attempt dns updates when the ip address @@ -212,7 +222,9 @@ def main(): mkhomedir=dict(required=False, type='bool'), on_master=dict(required=False, type='bool'), dnsok=dict(required=False, type='bool', default=False), - + dns_over_tls=dict(required=False, type='bool', default=False), + no_dnssec_validation=dict(required=False, type='bool', + default=False), enable_dns_updates=dict(required=False, type='bool'), all_ip_addresses=dict(required=False, type='bool', default=False), ip_addresses=dict(required=False, type='list', elements='str', @@ -249,6 +261,8 @@ def main(): options.mkhomedir = module.params.get('mkhomedir') options.on_master = module.params.get('on_master') dnsok = module.params.get('dnsok') + options.dns_over_tls = module.params.get('dns_over_tls') + options.no_dnssec_validation = module.params.get('no_dnssec_validation') fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) @@ -256,6 +270,7 @@ def main(): os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE options.dns_updates = module.params.get('enable_dns_updates') + options.dns_over_tls = module.params.get('dns_over_tls') options.all_ip_addresses = module.params.get('all_ip_addresses') options.ip_addresses = ansible_module_get_parsed_ip_addresses(module) options.request_cert = module.params.get('request_cert') @@ -279,7 +294,7 @@ def main(): options.no_sssd = False options.sssd = not options.no_sssd options.no_ac = False - options.dns_over_tls = False + options.dns_over_tls = module.params.get('dns_over_tls') nosssd_files = module.params.get('nosssd_files') selinux_works = module.params.get('selinux_works') krb_name = module.params.get('krb_name') diff --git a/roles/ipaclient/library/ipaclient_setup_sssd.py b/roles/ipaclient/library/ipaclient_setup_sssd.py index 434ec73a..d12b71f4 100644 --- a/roles/ipaclient/library/ipaclient_setup_sssd.py +++ b/roles/ipaclient/library/ipaclient_setup_sssd.py @@ -91,6 +91,11 @@ options: changes type: bool required: no + dns_over_tls: + description: Configure DNS over TLS + type: bool + default: no + required: no preserve_sssd: description: Preserve old SSSD configuration if possible type: bool @@ -140,6 +145,7 @@ def main(): fixed_primary=dict(required=False, type='bool'), permit=dict(required=False, type='bool'), enable_dns_updates=dict(required=False, type='bool'), + dns_over_tls=dict(required=False, type='bool', default=False), preserve_sssd=dict(required=False, type='bool'), no_krb5_offline_passwords=dict(required=False, type='bool'), ), @@ -169,6 +175,7 @@ def main(): options.primary = module.params.get('fixed_primary') options.permit = module.params.get('permit') options.dns_updates = module.params.get('enable_dns_updates') + options.dns_over_tls = module.params.get('dns_over_tls') options.preserve_sssd = module.params.get('preserve_sssd') options.no_krb5_offline_passwords = module.params.get( diff --git a/roles/ipaclient/library/ipaclient_test.py b/roles/ipaclient/library/ipaclient_test.py index 75970c58..b90ae943 100644 --- a/roles/ipaclient/library/ipaclient_test.py +++ b/roles/ipaclient/library/ipaclient_test.py @@ -124,6 +124,16 @@ options: type: bool required: no default: no + dns_over_tls: + description: Configure DNS over TLS + type: bool + default: no + required: no + no_dnssec_validation: + description: Disable DNSSEC validation for DNS over TLS + type: bool + default: no + required: no enable_dns_updates: description: Configures the machine to attempt dns updates when the ip address @@ -248,7 +258,8 @@ from ansible.module_utils.ansible_ipa_client import ( CLIENT_INSTALL_ERROR, tasks, check_ldap_conf, timeconf, constants, validate_hostname, nssldap_exists, gssapi, remove_file, check_ip_addresses, ipadiscovery, print_port_conf_info, - IPA_PYTHON_VERSION, getargspec + IPA_PYTHON_VERSION, getargspec, services, + CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION ) @@ -328,6 +339,9 @@ def main(): default=None), all_ip_addresses=dict(required=False, type='bool', default=False), on_master=dict(required=False, type='bool', default=False), + dns_over_tls=dict(required=False, type='bool', default=False), + no_dnssec_validation=dict(required=False, type='bool', + default=False), # sssd enable_dns_updates=dict(required=False, type='bool', default=False), @@ -356,6 +370,8 @@ def main(): options.ip_addresses = module.params.get('ip_addresses') options.all_ip_addresses = module.params.get('all_ip_addresses') options.on_master = module.params.get('on_master') + options.dns_over_tls = module.params.get('dns_over_tls') + options.no_dnssec_validation = module.params.get('no_dnssec_validation') options.enable_dns_updates = module.params.get('enable_dns_updates') # Get domain from first server if domain is not set, but if there are @@ -365,6 +381,16 @@ def main(): options.domain_name = options.servers[0][ options.servers[0].find(".") + 1:] + if options.dns_over_tls \ + and not services.knownservices["unbound"].is_installed(): + module.fail_json( + msg="To enable DNS over TLS, package ipa-client-encrypted-dns " + "must be installed.") + if options.dns_over_tls and not CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION: + module.fail_json( + msg="Important patches for DNS over TLS are missing in your IPA " + "version.") + try: self = options diff --git a/roles/ipaclient/module_utils/ansible_ipa_client.py b/roles/ipaclient/module_utils/ansible_ipa_client.py index 1a3a974e..08ced240 100644 --- a/roles/ipaclient/module_utils/ansible_ipa_client.py +++ b/roles/ipaclient/module_utils/ansible_ipa_client.py @@ -310,6 +310,15 @@ try: except ImportError: configure_selinux_for_client = None + try: + CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = False + from ipaclient.install.client import ClientInstallInterface + except ImportError: + pass + else: + if hasattr(ClientInstallInterface, "no_dnssec_validation"): + CLIENT_SUPPORTS_NO_DNSSEC_VALIDATION = True + logger = logging.getLogger("ipa-client-install") root_logger = logger diff --git a/roles/ipaclient/tasks/install.yml b/roles/ipaclient/tasks/install.yml index ae9b0669..ca56be3d 100644 --- a/roles/ipaclient/tasks/install.yml +++ b/roles/ipaclient/tasks/install.yml @@ -1,11 +1,23 @@ --- # tasks file for ipaclient -- name: Install - Ensure that IPA client packages are installed - ansible.builtin.package: - name: "{{ ipaclient_packages }}" - state: present +- name: Install - Package installation when: ipaclient_install_packages | bool + block: + + - name: Install - Set packages for installation + ansible.builtin.set_fact: + _ipapackages: "{{ ipaclient_packages }}" + + - name: Install - Set packages for installlation, add DOT + ansible.builtin.set_fact: + _ipapackages: "{{ _ipapackages + ipaclient_packages_dot }}" + when: ipaclient_dns_over_tls | bool + + - name: Install - Ensure that packages are installed + ansible.builtin.package: + name: "{{ _ipapackages }}" + state: present - name: Install - Set ipaclient_servers ansible.builtin.set_fact: @@ -38,7 +50,7 @@ msg: "ipaclient_domain or ipaserver_domain is required for ipaclient_configure_dns_resolver" when: ipaserver_domain is not defined and ipaclient_domain is not defined - - name: Install - Fail on missing ipaclient_servers + - name: Install - Fail on missing ipaclient_dns_servers ansible.builtin.fail: msg: "ipaclient_dns_servers is required for ipaclient_configure_dns_resolver" when: ipaclient_dns_servers is not defined @@ -69,6 +81,8 @@ ip_addresses: "{{ ipaclient_ip_addresses | default(omit) }}" all_ip_addresses: "{{ ipaclient_all_ip_addresses }}" on_master: "{{ ipaclient_on_master }}" + dns_over_tls: "{{ ipaclient_dns_over_tls }}" + no_dnssec_validation: "{{ ipaclient_no_dnssec_validation }}" ### sssd ### enable_dns_updates: "{{ ipasssd_enable_dns_updates }}" register: result_ipaclient_test @@ -323,6 +337,7 @@ fixed_primary: "{{ ipasssd_fixed_primary }}" permit: "{{ ipasssd_permit }}" enable_dns_updates: "{{ ipasssd_enable_dns_updates }}" + dns_over_tls: "{{ ipaclient_dns_over_tls }}" preserve_sssd: "{{ ipasssd_preserve_sssd }}" no_krb5_offline_passwords: "{{ ipasssd_no_krb5_offline_passwords }}" @@ -360,6 +375,8 @@ on_master: "{{ ipaclient_on_master }}" dnsok: "{{ result_ipaclient_test.dnsok }}" enable_dns_updates: "{{ ipasssd_enable_dns_updates }}" + dns_over_tls: "{{ ipaclient_dns_over_tls }}" + no_dnssec_validation: "{{ ipaclient_no_dnssec_validation }}" all_ip_addresses: "{{ ipaclient_all_ip_addresses }}" ip_addresses: "{{ ipaclient_ip_addresses | default(omit) }}" request_cert: "{{ ipaclient_request_cert }}" diff --git a/roles/ipaclient/vars/Debian-10.yml b/roles/ipaclient/vars/Debian-10.yml index 8de5dc8e..2beaa8b7 100644 --- a/roles/ipaclient/vars/Debian-10.yml +++ b/roles/ipaclient/vars/Debian-10.yml @@ -1,6 +1,7 @@ --- # vars/Debian.yml ipaclient_packages: [ "freeipa-client" ] +ipaclient_packages_dot: [ ] # Debian Buster must use python2 as Python interpreter due # to the way freeipa-client package is defined. # You must install package python2.7 before executing this role. diff --git a/roles/ipaclient/vars/Debian.yml b/roles/ipaclient/vars/Debian.yml index efa7c4d4..73fc7909 100644 --- a/roles/ipaclient/vars/Debian.yml +++ b/roles/ipaclient/vars/Debian.yml @@ -2,3 +2,4 @@ # vars/Debian.yml --- ipaclient_packages: [ "freeipa-client" ] +ipaclient_packages_dot: [ ] diff --git a/roles/ipaclient/vars/RedHat-7.yml b/roles/ipaclient/vars/RedHat-7.yml index c154c99f..3e7f75b6 100644 --- a/roles/ipaclient/vars/RedHat-7.yml +++ b/roles/ipaclient/vars/RedHat-7.yml @@ -2,3 +2,4 @@ # vars/RedHat-7 --- ipaclient_packages: [ "ipa-client", "libselinux-python" ] +ipaclient_packages_dot: [ ] diff --git a/roles/ipaclient/vars/RedHat-8.yml b/roles/ipaclient/vars/RedHat-8.yml index 65b554e0..f663c694 100644 --- a/roles/ipaclient/vars/RedHat-8.yml +++ b/roles/ipaclient/vars/RedHat-8.yml @@ -2,3 +2,4 @@ # vars/RedHat-8.yml --- ipaclient_packages: [ "@idm:DL1/client" ] +ipaclient_packages_dot: [ ] diff --git a/roles/ipaclient/vars/Ubuntu-18.04.yml b/roles/ipaclient/vars/Ubuntu-18.04.yml index e01f5021..44a638ca 100644 --- a/roles/ipaclient/vars/Ubuntu-18.04.yml +++ b/roles/ipaclient/vars/Ubuntu-18.04.yml @@ -1,6 +1,7 @@ # vars/Ubuntu-18.04.yml --- ipaclient_packages: [ "freeipa-client" ] +ipaclient_packages_dot: [ ] # Ubuntu Bionic Beaver must use python2 as Python interpreter due # to the way python-ipalib package is defined. # Package python2.7 must be installed before executing this role. diff --git a/roles/ipaclient/vars/default.yml b/roles/ipaclient/vars/default.yml index 2cfb3614..2b2ce88f 100644 --- a/roles/ipaclient/vars/default.yml +++ b/roles/ipaclient/vars/default.yml @@ -2,3 +2,4 @@ # vars/default.yml --- ipaclient_packages: [ "ipa-client", "python3-libselinux" ] +ipaclient_packages_dot: [ "ipa-client-encrypted-dns" ]