Compare commits

..

6 commits

11 changed files with 310 additions and 74 deletions

View file

@ -13,8 +13,13 @@ The **patch** part is incremented if multiple releases happen the same month
### Added
* apt: add list-upgradable-held-packages.sh
### Changed
* evobackup-client: upstream release 24.05
* evolinux-base: improve adding the current user to SSH AllowGroups of AllowUsers
### Fixed
### Removed
@ -25,7 +30,7 @@ The **patch** part is incremented if multiple releases happen the same month
### Added
proftpd: optional configuration of IP whitelists per groups of users
* proftpd: optional configuration of IP whitelists per groups of users
### Changed

View file

@ -29,4 +29,7 @@ apt_check_hold_cron_weekday: "*"
apt_check_hold_cron_day: "*"
apt_check_hold_cron_month: "*"
apt_list_upgradable_held_enabled: False
apt_list_upgradable_held_special_time: "weekly"
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"

View file

@ -0,0 +1,127 @@
#!/bin/bash
#####
# This script will send an email if some packages are on hold
# but have available updates.
#####
readonly VERSION="24.05"
# set all programs to C language (english)
export LC_ALL=C
# If expansion is attempted on an unset variable or parameter, the shell prints an
# error message, and, if not interactive, exits with a non-zero status.
set -o nounset
# The pipeline's return status is the value of the last (rightmost) command
# to exit with a non-zero status, or zero if all commands exit successfully.
set -o pipefail
# Enable trace mode if called with environment variable TRACE=1
if [[ "${TRACE-0}" == "1" ]]; then
set -o xtrace
fi
# shellcheck disable=SC2155
readonly PROGPATH=$(readlink -m "${0}")
# readonly PROGNAME=$(basename "${PROGPATH}")
# # shellcheck disable=SC2124
# readonly ARGS=$@
# Fetch values from evomaintenance configuration
get_evomaintenance_mail() {
grep "EVOMAINTMAIL=" /etc/evomaintenance.cf | cut -d '=' -f2
}
get_fqdn() {
hostname --fqdn
}
get_complete_hostname() {
REAL_HOSTNAME="$(get_fqdn)"
if [ "${HOSTNAME}" = "${REAL_HOSTNAME}" ]; then
echo "${HOSTNAME}"
else
echo "${HOSTNAME} (${REAL_HOSTNAME})"
fi
}
format_mail() {
cat <<EOTEMPLATE
From: Evolix <${EMAIL_FROM}>
Content-Type: text/plain; charset=UTF-8
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-Script: ${PROGPATH}
X-Script-Version: ${VERSION}
To: ${EMAIL_CLIENT:-alert5@evolix.fr}
Subject: Mise a jour manuelle disponible
Bonjour,
Un ou plusieurs paquets dont la mise à jour automatique a été
explicitement bloquée ont une nouvelle version disponible.
Nom du serveur :
${HOSTNAME_TEXT}
Liste des paquets :
${upgradable_held_packages}
Pour que nous appliquions ces mises à jour vous devez
nous contacter explicitement, de préférence par ticket,
en mentionnant le serveur et les paquets concernés,
ainsi que les modalités de mise à jour (créneau horaire,
procédure technique…).
Cordialement
--
Evolix
EOTEMPLATE
}
main() {
held_packages=$(apt-mark showhold)
upgradable_packages=$(apt list --upgradable 2> /dev/null)
if [ -z "${held_packages}" ]; then
# No packages are on hold
exit 0
elif [ -z "${upgradable_packages}" ]; then
# No packages are upgradable
exit 0
fi
kept_back_output=$(LC_ALL=C apt-get upgrade --dry-run | grep -A 1 'The following packages have been kept back:')
if [ -z "${kept_back_output}" ]; then
# No packages are kept back
exit 0
fi
upgradable_held_packages=$(apt list --upgradable 2> /dev/null | grep -f <(echo "${kept_back_output}" | tail -1 | tr ' ' '\n' | sed -e '/^$/d'))
if [ -z "${upgradable_held_packages}" ]; then
# No held packages are upgradable
exit 0
fi
HOSTNAME="$(get_fqdn)"
HOSTNAME_TEXT="$(get_complete_hostname)"
EMAIL_CLIENT="$(get_evomaintenance_mail)"
EMAIL_FROM="equipe@evolix.fr"
MAIL_CONTENT="$(format_mail)"
SENDMAIL_BIN="$(command -v sendmail)"
if [ -z "${SENDMAIL_BIN}" ]; then
>&2 echo "ERROR: No \`sendmail' command has been found, can't send mail."
exit 1
fi
if [ ! -x "${SENDMAIL_BIN}" ]; then
>&2 echo "ERROR: \`${SENDMAIL_BIN}' is not executable, can't send mail."
exit 1
fi
echo "${MAIL_CONTENT}" | "${SENDMAIL_BIN}" -oi -t -f "equipe@evolix.fr"
exit 0
}
main

View file

@ -76,7 +76,16 @@
tags:
- apt
- name: Check if Cron is installed
- name: List scripts is installed
ansible.builtin.copy:
src: list-upgradable-held-packages.sh
dest: /usr/share/scripts/list-upgradable-held-packages.sh
force: true
mode: "0755"
tags:
- apt
- name: Check if cron is installed
ansible.builtin.shell:
cmd: "dpkg --list 'cron' 2>/dev/null | grep -q -E '^(i|h)i'"
register: is_cron
@ -101,3 +110,15 @@
tags:
- apt
when: is_cron.rc == 0
- name: List upgradable held packages (script)
ansible.builtin.cron:
cron_file: apt-hold-packages
name: list-upgradable-held-packages
job: "/usr/share/scripts/list-upgradable-held-packages.sh"
user: root
special_time: "{{ apt_list_upgradable_held_special_time | mandatory }}"
state: "{{ apt_list_upgradable_held_enabled | bool | ternary('present', 'absent') }}"
tags:
- apt
when: is_cron.rc == 0

View file

@ -23,13 +23,23 @@ The **patch** part changes is incremented if multiple releases happen the same m
### Security
## [24.04.1]
## [24.05] - 2022-05-02
### Added
* evobackupctl: update LIBDIR when copying the template
### Changed
* evobackupctl: simplify the program path retrieval
## [24.04.1] - 2022-04-30
### Fixed
* evobackupctl: quote ARGS variable for options parsing.
## [24.04]
## [24.04] - 2022-04-29
### Added
@ -52,7 +62,7 @@ The **patch** part changes is incremented if multiple releases happen the same m
* don't exit the whole program if a sync task can't be done
## [22.12]
## [22.12] - 2022-12-27
### Changed
@ -77,6 +87,6 @@ The **patch** part changes is incremented if multiple releases happen the same m
* Make start_time and stop_time compatible with OpenBSD
## [22.03]
## [22.03] - 2022-04-03
Split client and server parts of the project

View file

@ -1,9 +1,8 @@
#!/usr/bin/env bash
# shellcheck disable=SC2155
readonly PROGNAME=$(basename "${0}")
# shellcheck disable=SC2155
readonly PROGDIR=$(readlink -m "$(dirname "${0}")")
readonly PROGPATH=$(readlink -m "${0}")
readonly PROGNAME=$(basename "${PROGPATH}")
# shellcheck disable=SC2124
readonly ARGS=$@
@ -78,10 +77,14 @@ copy_template() {
if cp "${LIBDIR}/zzz_evobackup.sh" "${dest_path}"; then
chmod 750 "${dest_path}"
sed -i "s|@COMMAND@|${PROGDIR}/${PROGNAME} ${ARGS}|" "${dest_path}"
# Insert metadata about the template
sed -i "s|@COMMAND@|${PROGPATH} ${ARGS}|" "${dest_path}"
sed -i "s|@DATE@|$(date --iso-8601=seconds)|" "${dest_path}"
sed -i "s|@VERSION@|${VERSION}|" "${dest_path}"
# Make sure that the library directory is correct
sed -i "s|^LIBDIR=.\+|LIBDIR=\"${LIBDIR}\"|" "${dest_path}"
printf "New evobackup script has been saved to '%s'.\n" "${dest_path}"
printf "Remember to customize it (mail notifications, backup servers…).\n"
exit 0

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034,SC2317
readonly VERSION="24.04.1"
readonly VERSION="24.05"
# set all programs to C language (english)
export LC_ALL=C

View file

@ -10,7 +10,7 @@
- name: "Remount /usr if needed"
include_role:
name: remount-usr
when: evobackup_client__lib_dir is search("/usr") or evobackup_client__bin_dir is search("/usr")
when: evobackup_client__lib_dir is search("/usr") or evobackup_client__bin_dir is search("/usr")
- name: copy evobackup libs
ansible.builtin.copy:

View file

@ -37,6 +37,6 @@ Main variables are:
* `evolinux_postfix_purge_exim`: purge Exim packages (default: `True`) ;
* `evolinux_ssh_password_auth_addresses`: list of addresses that can authenticate with a password (default: `[]`)
* `evolinux_ssh_disable_root`: disable SSH access for root (default: `False`)
* `evolinux_ssh_allow_current_user`: don't lock yourself out (default: `False`)
* `evolinux_ssh_allow_current_user`: don't lock yourself out is there is an AllowUsers or AllowGroups directive (default: `False`)
The full list of variables (with default values) can be found in `defaults/main.yml`.

View file

@ -16,34 +16,75 @@
dest: /etc/ssh/sshd_config.d/z-evolinux-defaults.conf
mode: "0644"
- name: "Get current user's group"
ansible.builtin.command:
cmd: logname
changed_when: False
register: logname
check_mode: no
when: evolinux_ssh_allow_current_user | bool
# Should we allow the current user?
- name: Allow the current user
block:
- name: "Get current user's login"
ansible.builtin.command:
cmd: logname
changed_when: False
register: _logname
check_mode: no
- name: verify AllowUsers directive
ansible.builtin.command:
cmd: "grep -ER '^AllowUsers' /etc/ssh"
failed_when: False
changed_when: False
register: grep_allowusers_ssh
check_mode: no
when: evolinux_ssh_allow_current_user | bool
- name: verify AllowUsers directive
ansible.builtin.command:
cmd: "grep --extended-regexp --dereference-recursive --files-with-matches '^AllowUsers' /etc/ssh/sshd_config /etc/ssh/sshd_config.d"
failed_when: False
changed_when: False
register: grep_allowusers_ssh
check_mode: no
- name: "Add AllowUsers sshd directive for current user"
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config.d/allow_evolinux_user.conf
create: yes
line: "AllowUsers {{ logname.stdout }}"
insertafter: 'Subsystem'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when: evolinux_ssh_allow_current_user and grep_allowusers_ssh.rc != 0
- name: verify AllowGroups directive
ansible.builtin.command:
cmd: "grep --extended-regexp --dereference-recursive --files-with-matches '^AllowGroups' /etc/ssh/sshd_config /etc/ssh/sshd_config.d"
failed_when: False
changed_when: False
register: grep_allowgroups_ssh
check_mode: no
# If we have AllowUsers but not AllowGroups, append the user to the list
# (in the first file where we found the directive)
- name: "Append user to existing AllowUsers sshd directive"
ansible.builtin.replace:
dest: "{{ grep_allowusers_ssh.stdout_lines[0] }}"
regexp: '^(AllowUsers ((?!{{ _logname.stdout }}).)*)$'
replace: '\1 {{ _logname.stdout }}'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_allowusers_ssh.rc == 0
- grep_allowgroups_ssh.rc != 0
# If we have AllowGroups but not AllowUsers, add the user to the group and append the group to the list
# (in the first file where we found the directive)
- name: "Append evolinux ssh group to AllowGroups sshd directive"
ansible.builtin.replace:
dest: "{{ grep_allowgroups_ssh.stdout_lines[0] }}"
regexp: '^(AllowGroups ((?!{{ evolinux_ssh_group }}).)*)$'
replace: '\1 {{ evolinux_ssh_group }}'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_allowusers_ssh.rc != 0
- grep_allowgroups_ssh.rc == 0
- name: "evolinux ssh group is present"
ansible.builtin.group:
name: "{{ evolinux_ssh_group }}"
when:
- grep_allowusers_ssh.rc != 0
- grep_allowgroups_ssh.rc == 0
- name: "Add current user to evolinux ssh group"
ansible.builtin.user:
name: "{{ _logname.stdout }}"
group: "{{ evolinux_ssh_group }}"
append: yes
when:
- grep_allowusers_ssh.rc != 0
- grep_allowgroups_ssh.rc == 0
when: evolinux_ssh_allow_current_user | bool
- ansible.builtin.meta: flush_handlers
# TODO si allowusers et allowgroups, ajouter utilisateur aux deux
# TODO si allowgroups, ajouter groupe de lutilisateur

View file

@ -61,40 +61,66 @@
notify: reload sshd
when: ansible_distribution_major_version is version('9', '>=')
- name: "Get current user"
ansible.builtin.command:
cmd: logname
changed_when: False
register: logname
check_mode: no
# Should we allow the current user?
- name: Allow the current user
block:
- name: "Get current user"
ansible.builtin.command:
cmd: logname
changed_when: False
register: _logname
check_mode: no
- name: verify AllowUsers directive
ansible.builtin.command:
cmd: "grep -E '^AllowUsers' /etc/ssh/sshd_config"
failed_when: False
changed_when: False
register: grep_allowusers_ssh
check_mode: no
- name: verify AllowGroups directive
ansible.builtin.command:
cmd: "grep -E '^AllowGroups' /etc/ssh/sshd_config"
failed_when: False
changed_when: False
register: grep_allowgroups_ssh
check_mode: no
# If we have AllowUsers but not AllowGroups, append the user to the list
- name: "Modify AllowUsers sshd directive for current user"
ansible.builtin.replace:
dest: /etc/ssh/sshd_config
regexp: '^(AllowUsers ((?!{{ _logname.stdout }}).)*)$'
replace: '\1 {{ _logname.stdout }}'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_allowusers_ssh.rc == 0
- grep_allowgroups_ssh.rc != 0
# If we have AllowGroups but not AllowUsers, add the user to the group and append the group to the list
- name: "Add current user to {{ evolinux_ssh_group }} group"
ansible.builtin.user:
name: "{{ _logname.stdout }}"
group: "{{ evolinux_ssh_group }}"
append: yes
when:
- grep_allowusers_ssh.rc != 0
- grep_allowgroups_ssh.rc == 0
- name: "Append '{{ evolinux_ssh_group }}' to AllowGroups sshd directive"
ansible.builtin.replace:
dest: "/etc/ssh/sshd_config"
regexp: '^(AllowGroups ((?!{{ evolinux_ssh_group }}).)*)$'
replace: '\1 {{ evolinux_ssh_group }}'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_allowusers_ssh.rc != 0
- grep_allowgroups_ssh.rc == 0
when: evolinux_ssh_allow_current_user | bool
# we must double-escape caracters, because python
- name: verify AllowUsers directive
ansible.builtin.command:
cmd: "grep -E '^AllowUsers' /etc/ssh/sshd_config"
failed_when: False
changed_when: False
register: grep_allowusers_ssh
check_mode: no
when: evolinux_ssh_allow_current_user | bool
- name: "Add AllowUsers sshd directive for current user"
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
line: "\nAllowUsers {{ logname.stdout }}"
insertafter: 'Subsystem'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when: evolinux_ssh_allow_current_user and grep_allowusers_ssh.rc != 0
- name: "Modify AllowUsers sshd directive for current user"
ansible.builtin.replace:
dest: /etc/ssh/sshd_config
regexp: '^(AllowUsers ((?!{{ logname.stdout }}).)*)$'
replace: '\1 {{ logname.stdout }}'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when: evolinux_ssh_allow_current_user and grep_allowusers_ssh.rc == 0
- ansible.builtin.meta: flush_handlers