From 0ca263c251d8bd8cfeebc4b2f8fc76c7fa9a456c Mon Sep 17 00:00:00 2001 From: syrell Date: Sun, 7 May 2023 12:01:52 +0200 Subject: [PATCH] Added base patch management role --- roles/unattended-upgrades/README.rst | 89 +++++++++++++++++++ roles/unattended-upgrades/defaults/main.yml | 16 ++++ roles/unattended-upgrades/handlers/main.yml | 14 +++ roles/unattended-upgrades/meta/main.yml | 52 +++++++++++ roles/unattended-upgrades/tasks/main.yml | 12 +++ roles/unattended-upgrades/tasks/postfix.yml | 55 ++++++++++++ .../tasks/unattended-upgrades.yml | 25 ++++++ .../templates/mail_credentials.j2 | 1 + .../templates/mail_generic.j2 | 1 + .../templates/mail_headers.j2 | 1 + .../unattended-upgrades/templates/main.cf.j2 | 29 ++++++ .../templates/reboot_alert.sh.j2 | 5 ++ .../templates/unattended-upgrades.j2 | 23 +++++ roles/unattended-upgrades/vars/main.yml | 2 + 14 files changed, 325 insertions(+) create mode 100644 roles/unattended-upgrades/README.rst create mode 100644 roles/unattended-upgrades/defaults/main.yml create mode 100644 roles/unattended-upgrades/handlers/main.yml create mode 100644 roles/unattended-upgrades/meta/main.yml create mode 100644 roles/unattended-upgrades/tasks/main.yml create mode 100644 roles/unattended-upgrades/tasks/postfix.yml create mode 100644 roles/unattended-upgrades/tasks/unattended-upgrades.yml create mode 100644 roles/unattended-upgrades/templates/mail_credentials.j2 create mode 100644 roles/unattended-upgrades/templates/mail_generic.j2 create mode 100644 roles/unattended-upgrades/templates/mail_headers.j2 create mode 100644 roles/unattended-upgrades/templates/main.cf.j2 create mode 100644 roles/unattended-upgrades/templates/reboot_alert.sh.j2 create mode 100644 roles/unattended-upgrades/templates/unattended-upgrades.j2 create mode 100644 roles/unattended-upgrades/vars/main.yml diff --git a/roles/unattended-upgrades/README.rst b/roles/unattended-upgrades/README.rst new file mode 100644 index 0000000..a703c34 --- /dev/null +++ b/roles/unattended-upgrades/README.rst @@ -0,0 +1,89 @@ +Unattended-upgrades setup +========================= + +Unattended-upgrades setup role. It also installs and configures Postfix as a SMTP relay in order to send emails when target system needs to be rebooted. + +Requirements +------------ + +This role was written for Debian (11) and requires root privileges. + +Role Variables +-------------- + +Variables can be found in the `default vars `_. As a bare minimum you should configure SMTP credentials. + +.. code-block:: yaml + + upgrades_sender: "{{ ansible_user }}@{{ ansible_hostname }}.lan" + +Defines which email unattended-upgrades will use to send emails. + +.. code-block:: yaml + + postfix_hostname: "{{ ansible_hostname }}.lan" + +Configures Postfix hostname. + +.. code-block:: yaml + + smtp_username: + smtp_password: + smtp_port: 587 + +SMTP credentials (required). Port defaults to 587 (STARTTLS). + +.. code-block::yaml + + relay_servername: "{{ smtp_username | regex_search('(?<=@)(.+)\\.[\\w]+$') }}" + +SMTP servername, defaults to ``smtp_username`` domain. If yours differs modify it here. + +.. code-block:: yaml + + custom_smtp_header: false + from_header: + from_email: + +Customizes SMTP header. Make sure to configure ``from_header`` (added header) and ``from_email`` (email address of FROM) correctly if you enable SMTP headers variable. + +.. code-block:: yaml + + smtp_masquerade: false + +SMTP masquerade allows to replace the FROM statement to the value of ``smtp_username``. + +.. code-block:: yaml + + additional_lists: [] + +List of additional sources lists you want to add to unattended-upgrades. + +Dependencies +------------ + +None. + +Example Playbook +---------------- + +.. code-block:: yaml + + - name: Deploy automatic upgrades + hosts: all + become: true + vars: + smtp_username: user@domain.com + smtp_password: pa$$word + roles: + - role: 'unattended-upgrades' + +License +------- + +BSD-3 + +Author Information +------------------ + +Role created by `syrell `_. diff --git a/roles/unattended-upgrades/defaults/main.yml b/roles/unattended-upgrades/defaults/main.yml new file mode 100644 index 0000000..6ed5f60 --- /dev/null +++ b/roles/unattended-upgrades/defaults/main.yml @@ -0,0 +1,16 @@ +--- +# defaults file for unattended-upgrades + +upgrades_sender: "{{ ansible_user }}@{{ ansible_hostname }}.lan" +postfix_hostname: "{{ ansible_hostname }}.lan" +smtp_username: +smtp_password: +smtp_port: 587 +relay_servername: "{{ smtp_username | regex_search('(?<=@)(.+)\\.[\\w]+$') }}" + +custom_smtp_header: false +from_header: +from_email: +smtp_masquerade: false + +additional_lists: [] \ No newline at end of file diff --git a/roles/unattended-upgrades/handlers/main.yml b/roles/unattended-upgrades/handlers/main.yml new file mode 100644 index 0000000..fa339a2 --- /dev/null +++ b/roles/unattended-upgrades/handlers/main.yml @@ -0,0 +1,14 @@ +--- +# handlers file for unattended-upgrades + +- name: restart_postfix + service: + name: postfix + state: restarted + become: yes + +- name: restart_unattended-upgrades + service: + name: unattended-upgrades + state: restarted + become: yes diff --git a/roles/unattended-upgrades/meta/main.yml b/roles/unattended-upgrades/meta/main.yml new file mode 100644 index 0000000..c572acc --- /dev/null +++ b/roles/unattended-upgrades/meta/main.yml @@ -0,0 +1,52 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.1 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/roles/unattended-upgrades/tasks/main.yml b/roles/unattended-upgrades/tasks/main.yml new file mode 100644 index 0000000..3b9684d --- /dev/null +++ b/roles/unattended-upgrades/tasks/main.yml @@ -0,0 +1,12 @@ +--- +# tasks file for unattended-upgrades + +- name: Check if Postfix is already configured + stat: + path: /etc/postfix/sasl_passwd.db + register: postfix_configured + +- import_tasks: postfix.yml + when: postfix_configured.stat.exists == false + +- import_tasks: unattended-upgrades.yml diff --git a/roles/unattended-upgrades/tasks/postfix.yml b/roles/unattended-upgrades/tasks/postfix.yml new file mode 100644 index 0000000..207324e --- /dev/null +++ b/roles/unattended-upgrades/tasks/postfix.yml @@ -0,0 +1,55 @@ +- name: Install postfix and mail client + apt: + update_cache: true + pkg: + - bsd-mailx + - postfix + - libsasl2-modules + +- name: Insert postfix main configuration + template: + src: main.cf.j2 + dest: /etc/postfix/main.cf + backup: true + notify: restart_postfix + +- name: Setup credentials + template: + src: mail_credentials.j2 + dest: /etc/postfix/sasl_passwd + mode: 0600 + +- name: Generate sasl.db file + command: postmap /etc/postfix/sasl_passwd + +- name: Delete credentials file + file: + name: /etc/postfix/sasl_passwd + state: absent + +- name: SMTP header tasks + block: + - name: Add custom from header configuration + template: + src: mail_headers.j2 + dest: /etc/postfix/smtp_header_checks + mode: 0600 + backup: true + + - name: Add postfix-pcre package + apt: + name: postfix-pcre + when: custom_smtp_header + +- name: SMTP masquerade tasks + block: + - name: Add SMTP masquerade file + template: + src: mail_generic.j2 + dest: /etc/postfix/generic + mode: 0600 + backup: true + + - name: Generate generic.db file + command: postmap /etc/postfix/generic + when: smtp_masquerade diff --git a/roles/unattended-upgrades/tasks/unattended-upgrades.yml b/roles/unattended-upgrades/tasks/unattended-upgrades.yml new file mode 100644 index 0000000..2a1d98a --- /dev/null +++ b/roles/unattended-upgrades/tasks/unattended-upgrades.yml @@ -0,0 +1,25 @@ +- name: Install unattended-upgrades package + apt: + name: unattended-upgrades + state: present + +- name: Setup unattended-upgrades config + template: + src: unattended-upgrades.j2 + dest: /etc/apt/apt.conf.d/52unattended-upgrades + backup: true + notify: restart_unattended-upgrades + +- name: Setup reboot notifier script + template: + src: reboot_alert.sh.j2 + dest: /usr/local/sbin/reboot_alert.sh + backup: true + mode: +x + +- name: Setup cron to launch notifier script + cron: + name: "alert if reboot is required" + minute: "0" + hour: "8" + job: "/usr/local/sbin/reboot_alert.sh" diff --git a/roles/unattended-upgrades/templates/mail_credentials.j2 b/roles/unattended-upgrades/templates/mail_credentials.j2 new file mode 100644 index 0000000..a2169dc --- /dev/null +++ b/roles/unattended-upgrades/templates/mail_credentials.j2 @@ -0,0 +1 @@ +[{{ relay_servername }}]:{{ smtp_port }} {{ smtp_username }}:{{ smtp_password }} \ No newline at end of file diff --git a/roles/unattended-upgrades/templates/mail_generic.j2 b/roles/unattended-upgrades/templates/mail_generic.j2 new file mode 100644 index 0000000..859a6c5 --- /dev/null +++ b/roles/unattended-upgrades/templates/mail_generic.j2 @@ -0,0 +1 @@ +{{ upgrades_sender }} {{ smtp_username }} \ No newline at end of file diff --git a/roles/unattended-upgrades/templates/mail_headers.j2 b/roles/unattended-upgrades/templates/mail_headers.j2 new file mode 100644 index 0000000..b8460e4 --- /dev/null +++ b/roles/unattended-upgrades/templates/mail_headers.j2 @@ -0,0 +1 @@ +/^From:.*/ REPLACE From: {{ from_header }} <{{ from_email }}> \ No newline at end of file diff --git a/roles/unattended-upgrades/templates/main.cf.j2 b/roles/unattended-upgrades/templates/main.cf.j2 new file mode 100644 index 0000000..08386bf --- /dev/null +++ b/roles/unattended-upgrades/templates/main.cf.j2 @@ -0,0 +1,29 @@ +myhostname={{ postfix_hostname }} + +smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) +biff = no + +# appending .domain is the MUA's job. +append_dot_mydomain = no + +alias_maps = hash:/etc/aliases +alias_database = hash:/etc/aliases +{% if custom_smtp_header %}smtp_header_checks = pcre:/etc/postfix/smtp_header_checks +{% endif %} +{% if smtp_masquerade %}smtp_generic_maps = hash:/etc/postfix/generic +{% endif %} + +relayhost = [{{ relay_servername }}]:{{ smtp_port }} +smtp_use_tls = yes +smtp_sasl_auth_enable = yes +smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd +smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt +smtp_sasl_security_options = noanonymous, noplaintext +smtp_sasl_tls_security_options = noanonymous +smtp_tls_security_level = encrypt + +mynetworks = 127.0.0.0/8 +inet_interfaces = loopback-only +recipient_delimiter = + + +compatibility_level = 2 diff --git a/roles/unattended-upgrades/templates/reboot_alert.sh.j2 b/roles/unattended-upgrades/templates/reboot_alert.sh.j2 new file mode 100644 index 0000000..dee1208 --- /dev/null +++ b/roles/unattended-upgrades/templates/reboot_alert.sh.j2 @@ -0,0 +1,5 @@ +#!/bin/bash + +if [ -f /var/run/reboot-required ]; then + echo "A reboot is required following updates to server `hostname -f` for packages: \n \n $(cat /var/run/reboot-required.pkgs)" | mail -s "Reboot Required" {{ smtp_username }} +fi diff --git a/roles/unattended-upgrades/templates/unattended-upgrades.j2 b/roles/unattended-upgrades/templates/unattended-upgrades.j2 new file mode 100644 index 0000000..dd60a16 --- /dev/null +++ b/roles/unattended-upgrades/templates/unattended-upgrades.j2 @@ -0,0 +1,23 @@ +Unattended-Upgrade::Origins-Pattern { + "origin=Debian,codename=${distro_codename}-updates"; + "origin=Debian,codename=${distro_codename},label=Debian"; + "origin=Debian,codename=${distro_codename},label=Debian-Security"; + "origin=Debian,codename=${distro_codename}-security,label=Debian-Security"; +{% for list in additional_lists %} + "{{ list }}"; +{% endfor %} +}; + +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; +APT::Periodic::Download-Upgradeable-Packages "1"; +APT::Periodic::AutocleanInterval "7"; +APT::Periodic::Verbose "2"; + +Unattended-Upgrade::Mail "{{ smtp_username }}"; +Unattended-Upgrade::Sender "{{ upgrades_sender }}"; +Unattended-Upgrade::MailReport "on-change"; + +Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"; +Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; +Unattended-Upgrade::Remove-Unused-Dependencies "false"; diff --git a/roles/unattended-upgrades/vars/main.yml b/roles/unattended-upgrades/vars/main.yml new file mode 100644 index 0000000..9e0153e --- /dev/null +++ b/roles/unattended-upgrades/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for system_updates