-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #241 from stackhpc/feat/freeipa-nocontainer
Add freeipa (not containerised)
- Loading branch information
Showing
31 changed files
with
530 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Use ONE of the following tags on this playbook: | ||
# - retrieve: copies keytabs out of the state volume to the environment | ||
# - deploy: copies keytabs from the environment to the state volume | ||
|
||
- hosts: freeipa_client | ||
become: yes | ||
gather_facts: no | ||
tasks: | ||
- import_role: | ||
name: freeipa | ||
tasks_from: backup-keytabs.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,42 @@ | ||
- hosts: basic_users | ||
- hosts: freeipa_client | ||
tags: | ||
- freeipa | ||
- freeipa_server # as this is only relevant if using freeipa_server | ||
- freeipa_host | ||
gather_facts: no | ||
become: yes | ||
tasks: | ||
- name: Ensure FreeIPA client hosts are added to the FreeIPA server | ||
import_role: | ||
name: freeipa | ||
tasks_from: addhost.yml | ||
when: groups['freeipa_server'] | length > 0 | ||
|
||
- hosts: freeipa_client | ||
tags: | ||
- basic_users | ||
- freeipa | ||
- freeipa_client | ||
gather_facts: yes | ||
become: yes | ||
tasks: | ||
- name: Install FreeIPA client | ||
import_role: | ||
name: freeipa | ||
tasks_from: client-install.yml | ||
- name: Enrol FreeIPA client | ||
import_role: | ||
name: freeipa | ||
tasks_from: enrol.yml | ||
|
||
- hosts: freeipa_server | ||
tags: | ||
- freeipa | ||
- freeipa_server | ||
- users | ||
gather_facts: yes | ||
become: yes | ||
tasks: | ||
- import_role: | ||
name: basic_users | ||
- name: Add FreeIPA users | ||
import_role: | ||
name: freeipa | ||
tasks_from: users.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
etc_hosts_template: hosts.j2 | ||
etc_hosts_hostvars: | ||
- ansible_host | ||
- inventory_hostname | ||
etc_hosts_hostvars: "{{ ['ansible_host'] + (['node_fqdn'] if node_fqdn is defined else []) + ['inventory_hostname'] }}" | ||
etc_hosts_extra_hosts: '' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
|
||
# freeipa | ||
|
||
Support FreeIPA in the appliance. In production use it is expected the FreeIPA server(s) will be external to the cluster, implying that hosts and users are managed outside the appliance. However for testing and development the role can also deploy an "in-appliance" FreeIPA server, add hosts to it and manage users in FreeIPA. | ||
|
||
# FreeIPA Client | ||
|
||
## Usage | ||
- Add hosts to the `freeipa_client` group and run (at a minimum) the `ansible/iam.yml` playbook. | ||
- Host names must match the domain name. By default (using the skeleton Terraform) hostnames are of the form `nodename.cluster_name.cluster_domain_suffix` where `cluster_name` and `cluster_domain_suffix` are Terraform variables. | ||
- Hosts discover the FreeIPA server FQDN (and their own domain) from DNS records. If DNS servers are not set this is not set from DHCP, then use the `resolv_conf` role to configure this. For example when using the in-appliance FreeIPA development server: | ||
|
||
```ini | ||
# environments/<env>/groups | ||
... | ||
[resolv_conf:children] | ||
freeipa_client | ||
... | ||
``` | ||
|
||
```yaml | ||
# environments/<env>/inventory/group_vars/all/resolv_conf.yml | ||
resolv_conf_nameservers: | ||
- "{{ hostvars[groups['freeipa_server'] | first].ansible_host }}" | ||
``` | ||
- For production use with an external FreeIPA server, a random one-time password (OTP) must be generated when adding hosts to FreeIPA (e.g. using `ipa host-add --random ...`). This password should be set as a hostvar `freeipa_host_password`. Initial host enrolment will use this OTP to enrol the host. After this it becomes irrelevant so it does not need to be committed to git. This approach means the appliance does not require the FreeIPA administrator password. | ||
- For development use with the in-appliance FreeIPA server, `freeipa_host_password` will be automatically generated in memory. | ||
- The `control` host must define `appliances_state_dir` (on persistent storage). This is used to back-up keytabs to allow FreeIPA clients to automatically re-enrol after e.g. reimaging. Note that: | ||
- This is implemented when using the skeleton Terraform; on the control node `appliances_state_dir` defaults to `/var/lib/state` which is mounted from a volume. | ||
- Nodes are not re-enroled by a [Slurm-driven reimage](../../collections/ansible_collections/stackhpc/slurm_openstack_tools/roles/rebuild/README.md) (as that does not run this role). | ||
- If both a backed-up keytab and `freeipa_host_password` exist, the former is used. | ||
|
||
|
||
## Role Variables for Clients | ||
|
||
- `freeipa_host_password`. Required for initial enrolment only, FreeIPA host password as described above. | ||
- `freeipa_setup_dns`: Optional, whether to use the FreeIPA server as the client's nameserver. Defaults to `true` when `freeipa_server` contains a host, otherwise `false`. | ||
|
||
See also use of `appliances_state_dir` on the control node as described above. | ||
|
||
# FreeIPA Server | ||
As noted above this is only intended for development and testing. Note it cannot be run on the `openondemand` node as no other virtual servers must be defined in the Apache configuration. | ||
|
||
## Usage | ||
- Add a single host to the `freeipa_server` group and run (at a minimum) the `ansible/bootstrap.yml` and `ansible/iam.yml` playbooks. | ||
- As well as configuring the FreeIPA server, the role will also: | ||
- Add ansible hosts in the group `freeipa_client` as FreeIPA hosts. | ||
- Optionally control users in FreeIPA - see `freeipa_users` below. | ||
|
||
The FreeIPA GUI will be available on `https://<freeipa_server_ip>/ipa/ui`. | ||
|
||
## Role Variables for Server | ||
|
||
These role variables are only required when using `freeipa_server`: | ||
|
||
- `freeipa_realm`: Optional, name of realm. Default is `{{ openhpc_cluster_name | upper }}.INVALID` | ||
- `freeipa_domain`: Optional, name of domain. Default is lowercased `freeipa_realm`. | ||
- `freeipa_ds_password`: Optional, password to be used by the Directory Server for the Directory Manager user (`ipa-server-install --ds-password`). Default is generated in `environments/<environment>/inventory/group_vars/all/secrets.yml` | ||
- `freeipa_admin_password`: Optional, password for the IPA `admin` user. Default is generated as for `freeipa_ds_password`. | ||
- `freeipa_server_ip`: Optional, IP address of freeipa_server host. Default is `ansible_host` of the `freeipa_server` host. Default `false`. | ||
- `freeipa_setup_dns`: Optional bool, whether to configure the FreeIPA server as an integrated DNS server and define a zone and records. NB: This also controls whether `freeipa_client` hosts use the `freeipa_server` host for name resolution. Default `true` when `freeipa_server` contains a host. | ||
- `freeipa_client_ip`: Optional, IP address of FreeIPA client. Default is `ansible_host`. | ||
- `freeipa_users`: A list of dicts defining users to add, with keys/values as for [community.general.ipa_user](https://docs.ansible.com/ansible/latest/collections/community/general/ipa_user_module.html): Note that: | ||
- `name`, `givenname` (firstname) and `sn` (surname) are required. | ||
- `ipa_host`, `ipa_port`, `ipa_prot`, `ipa_user`, `validate_certs` are automatically provided and cannot be overridden. | ||
- If `password` is set, the value should *not* be a hash (unlike `ansible.builtin.user` as used by the `basic_users` role), and it must be changed on first login. `krbpasswordexpiration` does not appear to be able to override this. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#freeipa_realm: | ||
freeipa_domain: "{{ freeipa_realm | lower }}" | ||
#freeipa_ds_password: | ||
#freeipa_admin_password: | ||
#freeipa_server_ip: | ||
freeipa_setup_dns: "{{ groups['freeipa_server'] | length > 0 }}" | ||
freeipa_client_ip: "{{ ansible_host }}" # when run on freeipa_client group! | ||
# freeipa_host_password: | ||
freeipa_user_defaults: | ||
ipa_pass: "{{ freeipa_admin_password | quote }}" | ||
ipa_user: admin | ||
freeipa_users: [] # see community.general.ipa_user | ||
|
||
_freeipa_keytab_backup_path: "{{ hostvars[groups['control'].0].appliances_state_dir }}/freeipa/{{ inventory_hostname }}/krb5.keytab" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
- name: Get ipa host information | ||
# This uses DNS to find the ipa server, which works as this is running on the enrolled ipa server | ||
# It doesn't fail even if the host doesn't exist | ||
community.general.ipa_host: | ||
name: "{{ node_fqdn }}" | ||
ip_address: "{{ freeipa_client_ip }}" | ||
ipa_host: "{{ groups['freeipa_server'].0 }}" | ||
ipa_pass: "{{ vault_freeipa_admin_password }}" | ||
ipa_user: admin | ||
state: present | ||
validate_certs: false | ||
delegate_to: "{{ groups['freeipa_server'].0 }}" | ||
register: _ipa_host_check | ||
check_mode: yes | ||
changed_when: false | ||
|
||
- name: Add host to IPA | ||
# Using random_password=true this unenroles an enroled host, hence the check above | ||
community.general.ipa_host: | ||
name: "{{ node_fqdn }}" | ||
ip_address: "{{ freeipa_client_ip }}" | ||
ipa_host: "{{ groups['freeipa_server'].0 }}" | ||
ipa_pass: "{{ vault_freeipa_admin_password }}" | ||
ipa_user: admin | ||
random_password: true | ||
state: present | ||
validate_certs: false | ||
delegate_to: "{{ groups['freeipa_server'].0 }}" | ||
when: "'sshpubkeyfp' not in _ipa_host_check.host" | ||
register: _ipa_host_add | ||
|
||
- name: Set fact for ipa host password | ||
set_fact: | ||
freeipa_host_password: "{{ _ipa_host_add.host.randompassword }}" | ||
when: _ipa_host_add.changed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
- name: Retrieve keytabs to localhost | ||
fetch: | ||
src: "{{ _freeipa_keytab_backup_path }}" | ||
dest: "{{ appliances_environment_root }}/keytabs/{{ inventory_hostname }}/" | ||
flat: true | ||
delegate_to: "{{ groups['control'].0 }}" | ||
tags: retrieve | ||
|
||
- name: Copy keytabs back to control node | ||
copy: | ||
src: "{{ appliances_environment_root }}/keytabs/{{ inventory_hostname }}/" | ||
dest: "{{ _freeipa_keytab_backup_path | dirname }}" | ||
delegate_to: "{{ groups['control'].0 }}" | ||
tags: deploy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
- name: Install FreeIPA client package | ||
dnf: | ||
name: ipa-client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/installing_identity_management/assembly_installing-an-idm-client_installing-identity-management | ||
|
||
- name: Retrieve persisted keytab from previous enrolement | ||
slurp: | ||
src: "{{ _freeipa_keytab_backup_path }}" | ||
delegate_to: "{{ groups['control'] | first }}" | ||
register: _slurp_persisted_keytab | ||
failed_when: false | ||
|
||
- name: Write persisted keytab from previous enrolment | ||
copy: | ||
content: "{{ _slurp_persisted_keytab.content | b64decode }}" | ||
dest: /tmp/krb5.keytab | ||
owner: root | ||
group: root | ||
mode: ug=rw,o= | ||
when: '"content" in _slurp_persisted_keytab' | ||
|
||
- name: Re-enrol with FreeIPA using backed-up keytab | ||
# Re-enrolment requires --force-join and --password, or --keytab | ||
# Re-rolement means: | ||
# 1. A new host certificate is issued | ||
# 2. The old host certificate is revoked | ||
# 3. New SSH keys are generated | ||
# 4. ipaUniqueID is preserved | ||
# and ALSO that the keytab is changed! | ||
command: | ||
cmd: > | ||
ipa-client-install | ||
--unattended | ||
--mkhomedir | ||
--enable-dns-updates | ||
--keytab /tmp/krb5.keytab | ||
when: '"content" in _slurp_persisted_keytab' | ||
register: ipa_client_install_keytab | ||
changed_when: ipa_client_install_keytab.rc == 0 | ||
failed_when: > | ||
ipa_client_install_keytab.rc !=0 and | ||
'IPA client is already configured' not in ipa_client_install_keytab.stderr | ||
- name: Enrol with FreeIPA using random password | ||
# Note --password is overloaded - it's bulkpassword unless --principal or --force-join is used in which case it's admin password | ||
command: | ||
cmd: > | ||
ipa-client-install | ||
--unattended | ||
--mkhomedir | ||
--enable-dns-updates | ||
--password '{{ freeipa_host_password }}' | ||
when: | ||
- '"content" not in _slurp_persisted_keytab' | ||
- freeipa_host_password is defined | ||
register: ipa_client_install_password | ||
changed_when: ipa_client_install_password.rc == 0 | ||
failed_when: > | ||
ipa_client_install_password.rc != 0 and | ||
'IPA client is already configured' not in ipa_client_install_password.stderr | ||
- name: Ensure NFS RPC security service is running | ||
# This service is installed by nfs-utils, which attempts to start it. | ||
# It has ConditionPathExists=/etc/krb5.keytab which fails if host is not enroled. | ||
# This task avoids a reboot. | ||
systemd: | ||
name: rpc-gssd.service | ||
state: started | ||
enabled: true | ||
|
||
- name: Retrieve current keytab | ||
slurp: | ||
src: /etc/krb5.keytab | ||
register: _slurp_current_keytab | ||
failed_when: false | ||
|
||
- name: Ensure keytab backup directory exists | ||
file: | ||
path: "{{ _freeipa_keytab_backup_path | dirname }}" | ||
state: directory | ||
owner: root | ||
group: root | ||
mode: ug=wrX,o= | ||
delegate_to: "{{ groups['control'] | first }}" | ||
|
||
- name: Persist keytab | ||
copy: | ||
content: "{{ _slurp_current_keytab.content | b64decode }}" | ||
dest: "{{ _freeipa_keytab_backup_path }}" | ||
delegate_to: "{{ groups['control'] | first }}" |
Oops, something went wrong.