From 49ba7cd121882e00feea78db41e57b22e9e0fba5 Mon Sep 17 00:00:00 2001 From: Tyler Hale Date: Wed, 1 Sep 2021 17:31:49 -0600 Subject: [PATCH] Initial commit --- README.md | 73 +++++++++++++ base.yml | 7 ++ hosts.yml | 18 ++++ roles/base/defaults/main.yml | 60 +++++++++++ roles/base/handlers/main.yml | 29 +++++ roles/base/public_keys/ansible_awx | 1 + roles/base/public_keys/thale-bw | 1 + roles/base/public_keys/thale-desktop | 2 + roles/base/public_keys/thale-laptop | 1 + roles/base/public_keys/thale-phone | 1 + roles/base/public_keys/thale-work | 1 + roles/base/tasks/core.yml | 62 +++++++++++ roles/base/tasks/core_cert.yml | 53 ++++++++++ roles/base/tasks/core_hostname.yml | 58 ++++++++++ roles/base/tasks/core_motd.yml | 42 ++++++++ roles/base/tasks/core_root_ca.yml | 73 +++++++++++++ roles/base/tasks/core_ssh.yml | 51 +++++++++ roles/base/tasks/core_web_management.yml | 39 +++++++ roles/base/tasks/debian.yml | 40 +++++++ roles/base/tasks/debian_automatic_updates.yml | 56 ++++++++++ roles/base/tasks/debian_firewall.yml | 25 +++++ roles/base/tasks/debian_kernel.yml | 8 ++ roles/base/tasks/debian_time_sync.yml | 31 ++++++ roles/base/tasks/main.yml | 22 ++++ roles/base/tasks/redhat.yml | 40 +++++++ roles/base/tasks/redhat_automatic_updates.yml | 50 +++++++++ roles/base/tasks/redhat_epel.yml | 8 ++ roles/base/tasks/redhat_firewall.yml | 25 +++++ roles/base/tasks/redhat_time_sync.yml | 13 +++ roles/base/templates/20auto-upgrades.j2 | 2 + ...apt-daily-upgrade.timer.d_override.conf.j2 | 4 + .../apt-daily.timer.d_override.conf.j2 | 4 + roles/base/templates/automatic.conf.j2 | 100 ++++++++++++++++++ .../dnf-automatic-install.service-7.j2 | 2 + .../dnf-automatic-install.service-8.j2 | 2 + .../templates/dnf-automatic-install.timer.j2 | 5 + roles/base/templates/issue.j2 | 16 +++ roles/base/templates/motd.j2 | 48 +++++++++ roles/base/vars/main.yml | 43 ++++++++ site.yml | 5 + 40 files changed, 1121 insertions(+) create mode 100644 base.yml create mode 100644 hosts.yml create mode 100644 roles/base/defaults/main.yml create mode 100644 roles/base/handlers/main.yml create mode 100644 roles/base/public_keys/ansible_awx create mode 100644 roles/base/public_keys/thale-bw create mode 100644 roles/base/public_keys/thale-desktop create mode 100644 roles/base/public_keys/thale-laptop create mode 100644 roles/base/public_keys/thale-phone create mode 100644 roles/base/public_keys/thale-work create mode 100644 roles/base/tasks/core.yml create mode 100644 roles/base/tasks/core_cert.yml create mode 100644 roles/base/tasks/core_hostname.yml create mode 100644 roles/base/tasks/core_motd.yml create mode 100644 roles/base/tasks/core_root_ca.yml create mode 100644 roles/base/tasks/core_ssh.yml create mode 100644 roles/base/tasks/core_web_management.yml create mode 100644 roles/base/tasks/debian.yml create mode 100644 roles/base/tasks/debian_automatic_updates.yml create mode 100644 roles/base/tasks/debian_firewall.yml create mode 100644 roles/base/tasks/debian_kernel.yml create mode 100644 roles/base/tasks/debian_time_sync.yml create mode 100644 roles/base/tasks/main.yml create mode 100644 roles/base/tasks/redhat.yml create mode 100644 roles/base/tasks/redhat_automatic_updates.yml create mode 100644 roles/base/tasks/redhat_epel.yml create mode 100644 roles/base/tasks/redhat_firewall.yml create mode 100644 roles/base/tasks/redhat_time_sync.yml create mode 100644 roles/base/templates/20auto-upgrades.j2 create mode 100644 roles/base/templates/apt-daily-upgrade.timer.d_override.conf.j2 create mode 100644 roles/base/templates/apt-daily.timer.d_override.conf.j2 create mode 100644 roles/base/templates/automatic.conf.j2 create mode 100644 roles/base/templates/dnf-automatic-install.service-7.j2 create mode 100644 roles/base/templates/dnf-automatic-install.service-8.j2 create mode 100644 roles/base/templates/dnf-automatic-install.timer.j2 create mode 100644 roles/base/templates/issue.j2 create mode 100644 roles/base/templates/motd.j2 create mode 100644 roles/base/vars/main.yml create mode 100644 site.yml diff --git a/README.md b/README.md index 9a0b55c..790a251 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,75 @@ # Ansible-Linux_Base +Configures a Linux machine to the corporate base image from default install media + +## Requirements + +--- + +If the "base_core_hostname" variable is defined, it is recommended to set the ansible_ssh_common_args variable for the host to the following setting so the regeneration of the SSH host keys will not cause an error. + +| Variable | Value | +| ----------------------- | ------------------------------------------------------------- | +| ansible_ssh_common_args | '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' | + +## Role Variables + +--- + +### Core Variables + +| Variable | Required | Default | Choices | Comments | +| -------------------------------------------- | -------- | ------------ | ----------- | ---------------------------------------------------------------------- | +| base_core_management_user | No | ansible_user | | Defines the account that ansible will use for management in the future | +| base_core_install_updates | Yes | True | True, False | Install all available updates for the distro at runtime | +| base_core_hostname | No | "" | | Defines the computer hostname | +| base_core_motd_banner | No | "" | | Banner to be added to MOTD if desired | +| base_core_ssh_permit_root_login | Yes | False | True, False | Permits the use of root logins for ssh | +| base_core_ssh_permit_password_authentication | Yes | False | True, False | Permits the use of passwords for ssh | +| base_core_cert_common_name | No | nodename | | Common name for created self-signed cert | +| base_core_root_ca_basename | No | "" | | Basename of the cert for local system reference | +| base_core_root_ca_convert | Yes | False | True, False | Converts the defined certificate from DER to PEM type | +| base_core_root_ca_url | No | "" | | URL of a Root CA to install | +| base_core_web_management | Yes | False | True, False | Enables installation of the Cockpit web management package(s) | + +## Example + +--- + +Execute playbook with needed variables + +`ansible-playbook -i hosts site.yml --ask-pass --ask-become-pass` + +Inventory File: + +```yaml +--- +# file: hosts.yml + +prod: + hosts: + prod-svr01: + ansible_host: 192.168.0.10 + base_core_hostname: "prod-svr01" + prod-svr02: + ansible_host: 192.168.0.11 + + vars: + ansible_ssh_common_args: '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' + base_core_ssh_permit_password_authentication: true + ansible_user: haletek + base_core_motd_banner: "##########################################\n __ __ __ __ __ \n / / / /____ _ / /___ / /_ ___ / /__\n / /_/ // __ `// // _ \\ / __// _ \\ / //_/\n / __ // /_/ // // __// /_ / __// ,< \n/_/ /_/ \\__,_//_/ \\___/ \\__/ \\___//_/|_| \n##########################################" + base_core_root_ca_url: "http://cert.haletek.cloud/PKI/RootCA.cer" + base_core_root_ca_basename: "HLTKCL_RootCA" + base_core_root_ca_convert: false +``` + +### Tags + +--- + +Available tags for the role: + +| Role | Tags | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| Base | all, authorized_key, automatic_updates, cert, firewall, hostname, kernel, motd, password_auth, root_ca, root_login, ssh, time_sync, web_management | diff --git a/base.yml b/base.yml new file mode 100644 index 0000000..d4ba07e --- /dev/null +++ b/base.yml @@ -0,0 +1,7 @@ +--- +# file: base.yml + +- hosts: all + become: true + roles: + - base diff --git a/hosts.yml b/hosts.yml new file mode 100644 index 0000000..59cacbd --- /dev/null +++ b/hosts.yml @@ -0,0 +1,18 @@ +--- +# file: hosts.yml + +prod: + hosts: + prod-svr01: + ansible_host: 192.168.0.10 + base_core_hostname: "prod-svr01" + prod-svr02: + ansible_host: 192.168.0.11 + + vars: + ansible_ssh_common_args: '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' + base_core_ssh_permit_password_authentication: true + ansible_user: haletek + base_core_motd_banner: "##########################################\n __ __ __ __ __ \n / / / /____ _ / /___ / /_ ___ / /__\n / /_/ // __ `// // _ \\ / __// _ \\ / //_/\n / __ // /_/ // // __// /_ / __// ,< \n/_/ /_/ \\__,_//_/ \\___/ \\__/ \\___//_/|_| \n##########################################" + base_core_root_ca_url: "http://cert.haletek.cloud/PKI/RootCA.cer" + base_core_root_ca_basename: "HLTKCL_RootCA" diff --git a/roles/base/defaults/main.yml b/roles/base/defaults/main.yml new file mode 100644 index 0000000..bada66e --- /dev/null +++ b/roles/base/defaults/main.yml @@ -0,0 +1,60 @@ +--- +# file: roles/base/defaults/main.yml + +# **** +# Core +# **** + +# General +# ======= + +# User that should have the authorized keys added +base_core_management_user: "{{ ansible_user }}" + +# Install all available updates at runtime +base_core_install_updates: true + +# Hostname +# ======== + +# Defines the hostname to be forced on the host but is ignored if undefined +base_core_hostname: "" + +# MOTD +# ==== + +# Banner to add to MOTD +base_core_motd_banner: "" + +# SSH +# === + +# Allow ssh root login +base_core_ssh_permit_root_login: false + +# Allow ssh password authentication +base_core_ssh_permit_password_authentication: false + +# Self Signed Cert +# ================ + +# Common name for self signed cert, use hostname as a default +base_core_cert_common_name: "{{ ansible_facts['nodename'] }}" + +# Root CA +# ======= + +# Defines the basename to use for the Root CA +base_core_root_ca_basename: "" + +# Converts the defined certificate from DER to PEM type +base_core_root_ca_convert: false + +# URL to download the Root CA +base_core_root_ca_url: "" + +# Web Management +# ============== + +# Enables the installation of the cockpit web management package(s) +base_core_web_management: false diff --git a/roles/base/handlers/main.yml b/roles/base/handlers/main.yml new file mode 100644 index 0000000..9167ecd --- /dev/null +++ b/roles/base/handlers/main.yml @@ -0,0 +1,29 @@ +--- +# file: roles/base/handlers/main.yml + +- name: Daemon Reload + systemd: + daemon_reload: yes + +- name: Reboot Host + reboot: + +- name: Reload Firewalld + service: + name: firewalld + state: reloaded + +- name: Reload UFW + ufw: + state: reloaded + +- name: Restart SSH + service: + name: sshd + state: restarted + +- name: Update CA Debian + command: update-ca-certificates + +- name: Update CA RedHat + command: /bin/update-ca-trust diff --git a/roles/base/public_keys/ansible_awx b/roles/base/public_keys/ansible_awx new file mode 100644 index 0000000..3e8db57 --- /dev/null +++ b/roles/base/public_keys/ansible_awx @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBACzgUaiXanC7LIMR2JHlNjqHdscstjUQ4ZMJOG9ndZY2Ml81g+KPSUQHsmEAO+24TBVc/EpmeU3iMX4BO6XhUEhRACIAfyxW0zZWBZlO46TWf+oMcH6CQNQHubEpxqGvZd8A0tNxI2npzOEW6b3mKDGd1Z60yBPjNr5KZWVcJePPMwjaw== ansible_awx diff --git a/roles/base/public_keys/thale-bw b/roles/base/public_keys/thale-bw new file mode 100644 index 0000000..fbbc92c --- /dev/null +++ b/roles/base/public_keys/thale-bw @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAGz4ngE94T9hGd7OeHf1fFnEefScPirBTDswVXCci9r5IQUOxQNlTy/Se/pMIiqNyx7xiKbqUF35tFb/Hu6DgnKZgAFyUTKJw8hK7n8R4xugEvjI1buW2cT7B05E1fA/1Q0ZE9F92CXVjwjHI3mRbrxtFBbuGM16PnPhvKMlgzPV5gp6A== thale-bw diff --git a/roles/base/public_keys/thale-desktop b/roles/base/public_keys/thale-desktop new file mode 100644 index 0000000..81965a2 --- /dev/null +++ b/roles/base/public_keys/thale-desktop @@ -0,0 +1,2 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAr8WVfAwXo2mpzfoIb6j/TOi8rvrvhHgVmDK8W+qq0AQLXKXJFof4yfiDpsxOOuMpgN1OqtMuIq1q5BHu1QdDhQwHF/W3U3OnhA8EFBaIqTdg1xZqI985NOslb4ZmNBdE3zmR3WHf2JvjbWap7MXzWFZyhl5b/khix05mN5X+66BhQag== thale-desktop + diff --git a/roles/base/public_keys/thale-laptop b/roles/base/public_keys/thale-laptop new file mode 100644 index 0000000..33cdc8d --- /dev/null +++ b/roles/base/public_keys/thale-laptop @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBACBwI8/hl03oNEdeVwswy+pnh3DwCTmnn+tW//UdHURxqIUV2gI1t06HlHOkc7GSJuxkCgyq8QulzDyqw04B9cahQCcOiA3KGGDuZ9o8THNKtOLlrLfsuWy8sUaWQC3ThXhGgJn0Yl5T+3AY7vtxUUy/EIyYMPqNpiZI/a7vECduR0VrA== thale-laptop diff --git a/roles/base/public_keys/thale-phone b/roles/base/public_keys/thale-phone new file mode 100644 index 0000000..38e4337 --- /dev/null +++ b/roles/base/public_keys/thale-phone @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAEVNT5rXIswezr8ItJRhPoOrajSAedK8NtM1Di2VD/zqtPvqGCwwJ7mXkX9jtVsSmLSkX5CjMBtUnisbbL5ccsAngFWaXcuCtiA4RTbC+0nLuho5YoFeRhqp4V85OjP90NOPGmaglj5Ic9GDGx0gYfoSn3axCxoGRMKwc4MSjU1+cZEpA== thale-phone diff --git a/roles/base/public_keys/thale-work b/roles/base/public_keys/thale-work new file mode 100644 index 0000000..704ce20 --- /dev/null +++ b/roles/base/public_keys/thale-work @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBACrXaAsTYw2ltE364tsiUYZ1l4DSzIWwLHcFyf2tl2RhyWcYlfUY5banoMsL9QBg33AOmeP//O8dKMFXWz48OFp4wF6+/U+nfpbZQru/ejRLwD1M+hlYqhPNDpysWLf8LH9c8VhfRpk1Y27AfbROuR8BkUrdKChCz2gMnVJnqnnapE7nQ== thale-work diff --git a/roles/base/tasks/core.yml b/roles/base/tasks/core.yml new file mode 100644 index 0000000..ceeda15 --- /dev/null +++ b/roles/base/tasks/core.yml @@ -0,0 +1,62 @@ +--- +# file: roles/base/tasks/core.yml + +- name: "*** Hostname Configuration ***" + include_tasks: + file: core_hostname.yml + apply: + tags: hostname + tags: + - hostname + +# Gather facts now that the hostname may have changed +- name: Gather facts + setup: + when: hostname_change.changed + +- name: Gather service facts + service_facts: + tags: + - always + +- name: "*** MOTD Configuration ***" + include_tasks: + file: core_motd.yml + apply: + tags: motd + tags: + - motd + +- name: "*** SSH Configuration ***" + include_tasks: + file: core_ssh.yml + apply: + tags: ssh + tags: + - ssh + +- name: "*** Generate Self-Signed Cert ***" + include_tasks: + file: core_cert.yml + apply: + tags: cert + when: base_core_cert_common_name != '' + tags: + - cert + +- name: "*** Root CA Install ***" + include_tasks: + file: core_root_ca.yml + apply: + tags: root_ca + tags: + - root_ca + +- name: "*** Web Management Configuration ***" + include_tasks: + file: core_web_management.yml + apply: + tags: web_management + when: base_core_web_management == true + tags: + - web_management diff --git a/roles/base/tasks/core_cert.yml b/roles/base/tasks/core_cert.yml new file mode 100644 index 0000000..958235c --- /dev/null +++ b/roles/base/tasks/core_cert.yml @@ -0,0 +1,53 @@ +--- +# file: roles/base/tasks/core_cert.yml + +- name: Install pip + package: + name: python3-pip + state: latest + register: pip_install + when: ansible_python_version is version('3', '>=') + +- name: Upgrade pip + command : pip3 install -U pip + when: pip_install.changed + +- name: Install latest python2-cryptography + package: + name: python2-cryptography + state: latest + when: ((ansible_python_version is version('2', '>=')) and (ansible_python_version is version('3', '<')) ) + +- name: Install latest cryptography + pip: + name: cryptography + state: latest + when: ansible_python_version is version('3', '>=') + +- name: Ensure directory exists for local self-signed TLS certs + file: + path: /etc/ssl/{{ base_core_cert_common_name }}/live + state: directory + +- name: Generate an OpenSSL private key + openssl_privatekey: + path: /etc/ssl/{{ base_core_cert_common_name }}/live/privkey.pem + +- name: Generate an OpenSSL CSR + openssl_csr: + path: /etc/ssl/{{ base_core_cert_common_name }}/{{ base_core_cert_common_name }}.csr + privatekey_path: /etc/ssl/{{ base_core_cert_common_name }}/live/privkey.pem + common_name: "{{ base_core_cert_common_name }}" + +- name: Generate a self signed OpenSSL certificate + openssl_certificate: + path: /etc/ssl/{{ base_core_cert_common_name }}/live/fullchain.pem + privatekey_path: /etc/ssl/{{ base_core_cert_common_name }}/live/privkey.pem + csr_path: /etc/ssl/{{ base_core_cert_common_name }}/{{ base_core_cert_common_name }}.csr + provider: selfsigned + +- name: Create merged certificate + assemble: + src: /etc/ssl/{{ base_core_cert_common_name }}/live/ + dest: /etc/ssl/{{ base_core_cert_common_name }}/live/merged.pem + regexp: '(fullchain.pem$|privkey.pem$)' diff --git a/roles/base/tasks/core_hostname.yml b/roles/base/tasks/core_hostname.yml new file mode 100644 index 0000000..459a2f5 --- /dev/null +++ b/roles/base/tasks/core_hostname.yml @@ -0,0 +1,58 @@ +--- +# file: roles/base/tasks/core_hostname.yml + +- name: Ensure system hostname + hostname: + name: "{{ base_core_hostname }}" + when: base_core_hostname != "" and base_core_hostname != ansible_facts['nodename'] + register: hostname_change + notify: Reboot Host + +- block: + - name: Ensure hostname is set in /etc/hosts + lineinfile: + dest: /etc/hosts + regexp: '^127\.0\.0\.1[ \t]+localhost' + line: '127.0.0.1 localhost {{ base_core_hostname }}' + state: present + + - name: Ensure hostname is set in /etc/hosts + lineinfile: + dest: /etc/hosts + regexp: '^127\.0\.1\.1[ \t]' + line: '127.0.1.1 {{ base_core_hostname }}' + state: present + + - name: Remove ssh certs + file: + state: absent + path: "{{item}}" + loop: + - /etc/ssh/ssh_host_rsa_key + - /etc/ssh/ssh_host_dsa_key + - /etc/ssh/ssh_host_ecdsa_key + - /etc/ssh/ssh_host_ed25519_key + + - name: Generate /etc/ssh/ RSA host key + command : ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C "" -N "" + args: + creates: /etc/ssh/ssh_host_rsa_key + + - name: Generate /etc/ssh/ DSA host key + command : ssh-keygen -q -t dsa -f /etc/ssh/ssh_host_dsa_key -C "" -N "" + args: + creates: /etc/ssh/ssh_host_dsa_key + + - name: Generate /etc/ssh/ ECDSA host key + command : ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C "" -N "" + args: + creates: /etc/ssh/ssh_host_ecdsa_key + + - name: Generate /etc/ssh/ ED25519 host key + command : ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -C "" -N "" + args: + creates: /etc/ssh/ssh_host_ed25519_key + when: hostname_change.changed + +- name: Flush handlers + meta: flush_handlers diff --git a/roles/base/tasks/core_motd.yml b/roles/base/tasks/core_motd.yml new file mode 100644 index 0000000..1bbe7f8 --- /dev/null +++ b/roles/base/tasks/core_motd.yml @@ -0,0 +1,42 @@ +--- +# file: roles/base/tasks/core_motd.yml + +- name: Disable unnecessary MOTD files + file: + path: "{{ item }}" + mode: 644 + with_items: + - "/etc/update-motd.d/00-header" + - "/etc/update-motd.d/10-help-text" + - "/etc/update-motd.d/50-motd-news" + - "/etc/update-motd.d/50-landscape-sysinfo" + when: ansible_os_family == "Debian" + +- name: Disable motd-news service in config file + ansible.builtin.lineinfile: + path: /etc/default/motd-news + regexp: ^ENABLED= + line: "ENABLED=0" + when: ansible_os_family == "Debian" + notify: + - Reboot Host + +- name: Disable motd-news timer + service: + name: motd-news.timer + state: stopped + enabled: no + when: ansible_os_family == "Debian" + +- name: Install the MOTD Script + template: + src: motd.j2 + dest: /etc/profile.d/login-info.sh + +- name: Configure SSH to not use the default MOTD + lineinfile: + path: /etc/ssh/sshd_config + regexp: '^#?PrintMotd ' + line: PrintMotd no + notify: + - Restart SSH diff --git a/roles/base/tasks/core_root_ca.yml b/roles/base/tasks/core_root_ca.yml new file mode 100644 index 0000000..c80d5b3 --- /dev/null +++ b/roles/base/tasks/core_root_ca.yml @@ -0,0 +1,73 @@ +--- +# file: roles/base/tasks/core_root_ca.yml + +- name: Install ca-certificates package + package: + name: ca-certificates + state: latest + +- block: + - name: Create temporary file for cert download + tempfile: + state: file + suffix: temp + register: cert_download + changed_when: False + + - name: Download root CA cert + get_url: + url: "{{ base_core_root_ca_url }}" + dest: "{{ cert_download.path }}" + force: yes + changed_when: False + + - block: + - name: Convert der to pem + command: "openssl x509 -inform DER -outform PEM -in '{{ cert_download.path }}' -out '{{ cert_download.path }}.crt'" + changed_when: False + + - name: Replace the temp file with the converted cert + copy: + src: "{{ cert_download.path }}.crt" + dest: "{{ cert_download.path }}" + remote_src: yes + changed_when: False + + - name: Remove the temporary converted cert + file: + path: "{{ cert_download.path }}.crt" + state: absent + changed_when: False + when: base_core_root_ca_convert == true + + - name: Ensure CR are removed + replace: + dest: "{{ cert_download.path }}" + regexp: "\r" + changed_when: False + + - name: Copy the certificate + copy: + src: "{{ cert_download.path }}" + dest: "/usr/local/share/ca-certificates/{{ base_core_root_ca_basename }}.crt" + remote_src: yes + notify: Update CA Debian + when: ansible_os_family == "Debian" + + - name: Copy the certificate + copy: + src: "{{ cert_download.path }}" + dest: "/etc/pki/ca-trust/source/anchors/{{ base_core_root_ca_basename }}.crt" + remote_src: yes + notify: Update CA RedHat + when: ansible_os_family == "RedHat" + + - name: Remove the temporary file + file: + path: "{{ cert_download.path }}" + state: absent + when: cert_download.path is defined + changed_when: False + when: base_core_root_ca_url != "" and base_core_root_ca_basename != "" + + diff --git a/roles/base/tasks/core_ssh.yml b/roles/base/tasks/core_ssh.yml new file mode 100644 index 0000000..e8490a2 --- /dev/null +++ b/roles/base/tasks/core_ssh.yml @@ -0,0 +1,51 @@ +--- +# file: roles/base/tasks/core_ssh.yml + +- name: Install the issue notice + template: + src: issue.j2 + dest: /etc/issue + notify: Restart SSH + tags: + - issue + +- name: Configure SSH to display the issue notice + lineinfile: + path: /etc/ssh/sshd_config + regexp: '^#?Banner ' + line: Banner /etc/issue + notify: Restart SSH + tags: + - issue + +- name: Setup authorized keys + authorized_key: + user: "{{ base_core_management_user }}" + state: present + key: '{{ lookup("file", item) }}' + with_fileglob: + - "public_keys/*" + tags: + - authorized_key + +- name: Configure SSH root login + lineinfile: + path: /etc/ssh/sshd_config + regexp: '^#?PermitRootLogin ' + line: PermitRootLogin no + when: base_core_ssh_permit_root_login == false + notify: + - Restart SSH + tags: + - root_login + +- name: Configure SSH password auth + lineinfile: + path: /etc/ssh/sshd_config + regexp: '^#?PasswordAuthentication ' + line: PasswordAuthentication no + when: base_core_ssh_permit_password_authentication == false + notify: + - Restart SSH + tags: + - password_auth diff --git a/roles/base/tasks/core_web_management.yml b/roles/base/tasks/core_web_management.yml new file mode 100644 index 0000000..3f975f0 --- /dev/null +++ b/roles/base/tasks/core_web_management.yml @@ -0,0 +1,39 @@ +--- +# file: roles/base/tasks/core_web_management.yml + +- name: Install cockpit packages + package: + name: + - cockpit + - cockpit-networkmanager + - cockpit-packagekit + - cockpit-storaged + - cockpit-dashboard + state: present + +- name: Install cockpit-machines package + package: + name: cockpit-machines + state: present + when: "'libvirt' in services" + +- name: Install redhat cockpit packages + package: + name: + - cockpit-selinux + - cockpit-sosreport + state: present + when: ansible_os_family == "RedHat" + +- name: Use created self-signed cert + file: + src: /etc/ssl/{{ base_core_cert_common_name }}/live/merged.pem + dest: /etc/cockpit/ws-certs.d/50-ansible.crt + state: link + when: base_core_cert_common_name != '' + +- name: Start and enable cockpit service + service: + name: cockpit.socket + state: started + enabled: yes diff --git a/roles/base/tasks/debian.yml b/roles/base/tasks/debian.yml new file mode 100644 index 0000000..ac4100c --- /dev/null +++ b/roles/base/tasks/debian.yml @@ -0,0 +1,40 @@ +--- +# file: roles/base/tasks/debian.yml + +- name: Install Current Updates + apt: + upgrade: full + update_cache: yes + when: base_core_install_updates == true + +- name: "*** Debian: Kernel Configuration ***" + include_tasks: + file: debian_kernel.yml + apply: + tags: kernel + tags: + - kernel + +- name: "*** Debian: Time Sync Configuration ***" + include_tasks: + file: debian_time_sync.yml + apply: + tags: time_sync + tags: + - time_sync + +- name: "*** Debian: Automatic Updates Configuration ***" + include_tasks: + file: debian_automatic_updates.yml + apply: + tags: automatic_updates + tags: + - automatic_updates + +- name: "*** Debian: Firewall Configuration ***" + include_tasks: + file: debian_firewall.yml + apply: + tags: firewall + tags: + - firewall diff --git a/roles/base/tasks/debian_automatic_updates.yml b/roles/base/tasks/debian_automatic_updates.yml new file mode 100644 index 0000000..ca35f8a --- /dev/null +++ b/roles/base/tasks/debian_automatic_updates.yml @@ -0,0 +1,56 @@ +--- +# file: roles/base/tasks/debian_automatic_updates.yml + +- name: Install unattended upgrade packages + package: + name: + - unattended-upgrades + - update-notifier-common + state: latest + +- name: Activate auto upgrades + template: + src: 20auto-upgrades.j2 + dest: /etc/apt/apt.conf.d/20auto-upgrades + +- name: Enable updates for all repos + lineinfile: + path: /etc/apt/apt.conf.d/50unattended-upgrades + regexp: '"\${distro_id}:\${distro_codename}-updates";' + line: ' "*:*";' + +- name: Enable auto-reboot + lineinfile: + path: /etc/apt/apt.conf.d/50unattended-upgrades + regexp: '^\/?\/?Unattended-Upgrade::Automatic-Reboot ' + line: 'Unattended-Upgrade::Automatic-Reboot "true";' + +- name: Configure auto-reboot time + lineinfile: + path: /etc/apt/apt.conf.d/50unattended-upgrades + regexp: '^\/?\/?Unattended-Upgrade::Automatic-Reboot-Time ' + line: 'Unattended-Upgrade::Automatic-Reboot-Time "03:30";' + +- name: Ensure directory exists for daily download timer + file: + path: /etc/systemd/system/apt-daily.timer.d + recurse: yes + state: directory + +- name: Configure daily download timer + template: + src: apt-daily.timer.d_override.conf.j2 + dest: /etc/systemd/system/apt-daily.timer.d/override.conf + notify: Daemon Reload + +- name: Ensure directory exists for daily upgrade timer + file: + path: /etc/systemd/system/apt-daily-upgrade.timer.d + recurse: yes + state: directory + +- name: Configure daily upgrade timer + template: + src: apt-daily-upgrade.timer.d_override.conf.j2 + dest: /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf + notify: Daemon Reload diff --git a/roles/base/tasks/debian_firewall.yml b/roles/base/tasks/debian_firewall.yml new file mode 100644 index 0000000..13cf9cb --- /dev/null +++ b/roles/base/tasks/debian_firewall.yml @@ -0,0 +1,25 @@ +--- +# file: roles/base/tasks/debian_firewall.yml + +- name: Allow SSH access through the firewall + ufw: + rule: allow + port: "22" + proto: tcp + interface: eth0 + direction: in + notify: Reload UFW + +- name: Allow web management access through the firewall + ufw: + rule: allow + port: "9090" + proto: tcp + notify: Reload UFW + when: base_core_web_management == true + tags: + - web_management + +- name: Enable firewall + ufw: + state: enabled diff --git a/roles/base/tasks/debian_kernel.yml b/roles/base/tasks/debian_kernel.yml new file mode 100644 index 0000000..0315253 --- /dev/null +++ b/roles/base/tasks/debian_kernel.yml @@ -0,0 +1,8 @@ +--- +# file: roles/base/tasks/debian_kernel.yml + +- name: Install linux-azure kernel + package: + name: linux-azure + state: latest + notify: Reboot Host diff --git a/roles/base/tasks/debian_time_sync.yml b/roles/base/tasks/debian_time_sync.yml new file mode 100644 index 0000000..d219447 --- /dev/null +++ b/roles/base/tasks/debian_time_sync.yml @@ -0,0 +1,31 @@ +--- +# file: roles/base/tasks/debian_time_sync.yml + +- name: Install chrony + package: + name: chrony + state: latest + +- name: Set refclock + lineinfile: + path: /etc/chrony/chrony.conf + line: 'refclock PHC /dev/ptp0 trust poll 1 filter 4' + insertafter: EOF + +- name: Set makestep + lineinfile: + path: /etc/chrony/chrony.conf + regexp: '^makestep ' + line: 'makestep 1 -1' + +- name: Disable systemd-timesyncd + service: + name: systemd-timesyncd + state: stopped + enabled: false + +- name: Enable chrony + service: + name: chronyd + state: started + enabled: true diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml new file mode 100644 index 0000000..5dda5ee --- /dev/null +++ b/roles/base/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# file: roles/base/tasks/main.yml + +- name: "### Core Tasks ###" + include_tasks: + file: core.yml + tags: + - always + +- name: "### Debian Family ###" + include_tasks: + file: debian.yml + when: ansible_os_family == "Debian" + tags: + - always + +- name: "### RedHat Family ###" + include_tasks: + file: redhat.yml + when: ansible_os_family == "RedHat" + tags: + - always diff --git a/roles/base/tasks/redhat.yml b/roles/base/tasks/redhat.yml new file mode 100644 index 0000000..e418f0a --- /dev/null +++ b/roles/base/tasks/redhat.yml @@ -0,0 +1,40 @@ +--- +# file: roles/base/tasks/redhat.yml + +- name: Install Current Updates + yum: + name: '*' + state: latest + when: base_core_install_updates == true + +- name: "*** RedHat: EPEL Install ***" + include_tasks: + file: redhat_epel.yml + apply: + tags: epel + tags: + - epel + +- name: "*** RedHat: Time Sync Configuration ***" + include_tasks: + file: redhat_time_sync.yml + apply: + tags: time_sync + tags: + - time_sync + +- name: "*** RedHat: Automatic Updates Configuration ***" + include_tasks: + file: redhat_automatic_updates.yml + apply: + tags: automatic_updates + tags: + - automatic_updates + +- name: "*** RedHat: Firewall Configuration ***" + include_tasks: + file: redhat_firewall.yml + apply: + tags: firewall + tags: + - firewall diff --git a/roles/base/tasks/redhat_automatic_updates.yml b/roles/base/tasks/redhat_automatic_updates.yml new file mode 100644 index 0000000..6154f9f --- /dev/null +++ b/roles/base/tasks/redhat_automatic_updates.yml @@ -0,0 +1,50 @@ +--- +# file: roles/base/tasks/redhat_automatic_updates.yml + +- name: Install dnf-automatic package + package: + name: dnf-automatic + state: present + +- name: Install yum-utils package for needs restarting + package: + name: yum-utils + state: present + when: ansible_distribution_major_version == 7 + +- name: Deploy dnf-automatic configuration file + template: + src: automatic.conf.j2 + dest: /etc/dnf/automatic.conf + +- name: Create dnf-automatic-install.timer directory + file: + path: /etc/systemd/system/dnf-automatic-install.timer.d + recurse: yes + state: directory + +- name: Deploy dnf-automatic install timer override + template: + src: dnf-automatic-install.timer.j2 + dest: /etc/systemd/system/dnf-automatic-install.timer.d/time.conf + become: yes + notify: Daemon Reload + +- name: Start and enable systemd timer for dnf-automatic + service: + name: dnf-automatic-install.timer + state: started + enabled: yes + +- name: Create dnf-automatic-install.service directory + file: + path: /etc/systemd/system/dnf-automatic-install.service.d + recurse: yes + state: directory + +- name: Deploy dnf-automatic install service override + template: + src: "dnf-automatic-install.service-{{ ansible_distribution_major_version }}.j2" + dest: /etc/systemd/system/dnf-automatic-install.service.d/override.conf + become: yes + notify: Daemon Reload diff --git a/roles/base/tasks/redhat_epel.yml b/roles/base/tasks/redhat_epel.yml new file mode 100644 index 0000000..836f47f --- /dev/null +++ b/roles/base/tasks/redhat_epel.yml @@ -0,0 +1,8 @@ +--- +# file: roles/base/tasks/redhat_epel.yml + +- name: Install EPEL RPM + package: + name: "https://dl.fedoraproject.org/pub/epel/epel-release-latest-{{ ansible_distribution_major_version }}.noarch.rpm" + state: present + disable_gpg_check: True diff --git a/roles/base/tasks/redhat_firewall.yml b/roles/base/tasks/redhat_firewall.yml new file mode 100644 index 0000000..9f9863f --- /dev/null +++ b/roles/base/tasks/redhat_firewall.yml @@ -0,0 +1,25 @@ +--- +# file: roles/base/tasks/redhat_firewall.yml + +- name: Allow SSH access through the firewall + firewalld: + service: ssh + permanent: yes + state: enabled + notify: Reload Firewalld + +- name: Allow web management access through the firewall + firewalld: + service: cockpit + permanent: yes + state: enabled + notify: Reload Firewalld + when: base_core_web_management == true + tags: + - web_management + +- name: Enable firewall + service: + name: firewalld + state: started + enabled: yes \ No newline at end of file diff --git a/roles/base/tasks/redhat_time_sync.yml b/roles/base/tasks/redhat_time_sync.yml new file mode 100644 index 0000000..71d3c1e --- /dev/null +++ b/roles/base/tasks/redhat_time_sync.yml @@ -0,0 +1,13 @@ +--- +# file: roles/base/tasks/redhat_time_sync.yml + +- name: Install chrony package + package: + name: chrony + state: present + +- name: Start and enable chrony + service: + name: chronyd + state: started + enabled: yes diff --git a/roles/base/templates/20auto-upgrades.j2 b/roles/base/templates/20auto-upgrades.j2 new file mode 100644 index 0000000..8d6d7c8 --- /dev/null +++ b/roles/base/templates/20auto-upgrades.j2 @@ -0,0 +1,2 @@ +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; diff --git a/roles/base/templates/apt-daily-upgrade.timer.d_override.conf.j2 b/roles/base/templates/apt-daily-upgrade.timer.d_override.conf.j2 new file mode 100644 index 0000000..f2e45f5 --- /dev/null +++ b/roles/base/templates/apt-daily-upgrade.timer.d_override.conf.j2 @@ -0,0 +1,4 @@ +[Timer] +OnCalendar= +OnCalendar=02:15 +RandomizedDelaySec=0 diff --git a/roles/base/templates/apt-daily.timer.d_override.conf.j2 b/roles/base/templates/apt-daily.timer.d_override.conf.j2 new file mode 100644 index 0000000..fdd89c0 --- /dev/null +++ b/roles/base/templates/apt-daily.timer.d_override.conf.j2 @@ -0,0 +1,4 @@ +[Timer] +OnCalendar= +OnCalendar=02:00 +RandomizedDelaySec=0 diff --git a/roles/base/templates/automatic.conf.j2 b/roles/base/templates/automatic.conf.j2 new file mode 100644 index 0000000..2ec99d8 --- /dev/null +++ b/roles/base/templates/automatic.conf.j2 @@ -0,0 +1,100 @@ +[commands] +# What kind of upgrade to perform: +# default = all available upgrades +# security = only the security upgrades +upgrade_type = {{ base_redhat_dnf_automatic_upgrade_type }} +random_sleep = {{ base_redhat_dnf_automatic_random_sleep }} + +# To just receive updates use dnf-automatic-notifyonly.timer + +# Whether updates should be downloaded when they are available, by +# dnf-automatic.timer. notifyonly.timer, download.timer and +# install.timer override this setting. +download_updates = {{ base_redhat_dnf_automatic_download_updates }} + +# Whether updates should be applied when they are available, by +# dnf-automatic.timer. notifyonly.timer, download.timer and +# install.timer override this setting. +apply_updates = {{ base_redhat_dnf_automatic_apply_updates }} + + +[emitters] +# Name to use for this system in messages that are emitted. Default is the +# hostname. +{% if base_redhat_dnf_automatic_system_name != '' %} +system_name = {{ base_redhat_dnf_automatic_system_name }} +{% else %} +# system_name = my-host +{% endif %} + +# How to send messages. Valid options are stdio, email and motd. If +# emit_via includes stdio, messages will be sent to stdout; this is useful +# to have cron send the messages. If emit_via includes email, this +# program will send email itself according to the configured options. +# If emit_via includes motd, /etc/motd file will have the messages. if +# emit_via includes command_email, then messages will be send via a shell +# command compatible with sendmail. +# Default is email,stdio. +# If emit_via is None or left blank, no messages will be sent. +emit_via = {{ base_redhat_dnf_automatic_emit_via }} + + +[email] +# The address to send email messages from. +email_from = {{ base_redhat_dnf_automatic_email_from }} + +# List of addresses to send messages to. +email_to = {{ base_redhat_dnf_automatic_email_to }} + +# Name of the host to connect to to send email messages. +email_host = {{ base_redhat_dnf_automatic_email_host }} + + +[command] +# The shell command to execute. This is a Python format string, as used in +# str.format(). The format function will pass a shell-quoted argument called +# `body`. +{% if base_redhat_dnf_automatic_command_format != '' %} +command_format = {{ base_redhat_dnf_automatic_command_format }} +{% else %} +# command_format = "cat" +{% endif %} + +# The contents of stdin to pass to the command. It is a format string with the +# same arguments as `command_format`. +{% if base_redhat_dnf_automatic_stdin_format != '' %} +stdin_format = {{ base_redhat_dnf_automatic_stdin_format }} +{% else %} +# stdin_format = "{body}" +{% endif %} + +[command_email] +# The shell command to use to send email. This is a Python format string, +# as used in str.format(). The format function will pass shell-quoted arguments +# called body, subject, email_from, email_to. +{% if base_redhat_dnf_automatic_email_command_format != '' %} +command_format = {{ base_redhat_dnf_automatic_email_command_format }} +{% else %} +# command_format = "mail -s {subject} -r {email_from} {email_to}" +{% endif %} + +# The contents of stdin to pass to the command. It is a format string with the +# same arguments as `command_format`. +{% if base_redhat_dnf_automatic_email_stdin_format != '' %} +stdin_format = {{ base_redhat_dnf_automatic_email_stdin_format }} +{% else %} +# stdin_format = "{body}" +{% endif %} + +# The address to send email messages from. +email_from = {{ base_redhat_dnf_automatic_email_from }} + +# List of addresses to send messages to. +email_to = {{ base_redhat_dnf_automatic_email_to }} + + +[base] +# This section overrides dnf.conf + +# Use this to filter DNF core messages +debuglevel = 1 diff --git a/roles/base/templates/dnf-automatic-install.service-7.j2 b/roles/base/templates/dnf-automatic-install.service-7.j2 new file mode 100644 index 0000000..00ee6eb --- /dev/null +++ b/roles/base/templates/dnf-automatic-install.service-7.j2 @@ -0,0 +1,2 @@ +[Service] +ExecStartPost=/bin/sh -ec 'needs-restarting -r | grep -q "Reboot is req.*" && shutdown -r +5 Rebooting after applying package updates || exit 0' diff --git a/roles/base/templates/dnf-automatic-install.service-8.j2 b/roles/base/templates/dnf-automatic-install.service-8.j2 new file mode 100644 index 0000000..58b55d1 --- /dev/null +++ b/roles/base/templates/dnf-automatic-install.service-8.j2 @@ -0,0 +1,2 @@ +[Service] +ExecStartPost=/bin/sh -ec 'dnf needs-restarting -r | grep -q "Reboot is req.*" && shutdown -r +5 Rebooting after applying package updates || exit 0' diff --git a/roles/base/templates/dnf-automatic-install.timer.j2 b/roles/base/templates/dnf-automatic-install.timer.j2 new file mode 100644 index 0000000..2fb9629 --- /dev/null +++ b/roles/base/templates/dnf-automatic-install.timer.j2 @@ -0,0 +1,5 @@ +[Timer] +OnBootSec= +OnCalendar= 2:00 +RandomizedDelaySec=5m +AccuracySec=1s diff --git a/roles/base/templates/issue.j2 b/roles/base/templates/issue.j2 new file mode 100644 index 0000000..ba6ddce --- /dev/null +++ b/roles/base/templates/issue.j2 @@ -0,0 +1,16 @@ +#jinja2: trim_blocks:False +********************************************************************* +* * +* Unauthorized access to this machine is prohibited * +* Disconnect if you are not an authorized user * +* * +* This system is for the use of authorized users only. Usage of * +* this system may be monitored and recorded by system personnel. * +* * +* Anyone using this system expressly consents to such monitoring * +* and is advised that if such monitoring reveals possible * +* evidence of criminal activity, system personnel may provide the * +* evidence from such monitoring to law enforcement officials. * +* * +********************************************************************* + diff --git a/roles/base/templates/motd.j2 b/roles/base/templates/motd.j2 new file mode 100644 index 0000000..fd7e6ec --- /dev/null +++ b/roles/base/templates/motd.j2 @@ -0,0 +1,48 @@ +#! /usr/bin/env bash + +# Basic info +HOSTNAME=`uname -n` +OSVERSION=`hostnamectl | grep "Operating System" | sed 's/^.*: //'` +CURRENTTIME=`date +"%Y-%m-%d %H:%M:%S"` +UPTIMEP=`uptime -p` +BOOTTIME=`uptime -s` +CONNECTEDUSERS=`who | wc -l` + +# System load +MEMORY1=`free -t -m | grep Total | awk '{print $3" MB";}'` +MEMORY2=`free -t -m | grep "Mem" | awk '{print $2" MB";}'` +MEMORY3=`free -t -m | grep Mem | awk '{print $3/$2 * 100.0}'` +MEMORY4=`printf %.0f $MEMORY3` +LOAD1=`cat /proc/loadavg | awk {'print $1'}` +LOAD5=`cat /proc/loadavg | awk {'print $2'}` +LOAD15=`cat /proc/loadavg | awk {'print $3'}` +PROCESSES=`ps ax | wc -l | tr -d " "` +SWAPSTAT=`free -m | tail -n 1 | awk '{print $3}'` +USAGEROOT=`df -Ph | grep /$ | awk '{print $5 " of " $2}'` +IPADDRESSES=`ip a|grep -oP "inet \K[0-9.]*(?=.*[^ ][^l][^o]$)"` + +{% if base_core_motd_banner != '' %} +BANNER=' +{{ base_core_motd_banner }} +' + +echo "$BANNER +********************************************************************* +{% else %} +echo "********************************************************************* +{% endif %} + - Hostname............: $HOSTNAME + - Operating System....: $OSVERSION + - Uptime..............: $UPTIMEP + - Current Time........: $CURRENTTIME + - Boot Time...........: $BOOTTIME + - Logged on users.....: $CONNECTEDUSERS +********************************************************************* + - Running Processes...: $PROCESSES + - CPU usage...........: $LOAD1, $LOAD5, $LOAD15 (1, 5, 15 min) + - Memory usage........: $MEMORY1 / $MEMORY2 ($MEMORY4%) + - Swap in use.........: $SWAPSTAT MB + - Usage of /..........: $USAGEROOT + - IP Addresses........: $IPADDRESSES +********************************************************************* +" diff --git a/roles/base/vars/main.yml b/roles/base/vars/main.yml new file mode 100644 index 0000000..c7787cd --- /dev/null +++ b/roles/base/vars/main.yml @@ -0,0 +1,43 @@ +--- +# file: roles/base/vars/main.yml + + +# ****** +# RedHat +# ****** + +# DNF Automatic +# ============= + +# commands +# -------- + +base_redhat_dnf_automatic_apply_updates: yes +base_redhat_dnf_automatic_download_updates: yes +base_redhat_dnf_automatic_upgrade_type: default +base_redhat_dnf_automatic_random_sleep: 0 + +# emitters +# -------- + +base_redhat_dnf_automatic_emit_via: stdio +base_redhat_dnf_automatic_system_name: "{{ ansible_facts['nodename'] }}" + +# command +# ------- + +base_redhat_dnf_automatic_command_format: "" +base_redhat_dnf_automatic_stdin_format: "" + +# command_email +# ------------- + +base_redhat_dnf_automatic_email_command_format: "" +base_redhat_dnf_automatic_email_stdin_format: "" + +# email +# ----- + +base_redhat_dnf_automatic_email_from: root +base_redhat_dnf_automatic_email_to: root +base_redhat_dnf_automatic_email_host: localhost diff --git a/site.yml b/site.yml new file mode 100644 index 0000000..f12b485 --- /dev/null +++ b/site.yml @@ -0,0 +1,5 @@ +--- +# file: site.yml +## This playbook deploys the whole application stack in this site. + +- import_playbook: base.yml