diff --git a/README.md b/README.md index 24daae9..991412c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Ansible AWX Template: Template +# Ansible AWX Template: IPA Management -Ansible AWX is the method used for the Rocky Linux infrastructure, as a replacement for using the CLI. This template should be copied, as to manage playbooks and tasks into reproducible, repeatable, and organized manner. +Ansible AWX is the method used for the Rocky Linux infrastructure, as a replacement for using the CLI. ## Provides / Information -This repository is for AWX templates. +This repository is for IPA Management. ``` . @@ -27,95 +27,3 @@ This repository is for AWX templates. └── main.yml ``` -## Guidelines - -These are the general guidelines for creating and maintaining these repositories. Please read carefully to ensure that you are meeting the criteria. - -1. Copy this template into a new repository with the format `ansible-type-usage`. For example, if this is for ipa management, you could use a name like `ansible-ipa-management`. -2. Change the top of the `README.md` from "Template" to an appropriate name for your repo. -3. Modify the `README.md` file at the Provides/Information section of what these tasks do. Please be descriptive and list all of the playbooks and accompanying tasks (see the example). Hint: Use the `tree` command. -4. List any requirements to run the playbooks, such as vars, mandatory or optional in playbooks. Optionally, you may list them in the `README.md` here. -5. Run `pre-commit install` - There is already a provided `.pre-commit-config.yaml` with some default settings. -6. (Optional) Remove everything starting at "Guidelines" in this README to reduce clutter. - -## GitLab Steps - -1. Create a new project -2. Click "import project" -3. Click "Repo by URL" -4. Put in the URL: https://git.rockylinux.org/infrastructure/public/ansible/ansible-awx-template.git -5. Type in the project name as outlined in `Guidelines` above -6. Ensure your project URL and slug are appropriate - -## Designing Playbooks - -Generally, your playbooks should be doing the following: - -1. Checking if ansible can be ran on a specific host -2. Asserting if variables are filled and are correctly formed -3. Importing tasks from the `./tasks` directory -4. Importing roles, if necessary -5. Post tasks, if necessary - -**Note**: At no point should you be using `./tasks/main.yml` - -### Pre-flight and Post-flight tasks - -``` - pre_tasks: - - name: Check if ansible cannot be run here - stat: - path: /etc/no-ansible - register: no_ansible - - - name: Verify if we can run ansible - assert: - that: - - "not no_ansible.stat.exists" - success_msg: "We are able to run on this node" - fail_msg: "/etc/no-ansible exists - skipping run on this node" - - # Assertions and other checks here - - # Import roles/tasks here - - post_tasks: - - name: Touching run file that ansible has ran here - file: - path: /var/log/ansible.run - state: touch - mode: '0644' - owner: root - group: root -``` - -### Comments - -Each playbook should have comments or a name descriptor that explains what the playbook does or how it is used. If not available, README-... files can be used in place, especially in the case of adhoc playbooks that take input. Documentation for each playbook/role does not have to be on this wiki. Comments or README's should be sufficient. - -### Tags - -Ensure that you use relevant tags where necessary for your tasks. - -### Playbook naming - -``` -init-* -> Starting infrastructure playbooks that run solo or import other - playbooks that start with import- -adhoc -> These playbooks are one-off playbooks that can be used on the CLI or - in AWX. These are typically for basic tasks. -import -> Playbooks that should be imported from the top level playbooks -role-* -> These playbooks call roles specifically for infrastructure tasks. - Playbooks that do not call a role should be named init or adhoc based - on their usage. -``` - -### Pre-commits / linting - -When pushing to your own forked version of this repository, pre-commit must run to verify your changes. They must be passing to be pushed up. This is an absolute requirement, even for roles. - -When the linter passes, the push will complete and you will be able to open a PR. - -## How are these repositories used? - -These repositories are generally cloned/pulled into AWX for the latest version, so they can be called within AWX either by hand or at a scheduled time. diff --git a/adhoc-ipabinder.yml b/adhoc-ipabinder.yml new file mode 100644 index 0000000..7da5cd4 --- /dev/null +++ b/adhoc-ipabinder.yml @@ -0,0 +1,41 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Creates a binder account for read-only binds +# What is expected: +# -> ipa_binder_name: Bind account name, in the form of name_binder +# -> ipa_binder_password: Bind account password + +- name: Create binder account + hosts: ipaserver + become: true + + tasks: + - name: "Check for user variables" + assert: + that: + - ipa_binder_name | mandatory + - ipa_binder_password | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing user information" + + - name: "Creating bind account template - binder" + template: + src: "tmp/binder_template.update" + dest: "/tmp/binder.update" + owner: root + group: root + mode: '0600' + tags: + - users + + - name: "Adding in the bind account" + command: "/usr/sbin/ipa-ldap-updater /tmp/binder.update" + register: bind_account + changed_when: "bind_account.rc == 0" + tags: + - users + + - name: "Remove template" + file: + path: "/tmp/binder.update" + state: absent diff --git a/adhoc-ipadnsrecord.yml b/adhoc-ipadnsrecord.yml new file mode 100644 index 0000000..a4fc216 --- /dev/null +++ b/adhoc-ipadnsrecord.yml @@ -0,0 +1,56 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Creates dns records in the idm infrastructure based on the variables +# provided. +# What is expected: +# -> ipaadmin_password: This should be the password of the admin user +# -> ipa_admin: The admin user that has kerberos management capabilities (default is admin) +# -> ipa_zone: The zone name (eg, rockylinux.org) +# -> ipa_name: The shortname (eg, buildbox instead of buildbox.rockylinux.org) +# -> ipa_name_type: Type of record (eg, CNAME, A, AAAA, PTR) +# -> ipa_name_value: Record value (depends on type of record) +# -> ipa_presence: present or absent +# NOTE: For usage in AWX, select an IPA server + +- name: Create a DNS Record + hosts: all + become: false + gather_facts: false + + tasks: + - name: "Checking for user variables" + assert: + that: + - ipaadmin_password | mandatory + - ipa_zone | mandatory + - ipa_name | mandatory + - ipa_name_type | mandatory + - ipa_name_value | mandatory + - ipa_presence | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing zone information or ipa admin password" + + - name: "Creating DNS Record" + freeipa.ansible_freeipa.ipadnsrecord: + ipaadmin_principal: "{{ ipa_admin|default('admin') }}" + ipaadmin_password: "{{ ipaadmin_password }}" + zone_name: "{{ ipa_zone }}" + name: "{{ ipa_name }}" + record_type: "{{ ipa_name_type }}" + record_value: "{{ ipa_name_value }}" + state: "{{ ipa_presence }}" + tags: + - dns + + # We try to do this just in case because if a certificate is being issued + # that wants a CNAME, the host has to "manage" said host. However, if the + # host doesn't exist, we'll ignore it. + - name: "Creating host object for CNAME" + freeipa.ansible_freeipa.ipahost: + ipaadmin_principal: "{{ ipa_admin|default('admin') }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ ipa_name }}.{{ ipa_zone }}" + force: true + managedby: + - "{{ ipa_name_value[:-1] }}" + ignore_errors: true diff --git a/adhoc-ipadnszone.yml b/adhoc-ipadnszone.yml new file mode 100644 index 0000000..ae81435 --- /dev/null +++ b/adhoc-ipadnszone.yml @@ -0,0 +1,28 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Creates dns zones in the idm infrastructure based on the variables +# provided. +# NOTE: For usage in AWX, select an IPA server + +- name: Create a DNS Zone + hosts: all + become: false + gather_facts: false + + tasks: + - name: "Checking for user variables" + assert: + that: + - ipa_admin | mandatory + - ipaadmin_password | mandatory + - ipa_zone | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing zone information or ipa admin password" + + - name: "Creating DNS Zone" + freeipa.ansible_freeipa.ipadnszone: + ipaadmin_principal: "{{ ipa_admin }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ ipa_zone }}" + tags: + - dns diff --git a/adhoc-ipagetcert.yml b/adhoc-ipagetcert.yml new file mode 100644 index 0000000..9a67d35 --- /dev/null +++ b/adhoc-ipagetcert.yml @@ -0,0 +1,33 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Requests and signs a certificate from an IPA CA +# What is expected: +# -> getcert_name: Name of the certificate (FQDN) +# -> getcert_owner: what account owns the certificate files +# -> getcert_key: path to the certificate key +# -> getcert_cert: path to the certificate +# -> getcert_postcmd: command to run after a certificate renews +# -> getcert_chain: true/false, should cert and key be chained together +# -> getcert_chain_location: location for the chain +# TODO: Add CNAME/SAN support +# NOTE: For usage in AWX, select an appropriate server + +- name: Request and sign an IPA Certificate + hosts: all + become: true + vars: + ipa_getcert_requested_hostnames: + - name: "{{ getcert_name|default(ansible_fqdn) }}" + owner: "{{ getcert_owner|default('root') }}" + key_location: "{{ getcert_key|default('/etc/pki/tls/private/newcert.key') }}" + cert_location: "{{ getcert_cert|default('/etc/pki/tls/certs/newcert.crt') }}" + nss_db_dir: "{{ getcert_nss_db_dir|default('/etc/pki/tls/db') }}" + nss_nickname: "{{ getcert_nss_nickname|default(ansible_fqdn) }}" + postcmd: "{{ getcert_postcmd|default(false) }}" + ipa_getcert_chain: "{{ getcert_chain|default(false) }}" + ipa_getcert_chain_location: "{{ getcert_chain_location|default('/etc/pki/tls/chain') }}" + ipa_getcert_nss: "{{ getcert_nss|default(false) }}" + + roles: + - role: rockylinux.ipagetcert + state: present diff --git a/adhoc-ipagetkeytab.yml b/adhoc-ipagetkeytab.yml new file mode 100644 index 0000000..02a1a03 --- /dev/null +++ b/adhoc-ipagetkeytab.yml @@ -0,0 +1,136 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# Special thanks to @remyabel for assisting in improving this playbook with +# extended security posture +# What: Pulls keytabs for a kerberos service +# What is expected: +# -> host: The host in the inventory, this MUST be FQDN. +# -> ipa_service: using this format: SVC/hostname.rockylinux.org@ROCKYLINUX.ORG +# Note: This service MUST exist +# -> ipa_keytab_fullpath: The full path to the keytab. Example: /etc/gitlab/gitlab.keytab +# -> ipa_server: This needs to be one of the IPA servers +# -> ipa_owner: If applicable, the local account that can read this keytab (eg apache) +# -> ipa_admin: The admin user that has kerberos management capabilities (default is admin) +# -> ipaadmin_password: This should be the password of the admin user +# NOTE: For usage in AWX, select an appropriate host + +- name: Pull keytab from IPA + hosts: all + become: true + gather_facts: false + + tasks: + - name: "Checking for user variables" + assert: + that: + - ipa_admin | mandatory + - ipaadmin_password | mandatory + - ipa_service | mandatory + - ipa_keytab_fullpath | mandatory + - ipa_server | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing required information" + + - name: "Check that a keytab doesn't already exist" + stat: + path: "{{ ipa_keytab_fullpath }}" + register: keytab_status + check_mode: false + changed_when: "1 != 1" + + - name: "Verify keytab existence" + assert: + that: + - "not keytab_status.stat.exists" + success_msg: "Keytab doesn't exist, moving on..." + fail_msg: "Keytab with that name already exists, skipping." + + - name: "Grant {{ host }} and {{ ipa_admin }} access to the service keytab" + delegate_to: "{{ ipa_server }}" + freeipa.ansible_freeipa.ipaservice: + ipaadmin_principal: "{{ ipa_admin }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ ipa_service }}" + allow_retrieve_keytab_user: + - "{{ ipa_admin }}" + allow_retrieve_keytab_host: + - "{{ host }}" + action: member + + - name: "Grant {{ host }} and {{ ipa_admin }} access to the host keytab" + delegate_to: "{{ ipa_server }}" + freeipa.ansible_freeipa.ipahost: + ipaadmin_principal: "{{ ipa_admin }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ host }}" + state: present + allow_retrieve_keytab_user: + - "{{ ipa_admin }}" + managedby_host: "{{ host }}" + action: member + + - name: "Get kerberos ticket" + delegate_to: "{{ ipa_server }}" + shell: "set -o pipefail && echo \"{{ ipaadmin_password }}\" | kinit {{ ipa_admin }}" + check_mode: false + changed_when: "1 != 1" + when: not keytab_status.stat.exists + + - name: "Attempt to retrieve keytab" + delegate_to: "{{ ipa_server }}" + command: "ipa-getkeytab -r -s {{ ipa_server }} -p {{ ipa_service }} -k /tmp/{{ host }}.kt" + register: ret_result + check_mode: false + changed_when: "1 != 1" + failed_when: "not ('Keytab successfully retrieved' in ret_result.stderr or 'krbPrincipalKey not found' in ret_result.stderr)" + + - name: "Create keytab if it didn't exist, based on the last task" + delegate_to: "{{ ipa_server }}" + command: "ipa-getkeytab -s {{ ipa_server }} -p {{ ipa_service }} -k /tmp/{{ host }}.kt" + when: "'krbPrincipalKey not found' in ret_result.stderr" + + - name: "Destroy admin ticket" + delegate_to: "{{ ipa_server }}" + command: "kdestroy -A" + register: kdestroy_result + changed_when: "kdestroy_result.rc == 0" + + - name: "Put the keytab into a register" + delegate_to: "{{ ipa_server }}" + command: "base64 /tmp/{{ host }}.kt" + register: keytab + check_mode: false + changed_when: "keytab.rc == 0" + + - name: "Destroy local keytab" + delegate_to: "{{ ipa_server }}" + file: + path: "/tmp/{{ host }}.kt" + state: absent + + - name: "Deploy keytab to {{ host }} from register" + copy: + dest: "{{ ipa_keytab_fullpath }}.b64" + content: "{{ keytab.stdout }}" + owner: "{{ ipa_owner|default('root') }}" + group: "{{ ipa_owner|default('root') }}" + mode: '0600' + + - name: "Decode keytab" + shell: "umask 077 && base64 -d {{ ipa_keytab_fullpath }}.b64 > {{ ipa_keytab_fullpath }}" + changed_when: "1 != 1" + + - name: "Destroy encoded keytab" + file: + path: "{{ ipa_keytab_fullpath }}.b64" + state: absent + + - name: "Set ownership if applicable, otherwise it's root owned" + file: + path: "{{ ipa_keytab_fullpath }}" + owner: "{{ ipa_owner|default('root') }}" + group: "{{ ipa_owner|default('root') }}" + mode: '0600' + state: file + tags: + - keytab diff --git a/adhoc-ipagroup.yml b/adhoc-ipagroup.yml new file mode 100644 index 0000000..daa0fe6 --- /dev/null +++ b/adhoc-ipagroup.yml @@ -0,0 +1,47 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Creates groups in the idm infrastructure based on the variables provided +# You MUST provide an ipa_admin user to run this. +# If group is going to be a fas group (exposed in noggin), ensure ipa_fas is +# set to true. + +- name: Create our initial users + hosts: ipaserver + become: false + gather_facts: false + + tasks: + - name: "Checking for user variables" + assert: + that: + - ipa_admin | mandatory + - ipaadmin_password | mandatory + - ipa_group | mandatory + - ipa_description | mandatory + - ipa_nonposix | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing group information or ipa admin password" + + - name: "Creating New Group" + freeipa.ansible_freeipa.ipagroup: + ipaadmin_principal: "{{ ipa_admin }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ ipa_group }}" + description: "{{ ipa_description }}" + nonposix: "{{ ipa_nonposix }}" + membermanager_user: "{{ ipa_group_manager_user | default(omit) }}" + membermanager_group: "{{ ipa_group_manager_group | default(omit) }}" + tags: + - groups + + - name: "Prepare FAS if required" + shell: "set -o pipefail && echo \"{{ ipaadmin_password }}\" | kinit {{ ipa_admin }}" + check_mode: false + changed_when: "1 != 1" + when: ipa_fas + + - name: "Apply FAS" + command: "ipa group-mod --fasgroup {{ ipa_group }}" + check_mode: false + changed_when: "1 != 1" + when: ipa_fas diff --git a/adhoc-ipaservice.yml b/adhoc-ipaservice.yml new file mode 100644 index 0000000..ab46f60 --- /dev/null +++ b/adhoc-ipaservice.yml @@ -0,0 +1,28 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Creates kerberos services in the idm infrastructure based on the variables provided + +- name: Create Services + hosts: ipaserver + become: false + gather_facts: false + + tasks: + - name: "Checking for user variables" + assert: + that: + - ipa_admin | mandatory + - ipaadmin_password | mandatory + - ipa_service | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing required information" + + - name: "Creating Kerberos Service" + freeipa.ansible_freeipa.ipaservice: + ipaadmin_principal: "{{ ipa_admin }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ ipa_service }}" + skip_host_check: "{{ ipa_skip_host_check | default(false) }}" + force: "{{ ipa_force | default(false) }}" + tags: + - services diff --git a/adhoc-ipauser-disable.yml b/adhoc-ipauser-disable.yml new file mode 100644 index 0000000..f2454f9 --- /dev/null +++ b/adhoc-ipauser-disable.yml @@ -0,0 +1,28 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Creates users in the idm infrastructure based on the variables provided. +# NOTE: For usage in AWX, select an appropriate host + +- name: Create a User + hosts: all + become: false + gather_facts: false + + tasks: + - name: "Checking for user variables" + assert: + that: + - ipa_admin | mandatory + - ipaadmin_password | mandatory + - ipa_name | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing user information or ipa admin password" + + - name: "Disabling User Account" + freeipa.ansible_freeipa.ipauser: + ipaadmin_principal: "{{ ipa_admin }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ ipa_name }}" + state: disabled + tags: + - users diff --git a/adhoc-ipauser-enable.yml b/adhoc-ipauser-enable.yml new file mode 100644 index 0000000..2394c9e --- /dev/null +++ b/adhoc-ipauser-enable.yml @@ -0,0 +1,28 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Creates users in the idm infrastructure based on the variables provided. +# NOTE: For usage in AWX, select an appropriate host + +- name: Create a User + hosts: all + become: false + gather_facts: false + + tasks: + - name: "Checking for user variables" + assert: + that: + - ipa_admin | mandatory + - ipaadmin_password | mandatory + - ipa_name | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing user information or ipa admin password" + + - name: "Enabling User Account" + freeipa.ansible_freeipa.ipauser: + ipaadmin_principal: "{{ ipa_admin }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ ipa_name }}" + state: enabled + tags: + - users diff --git a/adhoc-ipauser.yml b/adhoc-ipauser.yml new file mode 100644 index 0000000..e533b91 --- /dev/null +++ b/adhoc-ipauser.yml @@ -0,0 +1,39 @@ +--- +# This playbook is meant to be used with callable variables, like adhoc or AWX. +# What: Creates users in the idm infrastructure based on the variables provided. +# NOTE: For usage in AWX, select an appropriate host + +- name: Create a User + hosts: all + become: false + gather_facts: false + + tasks: + - name: "Checking for user variables" + assert: + that: + - ipa_admin | mandatory + - ipaadmin_password | mandatory + - ipa_name | mandatory + - ipa_first | mandatory + - ipa_last | mandatory + - ipa_email | mandatory + - ipa_password | mandatory + - ipa_title | mandatory + success_msg: "Required variables provided" + fail_msg: "We are missing user information or ipa admin password" + + - name: "Creating User Account" + freeipa.ansible_freeipa.ipauser: + ipaadmin_principal: "{{ ipa_admin }}" + ipaadmin_password: "{{ ipaadmin_password }}" + name: "{{ ipa_name }}" + first: "{{ ipa_first }}" + last: "{{ ipa_last }}" + email: "{{ ipa_email }}" + password: "{{ ipa_password }}" + title: "{{ ipa_title }}" + loginshell: "{{ ipa_loginshell|default('/sbin/nologin', True) }}" + update_password: on_create + tags: + - users diff --git a/role-rocky-ipa-client.yml b/role-rocky-ipa-client.yml new file mode 100644 index 0000000..2bafdb9 --- /dev/null +++ b/role-rocky-ipa-client.yml @@ -0,0 +1,38 @@ +--- +# Configures an IPA client for the Rocky infrastructure +# NOTE: For usage in AWX, select an appropriate host +- name: Configure IPA client + hosts: all + become: true + + pre_tasks: + - name: Check if ansible cannot be run here + stat: + path: /etc/no-ansible + register: no_ansible + + - name: Verify if we can run ansible + assert: + that: + - "not no_ansible.stat.exists" + success_msg: "We are able to run on this node" + fail_msg: "/etc/no-ansible exists - skipping run on this node" + + - name: Apply hostname based on inventory name + hostname: + name: "{{ inventory_hostname }}" + use: systemd + when: ansible_fqdn != inventory_hostname + + roles: + - role: freeipa.ansible_freeipa.ipaclient + state: present + + post_tasks: + - name: Touching run file that ansible has ran here + file: + path: /var/log/ansible.run + state: touch + mode: '0644' + owner: root + group: root diff --git a/role-rocky-ipa-replica.yml b/role-rocky-ipa-replica.yml new file mode 100644 index 0000000..5994194 --- /dev/null +++ b/role-rocky-ipa-replica.yml @@ -0,0 +1,62 @@ +--- +# Creates an IPA replica +# NOTE: Select the appropriate host or hostgroup +- name: Configure IPA server + hosts: all + become: true + + # This is to try to avoid the handler issue in pre/post tasks + handlers: + - import_tasks: handlers/main.yml + + pre_tasks: + - name: Check if ansible cannot be run here + stat: + path: /etc/no-ansible + register: no_ansible + + - name: Verify if we can run ansible + assert: + that: + - "not no_ansible.stat.exists" + success_msg: "We are able to run on this node" + fail_msg: "/etc/no-ansible exists - skipping run on this node" + + - name: Ensure 'dns=none' is set for Network Manager + ini_file: + path: /etc/NetworkManager/NetworkManager.conf + state: present + no_extra_spaces: true + section: main + option: dns + value: none + owner: root + group: root + mode: '0644' + backup: true + notify: + - reload_networkmanager + + - name: Ensure resolv.conf is pointing to main master + template: + src: etc/resolv.conf.j2 + dest: /etc/resolv.conf + owner: root + group: root + mode: '0644' + backup: true + notify: + - reload_networkmanager + + roles: + - role: freeipa.ansible_freeipa.ipareplica + state: present + + post_tasks: + - name: Touching run file that ansible has ran here + file: + path: /var/log/ansible.run + state: touch + mode: '0644' + owner: root + group: root diff --git a/role-rocky-ipa.yml b/role-rocky-ipa.yml new file mode 100644 index 0000000..40f1516 --- /dev/null +++ b/role-rocky-ipa.yml @@ -0,0 +1,62 @@ +--- +# Creates the first server for an IPA infrastructure +# Recommended specs for the IPA systems, that scale based on number of objects: +# CPU: 2 cores +# Memory: 4GB +# Storage: 10G /var/lib/dirsrv +# System fully up to date +# Define "host" as a hostgroup name or a single host +# NOTE: For AWX, choose the appropriate host or host group +- name: Configure IPA server + hosts: all + become: true + + # This is to try to avoid the handler issue in pre/post tasks + handlers: + - import_tasks: handlers/main.yml + + pre_tasks: + - name: Check if ansible cannot be run here + stat: + path: /etc/no-ansible + register: no_ansible + + - name: Verify if we can run ansible + assert: + that: + - "not no_ansible.stat.exists" + success_msg: "We are able to run on this node" + fail_msg: "/etc/no-ansible exists - skipping run on this node" + + - name: Ensure 'dns=none' is set for Network Manager to avoid change + ini_file: + path: /etc/NetworkManager/NetworkManager.conf + state: present + no_extra_spaces: true + section: main + option: dns + value: none + owner: root + group: root + mode: '0644' + backup: true + notify: + - reload_networkmanager + + roles: + - role: freeipa.ansible_freeipa.ipaserver + state: present + + post_tasks: + - name: Touching run file that ansible has ran here + file: + path: /var/log/ansible.run + state: touch + mode: '0644' + owner: root + group: root + + - name: Turn on reverse zone syncing + freeipa.ansible_freeipa.ipadnsconfig: + ipaadmin_password: '{{ ipaadmin_password }}' + allow_sync_ptr: true