diff --git a/roles/freeipa_client/defaults/main.yml b/roles/freeipa_client/defaults/main.yml new file mode 100644 index 00000000..25ec0b38 --- /dev/null +++ b/roles/freeipa_client/defaults/main.yml @@ -0,0 +1,25 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ipaserver_domain: +# ipaserver_realm: +# ipa_hosts: # List of FQDN of IPA hosts +# ipa_server_ips: # List of IP of IPA hosts +# ipaadmin_principal: +# ipaadmin_password: + +enable_dns: false +fallback_nameservers: [ "8.8.8.8" ] diff --git a/roles/freeipa_client/handlers/main.yml b/roles/freeipa_client/handlers/main.yml new file mode 100644 index 00000000..e1d74e4c --- /dev/null +++ b/roles/freeipa_client/handlers/main.yml @@ -0,0 +1,18 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: restart host + ansible.builtin.reboot: diff --git a/roles/freeipa_client/meta/main.yml b/roles/freeipa_client/meta/main.yml new file mode 100644 index 00000000..100b9b28 --- /dev/null +++ b/roles/freeipa_client/meta/main.yml @@ -0,0 +1,44 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +galaxy_info: + role_name: freeipa_client + namespace: cloudera + author: Webster Mudge Jim Enright Chuck Levesque + description: > + Deployment of FreeIPA clients for Cloudera Data Platform (CDP) Base and ECS + company: Cloudera + namespace: cloudera + license: Apache-2.0 + + min_ansible_version: 2.10 + + platforms: + - name: Debian + versions: all + - name: Fedora + versions: all + - name: GenericLinux + versions: all + - name: MacOSX + versions: all + - name: Ubuntu + versions: all + + galaxy_tags: + - cloudera + - cdp + - freeipa diff --git a/roles/freeipa_client/tasks/main.yml b/roles/freeipa_client/tasks/main.yml new file mode 100644 index 00000000..f3cb5aa2 --- /dev/null +++ b/roles/freeipa_client/tasks/main.yml @@ -0,0 +1,104 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: Disable SELinux + ansible.builtin.selinux: + state: disabled + notify: restart host + +- name: Set up DNS and networking + when: enable_dns + block: + - name: Update RHEL networking + when: ansible_facts['os_family'] == 'RedHat' + block: + - name: Set cloud-init to preserve hostname (RHEL) + ansible.builtin.lineinfile: + path: /etc/cloud/cloud.cfg + regex: "^(#)?preserve_hostname" + line: "preserve_hostname: 1" + state: present + notify: restart host + + - name: Set interface config to preserve resolv.conf changes (RHEL)' + ansible.builtin.lineinfile: + path: "/etc/sysconfig/network-scripts/ifcfg-{{ ansible_default_ipv4.interface }}" + regex: "^(#)?PEERDNS" + line: "PEERDNS=no" + state: present + notify: restart host + + - name: Set /etc/NetworkManager/conf.d/disable-resolve.conf-managing.conf (RHEL) + ansible.builtin.copy: + dest: /etc/NetworkManager/conf.d/disable-resolve.conf-managing.conf + content: | + # Generated by Ansible + [main] + dns=none + notify: restart host + + - name: Set /etc/resolv.conf directly + ansible.builtin.copy: + dest: /etc/resolv.conf + content: | + # Generated by Ansible + search {{ ipaserver_domain }} + {{ ['nameserver '] | product(ipa_server_ips | sort) | map('join') | join('\n') }} + notify: restart host + + - name: Set /etc/hostname to the FQDN + ansible.builtin.copy: + content: "{{ inventory_hostname }}" + dest: /etc/hostname + notify: restart host + + - name: Set /etc/hosts + ansible.builtin.copy: + dest: /etc/hosts + content: | + # Set by Ansible + {{ ansible_default_ipv4.address }} {{ inventory_hostname }} {{ inventory_hostname_short }} + notify: restart host + + - name: Set /etc/dhcp/dhclient.conf for domain search and name servers + ansible.builtin.lineinfile: + path: /etc/dhcp/dhclient.conf + regex: "^(#)?{{ dhclient_entry.value }}" + line: "{{ dhclient_entry.value }}" + state: present + loop: "{{ entries | dict2items }}" + loop_control: + loop_var: dhclient_entry + label: "{{ dhclient_entry.key }}" + vars: + entries: + domain_search: supersede domain-search "{{ ipaserver_domain }}"; + domain_name_servers: supersede domain-name-servers {{ ipa_server_ips | sort | union(fallback_nameservers) | join(', ') }}; + notify: restart host + +- name: Flush handlers + ansible.builtin.meta: flush_handlers + +- name: Set up the FreeIPA Client + ansible.builtin.include_role: + name: freeipa.ansible_freeipa.ipaclient + vars: + state: present + ipaclient_hostname: "{{ inventory_hostname }}" + ipaclient_servers: "{{ ipa_hosts }}" + ipaserver_setup_dns: "{{ enable_dns }}" + ipasssd_enable_dns_updates: "{{ enable_dns }}" + ipaclient_mkhomedir: yes diff --git a/roles/freeipa_server/defaults/main.yml b/roles/freeipa_server/defaults/main.yml new file mode 100644 index 00000000..83da2a81 --- /dev/null +++ b/roles/freeipa_server/defaults/main.yml @@ -0,0 +1,27 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#ipaserver_realm: "{{ krb5_realm | upper }}" +#ipaserver_domain: "{{ krb5_domain | default(krb5_realm | lower) }}" +#ipaserver_setup_firewalld: "no" +#ipaserver_setup_dns: "{{ freeipa_autodns | default(omit) }}" +#ipaserver_auto_forwarders: +#ipadm_password: + +# ipaserver_recursion_acl_cidr: +ipaserver_resolv_nameservers: [ '8.8.8.8' ] +ipaserver_server_recursion: true +enable_dns: false diff --git a/roles/freeipa_server/handlers/main.yml b/roles/freeipa_server/handlers/main.yml new file mode 100644 index 00000000..b73b6ffe --- /dev/null +++ b/roles/freeipa_server/handlers/main.yml @@ -0,0 +1,23 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: restart host + ansible.builtin.reboot: + +- name: restart dns + ansible.builtin.service: + name: named-pkcs11 + state: restarted diff --git a/roles/freeipa_server/meta/main.yml b/roles/freeipa_server/meta/main.yml new file mode 100644 index 00000000..0d01516e --- /dev/null +++ b/roles/freeipa_server/meta/main.yml @@ -0,0 +1,44 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +galaxy_info: + role_name: freeipa_server + namespace: cloudera + author: Webster Mudge Jim Enright Chuck Levesque + description: > + Deployment of sidecar FreeIPA Server for Cloudera Data Platform (CDP) Base and ECS + company: Cloudera + namespace: cloudera + license: Apache-2.0 + + min_ansible_version: 2.10 + + platforms: + - name: Debian + versions: all + - name: Fedora + versions: all + - name: GenericLinux + versions: all + - name: MacOSX + versions: all + - name: Ubuntu + versions: all + + galaxy_tags: + - cloudera + - cdp + - freeipa diff --git a/roles/freeipa_server/tasks/main.yml b/roles/freeipa_server/tasks/main.yml new file mode 100644 index 00000000..377408af --- /dev/null +++ b/roles/freeipa_server/tasks/main.yml @@ -0,0 +1,179 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: Include OS-specific variables + ansible.builtin.include_vars: "{{ item }}" + with_first_found: + - "{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml" + - "{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml" + - "{{ ansible_facts['distribution'] }}.yml" + - "{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml" + - "{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml" + - "{{ ansible_facts['os_family'] }}.yml" + - "default.yml" + +- name: Update NSS to the latest version + ansible.builtin.package: + name: nss + state: latest + +- name: Install Python and supporting packages + ansible.builtin.package: + lock_timeout: 180 + name: "{{ __pyver_item }}" + update_cache: yes + state: present + loop: + - python3 + - python2 + loop_control: + loop_var: __pyver_item + +- name: Disable SELinux + ansible.builtin.selinux: + state: disabled + notify: restart host + +- name: Install base FreeIPA server packages + ansible.builtin.package: + name: "{{ ipaserver_packages }}" + state: present + +- name: Set up DNS and networking + when: ipaserver_setup_dns + block: + - name: Configure RHEL systems + when: ansible_facts['os_family'] == 'RedHat' + block: + - name: Set cloud-init to preserve hostname (RHEL) + ansible.builtin.lineinfile: + path: /etc/cloud/cloud.cfg + regex: "^(#)?preserve_hostname" + line: "preserve_hostname: 1" + state: present + notify: restart host + + - name: Check for existence of /etc/NetworkManager/conf.d + ansible.builtin.stat: path=/etc/NetworkManager/conf.d + register: st + + - name: Set /etc/NetworkManager/conf.d/disable-resolve.conf-managing.conf (RHEL) + ansible.builtin.copy: + dest: /etc/NetworkManager/conf.d/disable-resolve.conf-managing.conf + content: | + # Generated by Ansible + [main] + dns=none + when: st.stat.exists + notify: restart host + + # TODO Either local if dns_provider=freeipa or keep nameserver and update search only + # TODO Convert to ansible.builtin.template with role templates + - name: Set /etc/resolv.conf directly + ansible.builtin.copy: + dest: /etc/resolv.conf + content: | + # Generated by Ansible + search {{ [[name_prefix, domain] | join('.'), domain] | join(' ') }} + nameserver 127.0.0.1 + {{ ['nameserver'] | product(ipaserver_resolv_nameservers) | map('join', ' ') | join('\n') }} + notify: restart host + + # TODO Need to check-n-set vs. overwrite (forces reboot...) + - name: Set /etc/hostname to the FQDN + ansible.builtin.copy: + content: "{{ inventory_hostname }}" + dest: /etc/hostname + notify: restart host + + # TODO Need to check-n-set vs. overwrite (forces reboot...) + - name: Set /etc/hosts + ansible.builtin.copy: + dest: /etc/hosts + content: | + # Generated by Ansible + 127.0.0.1 localhost + {{ ansible_default_ipv4.address }} {{ inventory_hostname }} {{ inventory_hostname_short }} + backup: yes + notify: restart host + + - name: Set /etc/dhcp/dhclient.conf for domain search and name servers + ansible.builtin.lineinfile: + path: /etc/dhcp/dhclient.conf + regex: "^(#)?{{ dhclient_entry.value }}" + line: "{{ dhclient_entry.value }}" + state: present + loop: "{{ entries | dict2items }}" + loop_control: + loop_var: dhclient_entry + label: "{{ dhclient_entry.key }}" + vars: + entries: + domain_search: supersede domain-search "{{ [[name_prefix, domain] | join('.'), domain] | join('", "') }}"; + domain_name_servers: supersede domain-name-servers 127.0.0.1, {{ ipaserver_resolv_nameservers | join(', ') }}; + notify: restart host + +- name: Flush handlers + ansible.builtin.meta: flush_handlers + +- name: Set up the FreeIPA Server + ansible.builtin.import_role: + name: freeipa.ansible_freeipa.ipaserver + vars: + state: present + +- name: Configure DNS recursion for priv & pub IPs + when: + - ipaserver_setup_dns + - ipaserver_server_recursion + block: + - name: Set up DNS recursion + when: ipaserver_recursion_acl_cidr is defined + block: + - name: Configure ACL for DNS recursion option + ansible.builtin.blockinfile: + path: /etc/named/ipa-ext.conf + block: | + acl "internal_network" { + localhost; + {{ ipaserver_recursion_acl_cidr }}; + }; + notify: restart dns + + - name: Configure DNS recursion option + ansible.builtin.lineinfile: + path: /etc/named/ipa-options-ext.conf + regex: "^(#)?allow-recursion" + line: "allow-recursion { internal_network; };" + notify: restart dns + +- name: Configure global DNS for PTR synchronization and forwarding rules + when: ipaserver_setup_dns + block: + - name: Update global DNS + freeipa.ansible_freeipa.ipadnsconfig: + allow_sync_ptr: yes + forward_policy: only + ipaadmin_password: "{{ ipaadmin_password }}" + rescue: + - name: Check if global DNS error is legitimate + ansible.builtin.assert: + that: + - ansible_failed_result.changed is false + - ansible_failed_result.failed is true + - ansible_failed_result.msg == 'dnsconfig_mod: no modifications to be performed' + fail_msg: ansible_failed_result.msg + diff --git a/roles/freeipa_server/vars/RedHat-7.yml b/roles/freeipa_server/vars/RedHat-7.yml new file mode 100644 index 00000000..b43a931d --- /dev/null +++ b/roles/freeipa_server/vars/RedHat-7.yml @@ -0,0 +1,17 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ipaserver_packages: [ "ipa-server", "libselinux-python" ] diff --git a/roles/freeipa_server/vars/RedHat-8.yml b/roles/freeipa_server/vars/RedHat-8.yml new file mode 100644 index 00000000..ce7f1fd0 --- /dev/null +++ b/roles/freeipa_server/vars/RedHat-8.yml @@ -0,0 +1,17 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ipaserver_packages: [ "@idm:DL1/server" ] diff --git a/roles/freeipa_server/vars/default.yml b/roles/freeipa_server/vars/default.yml new file mode 100644 index 00000000..83b8448c --- /dev/null +++ b/roles/freeipa_server/vars/default.yml @@ -0,0 +1,17 @@ +--- + +# Copyright 2023 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ipaserver_packages: [ "ipa-server", "python3-libselinux" ]