Compare commits

..

18 commits

Author SHA1 Message Date
William Hirigoyen 6dbe21b04c Petite amélioration d'UI pour la commande monitoringctl show (ne pas afficher la liste si n=1)
All checks were successful
Ansible Lint |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |2723|0|2723|0|:zzz:
gitea/ansible-roles/pipeline/head This commit looks good
2024-05-07 12:17:10 +02:00
William Hirigoyen 0be5f409aa Fixes
All checks were successful
Ansible Lint |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |2721|0|2721|0|:zzz:
gitea/ansible-roles/pipeline/head This commit looks good
2024-05-03 18:08:27 +02:00
William Hirigoyen 064ca2f20a mini fixes
All checks were successful
Ansible Lint |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |2722|0|2722|0|:zzz:
gitea/ansible-roles/pipeline/head This commit looks good
2024-05-03 10:10:34 +02:00
William Hirigoyen 6f52920f9e Split wrapper.yml, déplacement sbin -> bin, min mini-fixes
All checks were successful
Ansible Lint |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |2722|0|2722|0|:zzz:
gitea/ansible-roles/pipeline/head This commit looks good
2024-05-03 10:08:21 +02:00
William Hirigoyen b3751c3f70 Variables privées dans common + optim lecture conf NRPE 2024-05-03 10:08:21 +02:00
William Hirigoyen 5b460bf65b Version sant trop de bugs :) Gère si les noms des wrappers sont différents des checks, multiples, ou autres cas bizarres 2024-05-03 10:08:21 +02:00
William Hirigoyen 290e3de047 Améliorations diverses UI, message de désactivation dans alerts_wrapper, couleurs... 2024-05-03 10:08:21 +02:00
William Hirigoyen 056b1c4c0f Implémentation check all et couleurs dans les sorties de check et de status 2024-05-03 10:08:21 +02:00
William Hirigoyen 4f77466630 tmp 2024-05-03 10:08:21 +02:00
William Hirigoyen 5f03bf99d0 Commit 2024-05-03 10:08:21 +02:00
William Hirigoyen 5a1f13373a debug, amélioration complétion 2024-05-03 10:08:21 +02:00
William Hirigoyen 7edd8ac5b8 Fin de créneau (code non utilisable) 2024-05-03 10:08:21 +02:00
William Hirigoyen 8230fbbbc5 Timeout dans le fichier d'alerts_wrapper 2024-05-03 10:08:21 +02:00
William Hirigoyen 78d2c182f2 commit tmp (alerts_wrapper) 2024-05-03 10:08:21 +02:00
William Hirigoyen 4755620a9d Suite implémentation 2024-05-03 10:08:21 +02:00
William Hirigoyen 550821e57f check-local: passage à monitoringctl, amélioration lecture récursive conf, lecture port et adresse dans la conf, début d'implémentation des actions 2024-05-03 10:08:21 +02:00
William Hirigoyen 0fa7877d62 Implémentation raw de la recherche récursive d'une commande rnpe dans sa conf 2024-05-03 10:08:21 +02:00
William Hirigoyen 13aab31131 WIP parse NRPE conf 2024-05-03 10:08:21 +02:00
34 changed files with 1477 additions and 747 deletions

View file

@ -13,32 +13,18 @@ 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
### Fixed
### Removed
### Security
## [24.05] 2024-05-15
### Added
* apt: add list-upgradable-held-packages.sh
### Changed
* evobackup-client: upstream release 24.05.1
* evolinux-base: improve adding the current user to SSH AllowGroups of AllowUsers
* evolinux-users: improve SSH configuration
* evomaintenance: upstream release 24.05
* evomaintenance: move upstream files into upstream folder
### Fixed
* apt: use archive.debian.org with Buster
## [24.04] 2024-04-30
### Added

View file

@ -5,8 +5,6 @@
# but have available updates.
#####
readonly VERSION="24.05"
# set all programs to C language (english)
export LC_ALL=C
@ -50,7 +48,6 @@ 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

View file

@ -1,3 +1,3 @@
# {{ ansible_managed }}
deb http://archive.debian.org/debian buster-backports {{ apt_backports_components | mandatory }}
deb http://mirror.evolix.org/debian buster-backports {{ apt_backports_components | mandatory }}

View file

@ -1,4 +1,5 @@
# {{ ansible_managed }}
deb http://archive.debian.org/debian buster {{ apt_basics_components | mandatory }}
deb http://mirror.evolix.org/debian buster {{ apt_basics_components | mandatory }}
deb http://mirror.evolix.org/debian buster-updates {{ apt_basics_components | mandatory }}
deb http://security.debian.org/debian-security buster/updates {{ apt_basics_components | mandatory }}

View file

@ -23,12 +23,6 @@ The **patch** part changes is incremented if multiple releases happen the same m
### Security
## [24.05.1] - 2022-05-14
### Fixed
* client: fix shell syntax error
## [24.05] - 2022-05-02
### Added

View file

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

View file

@ -105,7 +105,7 @@ test_server() {
pick_server() {
local -i increment=${1:-0}
local -i list_length=${#SERVERS[@]}
local sync_name=${2:-""}
local sync_name=${2:""}
if (( increment >= list_length )); then
# We've reached the end of the list

View file

@ -14,7 +14,7 @@
- name: copy evobackup libs
ansible.builtin.copy:
src: upstream/lib/
src: upstream/lib
dest: "{{ evobackup_client__lib_dir }}/"
force: True
mode: "0644"

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 is there is an AllowUsers or AllowGroups directive (default: `False`)
* `evolinux_ssh_allow_current_user`: don't lock yourself out (default: `False`)
The full list of variables (with default values) can be found in `defaults/main.yml`.

View file

@ -16,78 +16,34 @@
dest: /etc/ssh/sshd_config.d/z-evolinux-defaults.conf
mode: "0644"
# 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 --extended-regexp --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: verify AllowGroups directive
ansible.builtin.command:
cmd: "grep --extended-regexp --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
# If we don't have AllowGroups nor AllowUsers, do nothing
- 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
- 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: "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
- ansible.builtin.meta: flush_handlers
# TODO si allowusers et allowgroups, ajouter utilisateur aux deux
# TODO si allowgroups, ajouter groupe de lutilisateur

View file

@ -61,66 +61,40 @@
notify: reload sshd
when: ansible_distribution_major_version is version('9', '>=')
# 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
- name: "Get current user"
ansible.builtin.command:
cmd: logname
changed_when: False
register: logname
check_mode: no
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

View file

@ -1,23 +1,8 @@
---
- name: Fetch SSHd config files
ansible.builtin.command:
cmd: "find /etc/ssh -type f \\( -name 'sshd_config' -o -path '/etc/ssh/sshd_config.d/*.conf' \\)"
changed_when: False
check_mode: no
register: _ssh_config_paths
- ansible.builtin.debug:
var: _ssh_config_paths
verbosity: 1
############################
# AllowUsers or AllowGroups
############################
- name: verify AllowGroups directive
ansible.builtin.command:
cmd: "grep --extended-regexp --recursive --files-with-matches '^AllowGroups' {{ _ssh_config_paths.stdout_lines | join(' ') }}"
cmd: "grep -Er '^AllowGroups' /etc/ssh"
changed_when: False
failed_when: False
check_mode: no
@ -29,7 +14,7 @@
- name: verify AllowUsers directive
ansible.builtin.command:
cmd: "grep --extended-regexp --recursive --files-with-matches '^AllowUsers' {{ _ssh_config_paths.stdout_lines | join(' ') }}"
cmd: "grep -Er '^AllowUsers' /etc/ssh"
changed_when: False
failed_when: False
check_mode: no
@ -57,14 +42,12 @@
var: ssh_allowusers
verbosity: 1
- name: Configure SSH in AllowGroups mode
ansible.builtin.include: ssh_allowgroups.yml
- ansible.builtin.include: ssh_allowgroups.yml
when:
- ssh_allowgroups
- not ssh_allowusers
- name: Configure SSH in AllowUsers mode
ansible.builtin.include: ssh_allowusers.yml
- ansible.builtin.include: ssh_allowusers.yml
vars:
user: "{{ item.value }}"
loop: "{{ evolinux_users | dict2items }}"
@ -73,24 +56,7 @@
- ssh_allowusers
- not ssh_allowgroups
# Do this again, to update the value
- name: Fetch SSHd config files
ansible.builtin.command:
cmd: "find /etc/ssh -type f \\( -name 'sshd_config' -o -path '/etc/ssh/sshd_config.d/*.conf' \\)"
changed_when: False
check_mode: no
register: _ssh_config_paths
##################
# PermitRootLogin
##################
### For Debian < 12
# if there is a commented value for PermitRootLogin
# we replace it with a "no"
- name: Root login is disabled (Debian < 12)
- name: disable root login
ansible.builtin.replace:
dest: /etc/ssh/sshd_config
regexp: '^#PermitRootLogin (yes|without-password|prohibit-password)'
@ -98,15 +64,11 @@
notify: reload sshd
when:
- evolinux_root_disable_ssh | bool
- ansible_distribution_major_version is version('12', '<')
### For Debian >= 12
# if there is no value for PermitRootLogin (anywhere)
# we add a "no" in z-evolinux-users.conf
- ansible_distribution_major_version is version('11', '<=')
- name: verify PermitRootLogin directive (Debian >= 12)
ansible.builtin.command:
cmd: "grep --extended-regexp --recursive --files-with-matches '^PermitRootLogin' {{ _ssh_config_paths.stdout_lines | join(' ') }}"
cmd: "grep -Er '^PermitRootLogin' /etc/ssh"
changed_when: False
failed_when: False
check_mode: no
@ -114,7 +76,12 @@
when:
- ansible_distribution_major_version is version('12', '>=')
- name: Root login is disabled (Debian >= 12)
# TODO avertir lorsque PermitRootLogin est déjà configuré?
- ansible.builtin.debug:
var: grep_permitrootlogin_ssh
verbosity: 1
- name: disable root login (Debian >= 12)
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config.d/z-evolinux-users.conf
line: "PermitRootLogin no"
@ -126,48 +93,6 @@
when:
- evolinux_root_disable_ssh | bool
- ansible_distribution_major_version is version('12', '>=')
- grep_permitrootlogin_ssh.rc != 0
#####################
# Allow current user
#####################
- name: Allow current user
block:
- name: Check if evolinux ssh group is used
ansible.builtin.command:
cmd: "grep --extended-regexp --recursive --files-with-matches '^AllowGroups.+{{ evolinux_ssh_group }}' {{ _ssh_config_paths.stdout_lines | join(' ') }}"
changed_when: False
failed_when: False
check_mode: no
register: grep_evolinux_group_ssh
- debug:
var: grep_evolinux_group_ssh
- name: "Get current user's login"
ansible.builtin.command:
cmd: logname
changed_when: False
register: _logname
check_mode: no
- debug:
var: evolinux_ssh_group
- debug:
var: evolinux_ssh_allow_current_user
- name: "Add current user ({{ _logname.stdout }}) to {{ evolinux_ssh_group }} group"
ansible.builtin.user:
name: "{{ _logname.stdout }}"
groups: "{{ evolinux_ssh_group }}"
append: yes
when:
- grep_evolinux_group_ssh.rc == 0
when:
- evolinux_ssh_group is defined
- evolinux_ssh_group | length > 0
- evolinux_ssh_allow_current_user | bool
- grep_permitrootlogin_ssh.rc == 1
- ansible.builtin.meta: flush_handlers

View file

@ -1,27 +1,18 @@
---
###
# this check must be repeated for each user
# even if it's been done before
- name: Fetch SSHd config files
ansible.builtin.command:
cmd: "find /etc/ssh -type f \\( -name 'sshd_config' -o -path '/etc/ssh/sshd_config.d/*.conf' \\)"
changed_when: False
check_mode: no
register: _ssh_config_paths
- name: verify AllowGroups directive
ansible.builtin.command:
cmd: "grep --extended-regexp --recursive --files-with-matches '^AllowGroups' {{ _ssh_config_paths.stdout_lines | join(' ') }}"
cmd: "grep -Er '^AllowGroups' /etc/ssh"
changed_when: False
failed_when: False
check_mode: no
register: grep_allowgroups_ssh
when:
- ansible_distribution_major_version is version('11', '<=')
###
- name: "Add AllowGroups sshd directive with '{{ evolinux_ssh_group }}' (Debian < 12)"
- name: "Add AllowGroups sshd directive with '{{ evolinux_ssh_group }}'"
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
line: "\nAllowGroups {{ evolinux_ssh_group }}"
@ -30,25 +21,25 @@
notify: reload sshd
when:
- ansible_distribution_major_version is version('11', '<=')
- grep_allowgroups_ssh.rc == 1 # Not found
- name: "Add AllowGroups sshd directive with '{{ evolinux_ssh_group }}' (Debian >= 12)"
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config.d/z-evolinux-users.conf
line: "\nAllowGroups {{ evolinux_ssh_group }}"
validate: '/usr/sbin/sshd -t -f %s'
create: yes
notify: reload sshd
when:
- ansible_distribution_major_version is version('12', '>=')
- grep_allowgroups_ssh.rc == 1 # Not found
- grep_allowgroups_ssh.rc != 0
- name: "Append '{{ evolinux_ssh_group }}' to AllowGroups sshd directive"
ansible.builtin.replace:
dest: "{{ grep_allowgroups_ssh.stdout_lines[0] }}"
dest: /etc/ssh/sshd_config
regexp: '^(AllowGroups ((?!\b{{ evolinux_ssh_group }}\b).)*)$'
replace: '\1 {{ evolinux_ssh_group }}'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_allowgroups_ssh.rc == 0 or grep_allowgroups_ssh.rc == 2 # Found, return code can be 0 or 2
- ansible_distribution_major_version is version('11', '<=')
- grep_allowgroups_ssh.rc == 0
- name: "Add AllowGroups sshd directive with '{{ evolinux_ssh_group }}'"
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config.d/z-evolinux-users.conf
line: "AllowGroups {{ evolinux_ssh_group }}"
create: yes
mode: "0644"
validate: '/usr/sbin/sshd -t -f %s'
when:
- ansible_distribution_major_version is version('12', '>=')

View file

@ -1,84 +1,55 @@
---
###
# these checks must be repeated for each user
# this check must be repeated for each user
# even if it's been done before
- name: Fetch SSHd config files
- name: verify AllowUsers directive
ansible.builtin.command:
cmd: "find /etc/ssh -type f \\( -name 'sshd_config' -o -path '/etc/ssh/sshd_config.d/*.conf' \\)"
changed_when: False
check_mode: no
register: _ssh_config_paths
- name: Verify AllowUsers directive
ansible.builtin.command:
cmd: "grep --extended-regexp --recursive --files-with-matches '^AllowUsers' {{ _ssh_config_paths.stdout_lines | join(' ') }}"
cmd: "grep -E '^AllowUsers' /etc/ssh/sshd_config"
changed_when: False
failed_when: False
check_mode: no
register: grep_allowusers_ssh
###
- name: "Add AllowUsers sshd directive with '{{ user.name }}' (Debian < 12)"
- name: "Add AllowUsers sshd directive with '{{ user.name }}'"
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
line: "\nAllowUsers {{ user.name }}"
insertafter: 'Subsystem'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_allowusers_ssh.rc != 0
- ansible_distribution_major_version is version('12', '<')
- name: "Add AllowUsers sshd directive with '{{ user.name }}' (Debian >= 12)"
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config.d/z-evolinux-users.conf
line: "\nAllowUsers {{ user.name }}"
insertafter: 'Subsystem'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_allowusers_ssh.rc != 0
- ansible_distribution_major_version is version('12', '>=')
when: grep_allowusers_ssh.rc != 0
- name: "Append '{{ user.name }}' to AllowUsers sshd directive"
ansible.builtin.replace:
dest: "{{ grep_allowusers_ssh.stdout_lines[0] }}"
dest: /etc/ssh/sshd_config
regexp: '^(AllowUsers ((?!\b{{ user.name }}\b).)*)$'
replace: '\1 {{ user.name }}'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_allowusers_ssh.rc == 0
when: grep_allowusers_ssh.rc == 0
- name: "verify Match User directive"
ansible.builtin.command:
cmd: "grep --extended-regexp --recursive --files-with-matches '^Match User' {{ _ssh_config_paths.stdout_lines | join(' ') }}"
cmd: "grep -E '^Match User' /etc/ssh/sshd_config"
changed_when: False
failed_when: False
check_mode: no
register: grep_matchuser_ssh
- name: "Add Match User sshd directive with '{{ user.name }}' (Debian <= 10)"
- name: "Add Match User sshd directive with '{{ user.name }}'"
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
line: "\nMatch User {{ user.name }}\n PasswordAuthentication no"
insertafter: "# END EVOLINUX PASSWORD RESTRICTIONS BY ADDRESS"
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_matchuser_ssh.rc != 0
- ansible_distribution_major_version is version('10', '<=')
when: grep_matchuser_ssh.rc != 0
- name: "Append '{{ user.name }}' to Match User's sshd directive (Debian <= 10)"
- name: "Append '{{ user.name }}' to Match User's sshd directive"
ansible.builtin.replace:
dest: "{{ grep_matchuser_ssh.stdout_lines[0] }}"
dest: /etc/ssh/sshd_config
regexp: '^(Match User ((?!{{ user.name }}).)*)$'
replace: '\1,{{ user.name }}'
validate: '/usr/sbin/sshd -t -f %s'
notify: reload sshd
when:
- grep_matchuser_ssh.rc == 0
- ansible_distribution_major_version is version('10', '<=')
when: grep_matchuser_ssh.rc == 0

View file

@ -1,12 +1,12 @@
#!/bin/sh
VERSION="24.05"
VERSION="23.10.1"
show_version() {
cat <<END
evomaintenance version ${VERSION}
Copyright 2007-2024 Evolix <info@evolix.fr>,
Copyright 2007-2023 Evolix <info@evolix.fr>,
Gregory Colpart <reg@evolix.fr>,
Jérémy Lecour <jlecour@evolix.fr>,
Brice Waegeneire <bwaegeneire@evolix.fr>,
@ -437,14 +437,6 @@ while :; do
printf 'ERROR: "--message" requires a non-empty option argument.\n' >&2
exit 1
;;
--no-evocheck)
# disable evocheck hook
EVOCHECK=0
;;
--evocheck)
# enable evocheck hook
EVOCHECK=1
;;
--no-commit)
# disable commit hook
HOOK_COMMIT=0
@ -589,7 +581,7 @@ GIT_REPOSITORIES="/etc /etc/bind /usr/share/scripts"
# Add /etc directories from lxc containers if they are git directories
if [ -d /var/lib/lxc ]; then
GIT_REPOSITORIES="${GIT_REPOSITORIES} $(find -L /var/lib/lxc/ -maxdepth 3 -name 'etc' | tr '\n' ' ' | sed 's/[[:space:]]\+$//')"
GIT_REPOSITORIES="${GIT_REPOSITORIES} $(find /var/lib/lxc/ -maxdepth 3 -name 'etc' | tr '\n' ' ' | sed 's/[[:space:]]\+$//')"
fi
# initialize variable

View file

@ -0,0 +1,33 @@
From: __FULLFROM__
Content-Type: text/plain; charset=UTF-8
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
To: __TO__
Subject: [evomaintenance] Intervention sur __HOSTNAME__ (__USER__)
Bonjour,
Une intervention vient de se terminer sur votre serveur.
Voici les renseignements sur l'intervention :
Nom du serveur : __HOSTNAME__
Personne ayant réalisée l'intervention : __USER__
Intervention réalisée depuis : __IP__
Début de l'intervention : __BEGIN_DATE__
Fin de l'intervention : __END_DATE__
###
Renseignements sur l'intervention :
__TEXTE__
###
__GIT_COMMITS__
Pour réagir à cette intervention, vous pouvez répondre à ce message
(sur l'adresse mail __FROM__). En cas d'urgence, utilisez
l'adresse __URGENCYFROM__ ou notre téléphone portable d'astreinte
(__URGENCYTEL__)
Cordialement,
--
__FULLFROM__

View file

@ -1,100 +0,0 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project **does not adhere to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)**.
## [Unreleased]
### Added
Add missing (but documented) `--(no-)evocheck` options
### Changed
### Deprecated
### Removed
### Fixed
### Security
## [23.10.1] - 2023-10-09
### Fixed
* Use a special variable name since USER is always defined from the environment
## [23.10] - 2023-10-09
### Added
* Force a user name with `-u,--user` option (default is still `logname(1)`).
* More people credited
### Deprecated
* `--autosysadmin` is replaced by `--user autosysadmin`
## [22.07] - 2022-07-05
### Added
* Add `--autosysadmin` flag
* Commit change in /etc of lxc containers
### Changed
### Deprecated
### Removed
### Fixed
### Security
## [22.01] - 2022-01-25
### Added
* version/host/user headers in sent email
### Changed
New version pattern
## [0.6.4] - 2021-06-17
### Added
* fallback if findmnt is absent
## [0.6.3] - 2020-02-02
### Added
* Notify syslog when partitions are re-mounted (Linux)
## [0.6.2] - 2020-02-02
### Fixed
* better detection of read-only partitions (Linux)
## [0.6.0] - 2019-11-05
### Added
* commit changes in /usr/share/scripts/ if needed
## Previous changelog
* 0.5.0 : options et mode interactif pour l'exécution des actions, meilleure compatibilité POSIX
* 0.4.1 : Utilisation de "printf" à la place de "echo" pour mieux gérer les sauts de ligne
* 0.4.0 : Amélioration de la récupération d'information (plus de cas gérés). Infos Git avant la saisie.
* 0.3.0 : Écriture dans un fichier de log, amélioration de la récupération d'informations, amélioration de la syntaxe shell
* 0.2.7 : Correction d'un bug lors de l'utilisation de '&' dans le texte
* 0.2.6 : Precision du charset dans les entetes du mail
* 0.2.5 : Correction d'un bug avec le path de sendmail sous OpenBSD
* 0.2.4 : Correction d'un bug lors de l'utilisation de '/' dans le texte
* 0.2.3 : Correction d'un bug avec $REALM

View file

@ -1,30 +0,0 @@
# Evomaintenance
```.plain
$ evomaintenance --help
evomaintenance is a program that helps reporting what you've done on a server
Usage: evomaintenance
or evomaintenance --message="add new host"
or evomaintenance --no-api --no-mail --no-commit
or echo "add new vhost" | evomaintenance
Options
-m, --message=MESSAGE set the message from the command line
--mail enable the mail hook (default)
--no-mail disable the mail hook
--db enable the database hook
--no-db disable the database hook (default)
--api enable the API hook (default)
--no-api disable the API hook
--commit enable the commit hook (default)
--no-commit disable the commit hook
--evocheck enable evocheck execution (default)
--no-evocheck disable evocheck execution
--auto use "auto" mode
--no-auto use "manual" mode (default)
-v, --verbose increase verbosity
-n, --dry-run actions are not executed
--help print this message and exit
--version print version and exit
```

View file

@ -35,12 +35,15 @@
- name: Evomaintenance script and template are installed
ansible.builtin.copy:
src: "upstream/evomaintenance.sh"
dest: "/usr/share/scripts/"
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: root
group: root
mode: "0700"
mode: "{{ item.mode }}"
force: true
backup: yes
loop:
- { src: 'evomaintenance.sh', dest: '/usr/share/scripts/', mode: '0700' }
- { src: 'evomaintenance.tpl', dest: '/usr/share/scripts/', mode: '0600' }
tags:
- evomaintenance
- evomaintenance

194
nagios-nrpe/files/alerts_switch Normal file → Executable file
View file

@ -1,83 +1,141 @@
#!/bin/bash
# https://forge.evolix.org/projects/evolix-private/repository
#
# You should not alter this file.
# If you need to, create and customize a copy.
set -e
# Source:
# https://gitea.evolix.org/evolix/ansible-roles/src/branch/stable/nagios-nrpe
#
readonly PROGNAME=$(basename $0)
readonly PROGDIR=$(readlink -m $(dirname $0))
readonly ARGS="$@"
readonly VERSION="24.04.00"
usage() {
echo "$PROGNAME action prefix"
# Load common functions and vars
readonly lib_dir="/usr/local/lib/monitoringctl"
if [ -r "${lib_dir}/common" ]; then
# shellcheck source=monitoringctl_common
source "${lib_dir}/common"
else
>&2 echo "Error: missing ${lib_dir}/common file."
exit 1
fi
function show_help() {
cat <<END
$PROGNAME disables or enables NRPE alerts wrapped by the script 'alerts_wrapper' in NRPE configuration.
Usage: $PROGNAME disable [-d|--during <DURATION>] [--message '<DISABLE_MESSAGE>'] <WRAPPER_NAME|all>
$PROGNAME enable [--message '<ENABLE_MESSAGE>'] <WRAPPER_NAME|all>
$PROGNAME help
WRAPPER_NAME: The name given to '--name' option of 'alerts_wrapper'.
DURATION: Duration of alert disabling.
Can be '1d' for 1 day, '5m' for 5 minutes or more complex
expressions like '1w2d10m42s' (if no time unit is provided,
hour is assumed)
Default value: 1h
DISABLE_MESSAGE: Message that will be logged and printed by alerts_wrapper
when alert is disabled.
ENABLE_MESSAGE: Message that will be logged when alert is enabled
END
}
disable_alerts () {
disabled_file="$1_disabled"
enabled_file="$1_enabled"
function disable_alerts() {
# $1: wrapper name, $2: duration_sec, $3: disable message
now_secs=$(date +"%s")
disable_until_secs=$(( now_secs + ${2} ))
disable_file_path="$(get_disable_file_path "${1}")"
echo "${disable_until_secs}" > "${disable_file_path}"
echo "$(logname || echo unknown): \"${3}\"" >> "${disable_file_path}"
chmod 0644 "${disable_file_path}"
log "${1} alerts disabled by $(logname || echo unknown)"
log "Disable message: ${3}"
}
if [ -e "${enabled_file}" ]; then
mv "${enabled_file}" "${disabled_file}"
else
touch "${disabled_file}"
chmod 0644 "${disabled_file}"
function enable_alerts() {
# $1: wrapper name, $2: enable message
disable_file_path="$(get_disable_file_path "${1}")"
if [ -e "${disable_file_path}" ]; then
rm "${disable_file_path}"
fi
log "${1} alerts enabled by $(logname || echo unknown)"
log "Enable message: ${2}"
}
function main() {
install --mode=0755 --directory "${var_dir}"
if [ "${action}" == 'enable' ]; then
if [ "${wrapper_name}" == "all" ]; then
for wrapper in $(get_wrappers_names); do
enable_alerts "${wrapper}" "${message}"
done
else
enable_alerts "${wrapper_name}" "${message}"
fi
elif [ "${action}" == 'disable' ]; then
duration_sec=$(time_to_seconds "${duration}")
if [ "${wrapper_name}" == "all" ]; then
for wrapper in $(get_wrappers_names); do
disable_alerts "${wrapper}" "${duration_sec}" "${message}"
done
else
disable_alerts "${wrapper_name}" "${duration_sec}" "${message}"
fi
elif [ "${action}" == 'help' ]; then
show_help
fi
}
enable_alerts () {
disabled_file="$1_disabled"
enabled_file="$1_enabled"
if [ -e "${disabled_file}" ]; then
mv "${disabled_file}" "${enabled_file}"
else
touch "${enabled_file}"
chmod 0644 "${enabled_file}"
fi
}
while :; do
case "${1}" in
enable|disable|help)
action="${1}"
shift;;
-d|--during)
if [ "$#" -gt 1 ]; then
if filter_duration "${2}"; then
duration="${2}"
else
usage_error "Option --during: \"${2}\" is not a valid duration."
fi
else
error "Missing --during argument."
fi
shift; shift;;
-m|--message)
if [ "$#" -gt 1 ]; then
message="${2}"
else
error "Missing --message argument."
fi
shift; shift;;
*)
if [ -n "${1}" ]; then
if is_wrapper "${1}" || [ "${1}" == "all" ]; then
wrapper_name="${1}"
else
error "Unknown argument '${1}', or NAME not defined in NRPE configuration."
fi
else
if [ -z "${action}" ]; then
error "Missing action argument."
elif [ -z "${1}" ]; then
break
fi
fi
now () {
date --iso-8601=seconds
}
log_disable () {
echo "$(now) - alerts disabled by $(logname || echo unknown)" >> $1
}
log_enable () {
echo "$(now) - alerts enabled by $(logname || echo unknown)" >> $1
}
main () {
local action=$1
local prefix=$2
local base_dir="/var/lib/misc"
mkdir -p "${base_dir}"
local file_path="${base_dir}/${prefix}_alerts"
local log_file="/var/log/${prefix}_alerts.log"
case "$action" in
enable)
enable_alerts ${file_path}
log_enable ${log_file}
;;
disable)
disable_alerts ${file_path}
log_disable ${log_file}
;;
help)
usage
;;
*)
>&2 echo "Unknown action '$action'"
exit 1
;;
shift;;
esac
}
done
if [ -z "${wrapper_name}" ] && [ "${action}" != 'help' ] ; then
error "Missing WRAPPER_NAME."
fi
if [ -z "${duration}" ]; then
duration="${default_disabled_time}"
fi
readonly wrapper_name duration action
main
main $ARGS

216
nagios-nrpe/files/alerts_wrapper Normal file → Executable file
View file

@ -1,114 +1,96 @@
#!/bin/bash
# https://forge.evolix.org/projects/evolix-private/repository
#
# You should not alter this file.
# If you need to, create and customize a copy.
# Source:
# https://gitea.evolix.org/evolix/ansible-roles/src/branch/stable/nagios-nrpe
#
VERSION="21.04"
readonly VERSION
readonly PROGNAME=$(basename $0)
readonly VERSION="24.04.00"
# base functions
# Load common functions and vars
readonly lib_dir="/usr/local/lib/monitoringctl"
if [ -r "${lib_dir}/common" ]; then
# shellcheck source=monitoringctl_common
source "${lib_dir}/common"
else
>&2 echo "Error: missing ${lib_dir}/common file."
exit 1
fi
show_version() {
function show_help() {
cat <<END
alerts_wrapper version ${VERSION}
alerts_wrapper wraps an NRPE command and overrides the return code.
Copyright 2018-2021 Evolix <info@evolix.fr>,
Jérémy Lecour <jlecour@evolix.fr>
and others.
alerts_wrapper comes with ABSOLUTELY NO WARRANTY.This is free software,
and you are welcome to redistribute it under certain conditions.
See the GNU General Public License v3.0 for details.
END
}
show_help() {
cat <<END
alerts_wrapper is supposed to wrap an NRPE command and overrides the return code.
Usage: alerts_wrapper --limit=1d --name=check_name command with optional arguments
or alerts_wrapper --name=check_name command with optional arguments
or alerts_wrapper check_name command with optional arguments
Usage: alerts_wrapper --name <WRAPPER_NAME> <CHECK_COMMAND>
Usage: alerts_wrapper <WRAPPER_NAME> <CHECK_COMMAND> (deprecated)
Options
--limit max age of the "check file" ;
can be "1d" for 1 day, "5m" for 5 minutes…
or more complex expressions like "1w2d10m42s"
--name check name
-h, --help print this message and exit
-V, --version print version and exit
--name Wrapper name, it is very recommended to use the check name (like load, disk1…).
Special name: 'all' is already hard-coded.
-h, --help Print this message and exit.
-V, --version Print version and exit.
END
}
time_in_seconds() {
if echo "${1}" | grep -E -q '^([0-9]+[wdhms])+$'; then
echo "${1}" | sed 's/w/ * 604800 + /g; s/d/ * 86400 + /g; s/h/ * 3600 + /g; s/m/ * 60 + /g; s/s/ + /g; s/+ $//' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+$)'; then
echo "${1} * 3600" | xargs expr
else
return 1
fi
}
delay_from_alerts_disabled_file() {
last_change=$(stat -c %Z "${alerts_disabled_file}")
limit_seconds=$(time_in_seconds "${wrapper_limit}" || time_in_seconds "${wrapper_limit_default}")
limit_date=$(date --date "${limit_seconds} seconds ago" +"%s")
echo $(( last_change - limit_date ))
}
enable_check() {
function enable_wrapper() {
# $1: wrapper name
if [ "$(id -u)" -eq "0" ] ; then
/usr/local/bin/alerts_switch enable "${check_name}"
/usr/local/bin/alerts_switch enable "${1}"
else
sudo /usr/local/bin/alerts_switch enable "${check_name}"
sudo /usr/local/bin/alerts_switch enable "${1}"
fi
}
main() {
${check_command} > "${check_stdout}"
check_rc=$?
readonly check_rc
function main() {
is_disabled="$(is_disabled "${wrapper_name}")"
delay=0
if [ -e "${alerts_disabled_file}" ]; then
delay=$(delay_from_alerts_disabled_file)
if [ "${delay}" -le "0" ]; then
enable_check
fi
if [ -e "${disable_file}" ] && [ "${is_disabled}" = "False" ]; then
enable_wrapper "${wrapper_name}"
fi
if [ -e "${alerts_disabled_file}" ]; then
formatted_last_change=$(date --date "@$(stat -c %Z "${alerts_disabled_file}")" +'%c')
readonly formatted_last_change
timeout_command=""
if [ "${is_disabled}" = "True" ]; then
timeout_command="timeout 9"
fi
echo "ALERTS DISABLED for ${check_name} (since ${formatted_last_change}, delay: ${delay} sec) - $(cat "${check_stdout}")"
check_stdout="$(${timeout_command} ${check_command})"
check_rc=$?
if [ "${is_disabled}" = "True" ] && [ "${check_rc}" -eq 124 ] && [ -z "${check_stdout}" ]; then
check_stdout="Check timeout (9 sec)"
fi
if [ "${is_disabled}" = "True" ]; then
enable_time="$(get_enable_time "${wrapper_name}")"
enable_delay="$(enable_delay "${enable_time}")"
delay_str="$(delay_to_string "${enable_delay}")"
enable_date="$(date --date "+${enable_delay} seconds" "+%d %h %Y at %H:%M:%S")"
disable_msg="$(get_disable_message "${wrapper_name}")"
if [ -n "${disable_msg}" ]; then
disable_msg="- ${disable_msg} "
fi
echo "ALERT DISABLED until ${enable_date} (${delay_str} left) ${disable_msg}- Check output: ${check_stdout}"
else
echo "${check_stdout}"
fi
if [ "${is_disabled}" = "True" ]; then
if [ ${check_rc} = 0 ]; then
# Nagios OK
exit 0
exit 0 # Nagios OK
else
# Nagios WARNING
exit 1
exit 1 # Nagios WARNING
fi
else
cat "${check_stdout}"
exit ${check_rc}
fi
}
# Default: 1 day before re-enabling the check
wrapper_limit_default="1d"
readonly wrapper_limit_default
if [[ "${1}" =~ -.* ]]; then
# parse options
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
while :; do
case $1 in
case "${1}" in
-h|-\?|--help)
show_help
exit 0
@ -117,47 +99,25 @@ if [[ "${1}" =~ -.* ]]; then
show_version
exit 0
;;
--limit)
-n|--name)
# with value separated by space
if [ -n "$2" ]; then
wrapper_limit=$2
shift
else
printf 'ERROR: "--limit" requires a non-empty option argument.\n' >&2
exit 1
fi
;;
--limit=?*)
# with value speparated by =
wrapper_limit=${1#*=}
;;
--limit=)
# without value
printf 'ERROR: "--limit" requires a non-empty option argument.\n' >&2
exit 1
;;
--name)
# with value separated by space
if [ -n "$2" ]; then
check_name=$2
if [ -n "${2}" ]; then
wrapper_name="${2}"
shift
else
printf 'ERROR: "--name" requires a non-empty option argument.\n' >&2
exit 1
exit 2
fi
;;
--name=?*)
# with value speparated by =
check_name=${1#*=}
-n|--name=?*)
# with value separated by =
wrapper_name="${1#*=}"
;;
--name=)
-n|--name=)
# without value
printf 'ERROR: "--name" requires a non-empty option argument.\n' >&2
exit 1
exit 2
;;
--)
# End of all options.
shift
@ -165,8 +125,8 @@ if [[ "${1}" =~ -.* ]]; then
;;
-?*)
# ignore unknown options
printf 'WARN: Unknown option : %s\n' "$1" >&2
exit 1
printf 'ERROR: Unknown option : %s\n' "${1}" >&2
exit 2
;;
*)
# Default case: If no more options then break out of the loop.
@ -180,38 +140,26 @@ if [[ "${1}" =~ -.* ]]; then
check_command="$*"
else
# no option is passed (backward compatibility with previous version)
# treat the first argument as check_name and the rest as the command
check_name="${1}"
# treat the first argument as wrapper_name and the rest as the command
wrapper_name="${1}"
shift
check_command="$*"
fi
# Default values or errors
if [ -z "${wrapper_limit}" ]; then
wrapper_limit="${wrapper_limit_default}"
fi
if [ -z "${check_name}" ]; then
printf 'ERROR: You must specify a check name, with --name.\n' >&2
exit 1
if [ -z "${wrapper_name}" ]; then
printf 'ERROR: You must specify a wrapper name, with --names.\n' >&2
exit 2
fi
if [ -z "${check_command}" ]; then
printf 'ERROR: You must specify a command to execute.\n' >&2
exit 1
exit 2
fi
if [ -e "${var_dir}" ] && [ ! -x "${var_dir}" ]; then
printf "ERROR: %s exists but is no reachable.\n" "${var_dir}"
exit 2
fi
readonly check_name
readonly check_command
readonly wrapper_limit
alerts_disabled_file="/var/lib/misc/${check_name}_alerts_disabled"
readonly alerts_disabled_file
check_file="/var/lib/misc/${check_name}_alerts_disabled"
readonly check_file
check_stdout=$(mktemp --tmpdir=/tmp "${check_name}_stdout.XXXX")
readonly check_stdout
# shellcheck disable=SC2064
trap "rm ${check_stdout}" EXIT
disable_file="$(get_disable_file_path "${wrapper_name}")"
readonly wrapper_name check_command disable_file
main

View file

@ -1,36 +0,0 @@
#!/usr/bin/env bash
CHECK_BIN=/usr/lib/nagios/plugins/check_nrpe
server_address="127.0.0.1"
if ! test -f "${CHECK_BIN}"; then
echo "${CHECK_BIN} is missing, please install nagios-nrpe-plugin package."
exit 1
fi
for file in /etc/nagios/{nrpe.cfg,nrpe_local.cfg,nrpe.d/evolix.cfg}; do
if [ -r ${file} ]; then
command_search=$(grep "\[check_$1\]" "${file}" | grep -v '^[[:blank:]]*#' | tail -n1 | cut -d'=' -f2-)
fi
if [ -n "${command_search}" ]; then
command="${command_search}"
fi
if [ -r ${file} ]; then
server_address_search=$(grep "server_address" "${file}" | grep -v '^[[:blank:]]*#' | cut -d'=' -f2)
fi
if [ -n "${server_address_search}" ]; then
server_address="${server_address_search}"
fi
done
if [ -n "${command}" ]; then
echo "Found command in /etc/nagios (take care, in some cases, Nagios can play another command):"
echo " ${command}"
fi
echo "NRPE daemon output:"
"${CHECK_BIN}" -H "${server_address}" -c "check_$1"

5
nagios-nrpe/files/check-local_completion Normal file → Executable file
View file

@ -1,5 +1,6 @@
#!/usr/bin/env bash
# List of available checks
_check_local_dynamic_completion() {
local cur;
cur=${COMP_WORDS[COMP_CWORD]};
@ -7,6 +8,10 @@ _check_local_dynamic_completion() {
COMPREPLY=( $( compgen -W '$(grep "\[check_" -Rs /etc/nagios/ | grep -vE "^[[:blank:]]*#" | awk -F"[\\\[\\\]=]" "{print \$2}" | sed "s/check_//" | sort | uniq)' -- $cur ) );
}
# List of available disable names of alerts_wrapper
# grep "alerts_wrapper" -Rs /etc/nagios/ | grep -vE "^\s*#" | awk '{ for (i=1; i<=NF; i++) { if ($i ~ /--name[s]?/) print $(i+1) } }' | tr ',' '\n' | sort | uniq
# + ajouter all
complete -F _check_local_dynamic_completion check-local

0
nagios-nrpe/files/check_async Normal file → Executable file
View file

577
nagios-nrpe/files/monitoringctl Executable file
View file

@ -0,0 +1,577 @@
#!/usr/bin/env bash
#set -x
readonly PROGNAME=$(basename $0)
readonly VERSION="24.04.00"
readonly red="\e[0;31m"
readonly green="\e[0;32m"
readonly orange="\e[0;33m"
readonly lightgreen="\e[1;32m"
readonly yellow="\e[1;33m"
readonly lightblue="\e[1;34m"
readonly purple="\e[0;35m"
readonly nocolor="\e[0m"
# Load common functions and vars
readonly lib_dir="/usr/local/lib/monitoringctl"
if [ -r "${lib_dir}/common" ]; then
# shellcheck source=monitoringctl_common
source "${lib_dir}/common"
else
>&2 echo "Error: missing ${lib_dir}/common file."
exit 1
fi
function show_help() {
cat <<EOF
monitoringctl version ${VERSION}.
monitoringctl gives some control over NRPE checks and alerts.
Usage: monitoringctl [OPTIONS] ACTION ARGUMENTS
GENERAL OPTIONS:
-h, --help Print this message and exit.
-V, --version Print version number and exit.
ACTIONS:
status [CHECK_NAME|all]
Print whether alerts are enabled or not (silenced).
If alerts are disabled (silenced), show disable message and time left before automatic re-enabling.
check [--bypass-nrpe] CHECK_NAME
Ask CHECK_NAME status to NRPE as an HTTP request.
Indicates which command NRPE has supposedly run (from its configuration).
-b, --bypass-nrpe Execute directly command from NRPE configuration,
as user nagios, without passing the request to NRPE.
disable CHECK_NAME|all [--during DURATION] [--message 'DISABLE MESSAGE']
Disable (silence) CHECK_NAME or all alerts for DURATION and write DISABLE MESSAGE into the log.
Checks output is still printed, so alerts history won't be lost.
enable CHECK_NAME|all [--message 'ENABLE MESSAGE']
Re-enable CHECK_NAME or all alerts
show CHECK_NAME
Show NPRE command(s) configured for CHECK_NAME
MESSAGE:
Message to be written in log and disabled check output (mandatory, will be asked dynamically if not provided).
DURATION:
Time (string) during which alerts will be disabled (optional, default: "1h").
Format:
You can use 'd' (day), 'h' (hour) and 'm' (minute) , or a combination of them, to specify a duration.
Examples: '2d', '1h', '10m', '1h10' ('m' is guessed).
NOTES
For actions disable, enable and status, CHECK_NAME is actually the --name option passed to alerts_wrapper, and not the NRPE check name. Both check name and alerts_wrapper --name option should be equal in NRPE configuration to avoid confusion.
Log path: ${log_file}
EOF
}
function check() {
# $1: check name, "all" or empty
readonly check_nrpe_bin="/usr/lib/nagios/plugins/check_nrpe"
if [ ! -f "${check_nrpe_bin}" ]; then
>&2 echo "${check_nrpe_bin} is missing, please install nagios-nrpe-plugin package."
exit 1
fi
conf_lines="$(get_nrpe_conf "${nrpe_conf_path}")"
server_address=$(echo "$conf_lines" | grep "server_address" | tail -n1 | cut -d'=' -f2)
if [ -z "${server_address}" ]; then server_address="127.0.0.1"; fi
server_port=$(echo "$conf_lines" | grep "server_port" | tail -n1 | cut -d'=' -f2)
if [ -z "${server_port}" ]; then server_port="5666"; fi
if [ -z "${1}" ] || [ "${1}" = "all" ]; then
checks="$(get_checks_names)"
header="Check\tStatus\tOutput (truncated)"
underline="-----\t------\t------------------"
str_out="${header}\n${underline}\n"
else
checks="${1}"
if [ "${bypass_nrpe}" = "False" ]; then
str_out="NRPE service output (on ${server_address}:${server_port}):\n"
else
str_out="Direct check output (bypassing NRPE):\n"
fi
fi
for check in $checks; do
printf "\033[KChecking %s…\r" "${check}"
err_msg=""
if [ "${bypass_nrpe}" = "False" ]; then
request_command="${check_nrpe_bin} -H ${server_address} -p ${server_port} -c check_${check} 2&>1"
else
check_commands="$(get_check_commands "${check}")"
if [ -n "${check_commands}" ]; then
check_command="$(echo "${check_commands}" | tail -n1)"
request_command="sudo -u nagios -- ${check_command}"
else
if [ -z "${1}" ] || [ "${1}" = "all" ]; then
err_msg="Check command not found in NRPE configuration."
else
err_msg="Error: no command found in NRPE configuration for check '${check}'. Aborted."
fi
fi
fi
if [ -z "${err_msg}" ]; then
check_output="$(${request_command})"
rc="$?"
check_output="$(echo "${check_output}" | tr '\n' ' ')"
if [ -z "${1}" ] || [ "${1}" = "all" ]; then
if [ "${#check_output}" -gt 60 ]; then
check_output="$(echo "${check_output}" | cut -c-80) [...]"
fi
fi
else
check_output="${err_msg}"
rc="3"
fi
case "${rc}" in
0)
rc_str="OK"
color="${green}"
;;
1)
rc_str="Warning"
color="${orange}"
;;
2)
rc_str="Critical"
color="${red}"
;;
3)
rc_str="Unknown"
color="${purple}"
;;
*)
rc_str="Unknown"
color="${purple}"
esac
if [ -z "${1}" ] || [ "${1}" = "all" ]; then
str_out="${str_out}${color}${check}\t${rc_str}${nocolor}\t${check_output}\n"
fi
done
if [ -z "${1}" ] || [ "${1}" = "all" ]; then
echo -e "${str_out}" | column -t -s $'\t'
else
echo -e "${str_out}${color}${nocolor}${check_output}" | sed 's/|/\n/g'
exit "${rc}"
fi
}
# Print error message and exit if not installed
function alerts_switch_is_installed() {
if ! command -v alerts_switch &> /dev/null; then
error "Error: script 'alerts_switch' is not installed. Aborted."
fi
}
function disable_alerts() {
# $1: check name, $2: disable message
alerts_switch_is_installed
if [ "${1}" = "all" ]; then
checks="$(get_checks_names)"
else
checks="${1}"
fi
warn_not_wrapped "${checks}"
warn_wrapper_names "${checks}"
if [ -z "${2}" ]; then
echo -n "> Please provide a disable message (for logging and check output): "
read -r message
echo ''
if [ -z "${message}" ]; then
error "${red}Error:${nocolor} disable message is mandatory."
fi
else
message="${2}"
fi
default_msg=""
if [ "${default_duration}" = "True" ]; then
default_msg=" (use --during to change default time)"
fi
if [ "${1}" = "all" ]; then
check_txt="All checks"
else
check_txt="Check ${1}"
fi
echo_box "${check_txt} will be disabled for ${duration}${default_msg}."
cat <<EOF
Additional information:
* Alerts history is kept in our monitoring system.
* To re-enable alert(s) before ${duration}, execute as root or with sudo: 'monitoringctl enable ${1}'
EOF
if [ "${1}" != "all" ]; then
wrapper="$(get_check_wrapper_name "${1}")"
checks="$(get_wrapper_checks "${wrapper}")"
n_checks="$(echo "${checks}" | wc -w)"
if [ "${n_checks}" -gt 1 ]; then
other_checks="$(echo "${checks}" | xargs -n1 | grep -v "${1}" | xargs)"
>&2 echo -e "${orange}Warning:${nocolor} because they have the same configuration, disabling ${1} will also disable: ${other_checks}.\n"
log "Warning: check ${1} will also disable ${other_checks} (which have the same wrapper name)."
fi
else
wrapper="all"
fi
echo -n "> Confirm (y/N)? "
read -r answer
if [ "${answer}" != "Y" ] && [ "${answer}" != "y" ]; then
echo -e "${orange}Canceled.${nocolor}" && exit 0
fi
log "Action disable ${1} requested for ${duration} by user $(logname || echo unknown)."
alerts_switch disable "${wrapper}" --during "${duration}" --message "${message}"
if [ "${1}" != "all" ]; then
if [ "${n_checks}" -eq 1 ]; then
echo -e "${orange}Check ${1} alerts are now disabled for ${duration}.${nocolor}"
else
echo -e "${orange}Alerts are now disabled for ${duration} for checks: ${checks}.${nocolor}"
fi
else
echo -e "${orange}All alerts are now disabled for ${duration}.${nocolor}"
fi
}
function enable_alerts() {
# $1: check name, $2: enable message
alerts_switch_is_installed
if [ "${1}" != "all" ]; then
# Verify that check is not already enabled
is_disabled="$(is_disabled "${1}")"
if [ "${is_disabled}" = "False" ]; then
echo "${1} is already enabled, see 'monitoringctl status'"
exit 0
fi
fi
if [ -z "${2}" ]; then
echo -n "> Please provide an enable message (for logging): "
read -r message
echo ''
if [ -z "${message}" ]; then
error "${red}Error:${nocolor} disable message is mandatory."
fi
else
message="${2}"
fi
log "Action enable ${1} requested by user $(logname || echo unknown)."
if [ "${1}" != "all" ]; then
wrapper="$(get_check_wrapper_name "${1}")"
checks="$(get_wrapper_checks "${wrapper}")"
n_checks="$(echo "${checks}" | wc -w)"
if [ "${n_checks}" -gt 1 ]; then
other_checks="$(echo "${checks}" | xargs -n1 | grep -v "${1}" | xargs)"
>&2 echo -e "${orange}Warning:${nocolor} because they have the same configuration, enabling ${1} will also enable: ${other_checks}.\n"
log "Warning: check ${1} will also enable ${other_checks} (which have the same wrapper name)."
fi
else
wrapper="all"
fi
alerts_switch enable "${wrapper}" --message "${message}"
if [ "${1}" != "all" ]; then
if [ "${n_checks}" -eq 1 ]; then
echo -e "${green}Check ${1} alerts are now enabled.${nocolor}"
else
echo -e "${green}Alerts are now enabled for checks: ${checks}.${nocolor}"
fi
else
echo -e "${green}All alerts are now enabled.${nocolor}"
fi
}
# Show NRPE command(s) configured for a check
function show_check_commands() {
# $1: check name
check_commands=$(get_check_commands "${1}")
if [ -z "${check_commands}" ]; then
usage_error "Error: no command found in NRPE configuration for check '${1}."
fi
n_commands="$(echo "${check_commands}" | wc -l)"
if [ "${n_commands}" -ne 1 ]; then
echo "Available commands (in config order, the last one overwrites the others):"
echo " $check_commands"
fi
check_command=$(echo "${check_commands}" | tail -n1)
echo "Command used by NRPE:"
echo " ${check_command}"
}
# Print a warning if some wrappers have the same name
# or if a name is different from the check.
function warn_wrapper_names() {
#$1: checks to verify
warned="False"
for check in ${1}; do
wrapper_name="$(get_check_wrapper_name "${check}")"
if [ -n "${wrapper_name}" ] && [ "${wrapper_name}" != "${check}" ]; then
>&2 echo -e "${orange}Warning:${nocolor} ${check} check has wrapper name ${wrapper_name}."
warned="True"
fi
done
if [ "${warned}" = "True" ]; then
>&2 echo -e "${orange}It is recommanded to name the wrappers the same as the checks.${nocolor}\n"
fi
}
# Print a warning if some checks are not wrapped
function warn_not_wrapped() {
#$1: checks to verify
unwrappeds="$(not_wrapped_checks)"
unwrapped_checks="$(comm -12 <(echo "${1}") <(echo "${unwrappeds}"))"
if [ -n "${unwrapped_checks}" ]; then
n_checks="$(echo "${1}" | wc -w)"
n_unwrapped="$(echo "${unwrapped_checks}" | wc -w)"
if [ "${n_unwrapped}" == "${n_checks}" ]; then
if [ "${n_unwrapped}" -eq 1 ]; then
error "${red}Error:${nocolor} ${1} check is not wrapped, it cannot be disabled."
else
error "${red}Error:${nocolor} these checks are not wrapped, they cannot be disabled: $(echo "${unwrapped_checks}" | xargs)"
fi
else
if [ "${n_unwrapped}" -eq 1 ]; then
>&2 echo -e "${orange}Warning:${nocolor} ${unwrapped_checks} check is not wrapped, it will not be disabled."
else
>&2 echo -e -n "${orange}Warning:${nocolor} some checks are not configured, they will not be disabled: $(echo "${unwrapped_checks}" | xargs)\n\n"
fi
fi
log "Warning: some checks have no alerts_wrapper, they will not be disabled: $(echo "${unwrapped_checks}" | xargs)"
fi
}
# Echo a message in a box
function echo_box() {
# $1: message
msg_len="${#1}"
line="$(printf '─%.0s' $(eval "echo {1.."${msg_len}"}"))"
cat <<EOF
┌${line}┐
│${1}│
└${line}┘
EOF
}
# Echo which checks are enabled or disabled and time left
function alerts_status() {
# $1: check name, "all" or empty
if [ -z "${1}" ] || [ "${1}" = "all" ]; then
checks="$(get_checks_names)"
else
checks="${1}"
fi
warn_wrapper_names "${checks}"
header="Check\tStatus\tRe-enable time\tDisable message"
underline="-----\t------\t--------------\t---------------"
str_out="${header}\n${underline}\n"
for check in $checks; do
enable_str=""
status_str="Enabled"
disable_msg=""
if ! is_wrapped "${check}"; then
status_str="Not configured"
else
is_disabled="$(is_disabled "${check}")"
wrapper_name="$(get_check_wrapper_name "${check}")"
if [ "${is_disabled}" = "True" ]; then
status_str="Disabled"
enable_time="$(get_enable_time "${wrapper_name}")"
enable_delay="$(enable_delay "${enable_time}")"
delay_str="$(delay_to_string "${enable_delay}")"
enable_date="$(date --date "+${enable_delay} seconds" "+%d %h %Y at %H:%M:%S")"
enable_str="${enable_date} (${delay_str} left)"
disable_msg="$(get_disable_message "${wrapper_name}")"
fi
fi
case "${status_str}" in
"Enabled")
color="${green}"
;;
"Disabled")
color="${orange}"
;;
*)
color="${red}"
esac
str_out="${str_out}${color}${check}\t${status_str}${nocolor}\t${enable_str}\t${disable_msg}\n"
done
echo -e "${str_out}" | column -t -s $'\t'
}
### MAIN #########################################
# No root
if [ "$(id -u)" -ne 0 ]; then
>&2 echo "You need to be root (or use sudo) to run ${0}!"
exit 1
fi
# No argument
if [ "$#" = "0" ]; then
show_help
exit 1
fi
# Default arguments and options
action=""
message=""
duration="${default_disabled_time}"
bypass_nrpe="False"
default_duration="True"
# Parse arguments and options
while :; do
case "${1}" in
-h|-\?|--help)
show_help
exit 0;;
-V|--version)
show_version
exit 0;;
-b|--bypass-nrpe)
bypass_nrpe="True"
shift;;
-d|--during)
if [ "${default_duration}" = "False" ]; then
usage_error "Option --during: defined multiple times."
fi
if [ "$#" -lt 2 ]; then
usage_error "Option --during: missing value."
fi
if filter_duration "${2}"; then
duration="${2}"
else
usage_error "Option --during: \"${2}\" is not a valid duration."
fi
default_duration="False"
shift; shift;;
-m|--message)
if [ "$#" -lt 2 ]; then
usage_error "Option --message: missing message string."
fi
message="${2}"
shift; shift;;
status|check|enable|disable|show)
action="${1}"
shift;;
*)
if [ -z "${1}" ]; then
break
fi
case "${action}" in
status)
if is_check "${1}" || [ "${1}" = "all" ]; then
check_name="${1}"
else
usage_error "Action ${action}: unknown check '${1}'."
fi
;;
check|show)
if is_check "${1}"; then
check_name="${1}"
else
usage_error "Action ${action}: unknown check '${1}'."
fi
;;
enable|disable)
if is_wrapper "${1}" || is_check "${1}" || [ "${1}" = "all" ]; then
check_name="${1}"
else
# We use the word "check" for the end user,
# but this is actually "unknown wrapper"
usage_error "Action ${action}: unknown check '${1}'."
fi
;;
*)
usage_error "Missing or invalid ACTION argument."
;;
esac
shift;;
esac
done
if [ "$#" -gt 0 ]; then
usage_error "Too many arguments."
fi
case "${action}" in
disable|enable|show)
if [ -z "${check_name}" ]; then
usage_error "Action ${action}: missing CHECK_NAME argument."
fi
;;
esac
if [ ! "${action}" = "disable" ]; then
if [ "${default_duration}" = "False" ]; then
usage_error "Action ${action}: there is no --during option."
fi
fi
case "${action}" in
status)
alerts_status "${check_name}"
;;
check)
check "${check_name}"
;;
show)
show_check_commands "${check_name}"
;;
enable)
enable_alerts "${check_name}" "${message}"
;;
disable)
disable_alerts "${check_name}" "${message}"
;;
esac

View file

@ -0,0 +1,286 @@
#!/usr/bin/env bash
# Location of disable files
readonly var_dir="/var/lib/monitoringctl"
readonly log_file="/var/log/monitoringctl.log"
readonly nrpe_conf_path="/etc/nagios/nrpe.cfg"
debian_major_version="$(cut -d "." -f 1 < /etc/debian_version)"
readonly debian_major_version
# If no time limit is provided in CLI or found in file, this value is used
readonly default_disabled_time="1h"
_nrpe_conf_lines='' # populated at the end of the file
function error() {
# $1: error message
>&2 echo -e "${1}"
exit 1
}
function usage_error() {
# $1: error message
>&2 echo "${1}"
>&2 echo "Execute \"${PROGNAME} --help\" for information on usage."
exit 1
}
function log() {
# $1: message
echo "$(now_iso) - ${PROGNAME}: ${1}" >> "${log_file}"
}
function show_version() {
cat <<END
${PROGNAME} version ${VERSION}.
Copyright 2018-2024 Evolix <info@evolix.fr>,
Jérémy Lecour <jlecour@evolix.fr>
and others.
${PROGNAME} comes with ABSOLUTELY NO WARRANTY.This is free software,
and you are welcome to redistribute it under certain conditions.
See the GNU General Public License v3.0 for details.
END
}
# Fail if argument does not respect format: XwXdXhXmXs, XhX, XmX
function filter_duration() {
# $1: duration in format specified above
_time_regex="^([0-9]+d)?(([0-9]+h(([0-9]+m?)|([0-9]+m([0-9]+s?)?))?)|(([0-9]+m([0-9]+s?)?)?))?$"
if [[ "${1}" =~ ${_time_regex} ]]; then
return 0
fi
return 1
}
# Convert human writable duration into seconds
function time_to_seconds() {
# $1: formated time string
if echo "${1}" | grep -E -q '^([0-9]+[wdhms])+$'; then
echo "${1}" | sed 's/w/ * 604800 + /g; s/d/ * 86400 + /g; s/h/ * 3600 + /g; s/m/ * 60 + /g; s/s/ + /g; s/+ $//' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+h[0-9]+$)'; then
echo "${1}" | sed 's/h/ * 3600 + /g; s/$/ * 60/' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+m[0-9]+$)'; then
echo "${1}" | sed 's/m/ * 60 + /g' | xargs expr
else
error "Invalid duration: '${1}'."
fi
}
# Print re-enable time in secs
function get_enable_time() {
# $1: wrapper name
_disable_file_path="$(get_disable_file_path "${1}")"
if [ ! -e "${_disable_file_path}" ]; then
return
fi
_enable_secs="$(grep -v -E "^\s*#" "${_disable_file_path}" | sed '/^$/d' | head -n1 | awk '/^[0-9]+$/ {print $1}')"
# If file is empty, use file last change date plus default disabled time
if [ -z "${_enable_secs}" ]; then
_file_last_change_secs="$(stat -c %Z "${_disable_file_path}")"
_default_disabled_time_secs="$(time_to_seconds "${default_disabled_time}")"
_enable_secs="$(( _file_last_change_secs + _default_disabled_time_secs ))"
fi
echo "${_enable_secs}"
}
# Print disable message
function get_disable_message() {
# $1: wrapper name
_disable_file_path="$(get_disable_file_path "${1}")"
if [ ! -e "${_disable_file_path}" ]; then
return
fi
_disable_msg="$(sed '/^$/d' "${_disable_file_path}" | tail -n+2 | tr '\n' ' ' | awk '{$1=$1;print}')"
echo "${_disable_msg}"
}
function now_secs() {
date +"%s"
}
function now_iso() {
date --iso-8601=seconds
}
# Print delay before re-enable in secs
function enable_delay() {
# $1: re-enable time in secs
echo $(( ${1} - $(now_secs) ))
}
# Converts delay (in seconds) into human readable duration
function delay_to_string() {
# $1: delay in secs
_delay_days="$(( ${1} /86400 ))"
if [ "${_delay_days}" -eq 0 ]; then _delay_days=""
else _delay_days="${_delay_days}d"; fi
_delay_hours="$(( (${1} %86400) /3600 ))"
if [ "${_delay_hours}" -eq 0 ]; then _delay_hours=""
else _delay_hours="${_delay_hours}h"; fi
_delay_minutes="$(( ((${1} %86400) %3600) /60 ))"
if [ "${_delay_minutes}" -eq 0 ]; then _delay_minutes=""
else _delay_minutes="${_delay_minutes}m"; fi
_delay_seconds="$(( ((${1} %86400) %3600) %60 ))"
if [ "${_delay_seconds}" -eq 0 ]; then _delay_seconds=""
else _delay_seconds="${_delay_seconds}s"; fi
echo "${_delay_days}${_delay_hours}${_delay_minutes}${_delay_seconds}"
}
function is_disabled() {
# $1: check name
_wrapper="$(get_check_wrapper_name "${1}")"
_disable_file_path="$(get_disable_file_path "${_wrapper}")"
if [ -e "${_disable_file_path}" ]; then
_enable_time="$(get_enable_time "${_wrapper}")"
_enable_delay="$(enable_delay "${_enable_time}")"
if [ "${_enable_delay}" -le "0" ]; then
echo "False"
else
echo "True"
fi
else
echo False
fi
}
function get_disable_file_path() {
# $1: wrapper name
echo "${var_dir}/${1}_alerts_disabled"
}
### Nagios configuration functions ####################
# Print NRPE configuration, with includes, without comments
# and in the same order than NRPE does (taking account that
# order changes from Deb10)
function get_nrpe_conf() {
echo "${_nrpe_conf_lines}"
}
# Private function to recursively get NRPE conf from file
function _get_conf_from_file() {
# $1: NRPE conf file (.cfg)
if [ ! -f "${1}" ]; then return; fi
_conf_lines=$(grep -E -R -v --no-filename "^\s*(#.*|)$" "${1}")
while read -r _line; do
if [[ "${_line}" =~ .*'include='.* ]]; then
_conf_file=$(echo "${_line}" | cut -d= -f2)
_get_conf_from_file "${_conf_file}"
elif [[ "${_line}" =~ .*'include_dir='.* ]]; then
_conf_dir=$(echo "${_line}" | cut -d= -f2)
_get_conf_from_dir "${_conf_dir}"
else
echo "${_line}"
fi
done <<< "${_conf_lines}"
}
# Private function to recursively get NRPE conf from directory
function _get_conf_from_dir() {
# $1: NRPE conf dir
if [ ! -d "${1}" ]; then return; fi
if [ "${debian_major_version}" -ge 10 ]; then
# From Deb10, NRPE use scandir() with alphasort() function
_sort_command="sort"
else
# Before Deb10, NRPE use loaddir(), like find utility
_sort_command="cat -"
fi
# Add conf files in dir to be processed recursively
for _file in $(find "${1}" -maxdepth 1 -name "*.cfg" 2> /dev/null | ${_sort_command}); do
if [ -f "${_file}" ]; then
_get_conf_from_file "${_file}"
elif [ -d "${_file}" ]; then
_get_conf_from_dir "${_file}"
fi
done
}
# Print the checks that are configured in NRPE
function get_checks_names() {
echo "${_nrpe_conf_lines}" | grep -E "command\[check_.*\]=" | awk -F"[\\\[\\\]=]" '{sub("check_", "", $2); print $2}' | sort | uniq
}
# Print the commands defined for check $1 in NRPE configuration
function get_check_commands() {
# $1: check name
echo "${_nrpe_conf_lines}" | grep -E "command\[check_${1}\]" | cut -d'=' -f2-
}
# Print the checks that have no alerts_wrapper in NRPE configuration
function not_wrapped_checks() {
for _check in $(get_checks_names); do
if ! is_wrapped "${_check}"; then
echo "${_check}"
fi
done
}
# Fail if check is not wrapped
function is_wrapped() {
# $1: check name
_cmd=$(get_check_commands "${1}" | tail -n1)
if echo "${_cmd}" | grep --quiet --no-messages alerts_wrapper; then
return 0
fi
return 1
}
# Print the names that are defined in the wrappers of the checks
function get_wrappers_names() {
echo "${_nrpe_conf_lines}" | grep -s "alerts_wrapper" | awk '{ for (i=1 ; i<=NF; i++) { if ($i ~ /^(-n|--name)$/) { print $(i+1); break } } }' | tr ',' '\n' | sort | uniq
}
# Print the wrapper name of the check
function get_check_wrapper_name() {
# $1: check name
_cmd=$(get_check_commands "${1}" | tail -n1)
if echo "${_cmd}" | grep --quiet --no-messages alerts_wrapper; then
echo "${_cmd}" | awk '/--name/ {match($0, /--name\s*([a-zA-Z0-9_\-]*)\s*/, m); print m[1]}'
fi
}
function is_check() {
# $1: check name
_checks="$(get_checks_names)"
if echo "${_checks}" | grep --quiet -E "^${1}$"; then
return 0
fi
return 1
}
function is_wrapper() {
# $1: wrapper name
_wrappers="$(get_wrappers_names)"
if echo "${_wrappers}" | grep --quiet -E "^${1}$"; then
return 0
fi
return 1
}
# Print the checks that name this wrapper
function get_wrapper_checks() {
# $1: wrapper name
echo "${_nrpe_conf_lines}" | grep -E "command\[check_.*\]=" | grep -E "\-\-name\s*${1}" | awk -F"[\\\[\\\]=]" '{sub("check_", "", $2); print $2}' | sort | uniq | xargs
}
# Load NRPE configuration
_nrpe_conf_lines="$(_get_conf_from_file "${nrpe_conf_path}")"

View file

@ -0,0 +1,88 @@
#!/usr/bin/bash
#
function _get_wrappers_names() {
grep "alerts_wrapper" --no-filename --no-messages -R /etc/nagios/ | grep --invert-match --extended-regexp "^\s*#" | awk '{ for (i=1 ; i<=NF; i++) { if ($i ~ /^(-n|--name)$/) { print $(i+1); break } } }' | tr ',' '\n' | sort | uniq
}
function _get_checks_names() {
grep --extended-regexp --no-filename --no-messages -R "command\[check_.*\]=" /etc/nagios/ | grep --invert-match --extended-regexp "^\s*#" | awk -F"[\\\[\\\]=]" '{sub("check_", "", $2); print $2}' | sort | uniq
}
function _monitoringctl_completion() {
local cur=${COMP_WORDS[COMP_CWORD]};
local prev=${COMP_WORDS[COMP_CWORD-1]};
local action=""
for w in "${COMP_WORDS[@]}"; do
case "$w" in
status|check|enable|disable|show)
action="${w}"
;;
esac
done
local words="--help"
case "${action}" in
check|show)
checks="$(_get_checks_names)"
check=""
for w in "${COMP_WORDS[@]}"; do
for c in ${checks}; do
if [ "${c}" == "${w}" ]; then
check="${w}"
break
fi
done
done
if [ -z "${check}" ]; then
words="${checks} ${words}"
fi
if [ "${action}" == "check" ]; then
words="--bypass-nrpe ${words}"
fi
;;
status)
if [ "${prev}" == "enable" ]; then
words="all $(_get_checks_names)"
fi
;;
enable)
if [ "${prev}" == "enable" ]; then
words="all $(_get_wrappers_names)"
else
words="--comment ${words}"
fi
;;
disable)
if [ "${prev}" == "disable" ]; then
words="all $(_get_wrappers_names)"
elif [ "${prev}" == "-d" ] || [ "${prev}" == "--during" ]; then
words="1d 1d12h 1h 1h30m 1m 1m30s 30s"
else
words="--during --comment ${words}"
fi
;;
*)
words="status check enable disable show ${words}"
;;
esac
# Avoid double
opts=();
for i in ${words}; do
for j in "${COMP_WORDS[@]}"; do
if [[ "$i" == "$j" ]]; then
continue 2
fi
done
opts+=("$i")
done
COMPREPLY=($(compgen -W "${opts[*]}" -- "${cur}"))
return 0
}
complete -F _monitoringctl_completion monitoringctl

View file

@ -93,4 +93,5 @@
- ansible.builtin.include_tasks: wrapper.yml
- ansible.builtin.include_tasks: check-local.yml
- ansible.builtin.include_tasks: monitoringctl.yml

View file

@ -0,0 +1,44 @@
---
- name: "Remount /usr if needed"
ansible.builtin.include_role:
name: remount-usr
- name: "dir /usr/local/lib/monitoringctl/ exists"
ansible.builtin.file:
path: /usr/local/lib/monitoringctl/
state: directory
mode: '0755'
- name: "monitoringctl is not in /usr/local/sbin/"
ansible.builtin.file:
path: /usr/local/sbin/monitoringctl
state: absent
- name: "copy monitoringctl"
ansible.builtin.copy:
src: monitoringctl
dest: /usr/local/bin/monitoringctl
owner: root
group: root
mode: "0750"
force: true
- name: "copy monitoringctl_common lib"
ansible.builtin.copy:
src: monitoringctl_common
dest: /usr/local/lib/monitoringctl/common
owner: root
group: root
mode: "0644"
force: true
- name: "copy monitoringctl_completion script"
ansible.builtin.copy:
src: monitoringctl_completion
dest: /etc/bash_completion.d/monitoringctl
owner: root
group: root
mode: "0644"
force: true

View file

@ -1,16 +1,21 @@
---
- name: "Remount /usr if needed"
ansible.builtin.include_role:
name: remount-usr
- name: check if old script is present
- name: "dir /usr/local/lib/monitoringctl/ exists"
ansible.builtin.file:
path: /usr/local/lib/monitoringctl/
state: directory
mode: '0755'
- name: "check if old alerts_switch script is present"
ansible.builtin.stat:
path: /usr/share/scripts/alerts_switch
register: old_alerts_switch
- name: alerts_switch is at the right place
- name: "alerts_switch is at the right place"
ansible.builtin.command:
cmd: "mv /usr/share/scripts/alerts_switch /usr/local/bin/alerts_switch"
args:
@ -26,18 +31,56 @@
mode: "0750"
force: true
- name: "symlink for backward compatibility"
- name: "alerts_switch symlink for backward compatibility"
ansible.builtin.file:
src: /usr/local/bin/alerts_switch
dest: /usr/share/scripts/alerts_switch
path: /usr/share/scripts/alerts_switch
state: link
when: old_alerts_switch.stat.exists
- name: "Nagios user can run alerts_switch with sudo (used by alerts_wrapper)"
ansible.builtin.lineinfile:
path: /etc/sudoers.d/evolinux
regexp: "nagios.*alerts_switch"
line: "nagios ALL = NOPASSWD:/usr/local/bin/alerts_switch *"
owner: root
group: root
mode: "640"
validate: "visudo -c -f %s"
- name: "check if old alerts_wrapper script is present"
ansible.builtin.stat:
path: "{{ nagios_plugins_directory }}/alerts_wrapper"
register: old_alerts_wrapper
- name: "alerts_wrapper is at the right place"
ansible.builtin.command:
cmd: "mv {{ nagios_plugins_directory }}/alerts_wrapper /usr/local/lib/monitoringctl/alerts_wrapper"
creates: /usr/local/lib/monitoringctl/alerts_wrapper
when: old_alerts_wrapper.stat.exists
- name: "copy alerts_wrapper"
ansible.builtin.copy:
src: alerts_wrapper
dest: "{{ nagios_plugins_directory }}/alerts_wrapper"
dest: "/usr/local/lib/monitoringctl/alerts_wrapper"
owner: root
group: staff
mode: "0755"
force: true
force: true
- name: "alerts_wrapper symlink for backward compatibility"
ansible.builtin.file:
src: /usr/local/lib/monitoringctl/alerts_wrapper
path: "{{ nagios_plugins_directory }}/alerts_wrapper"
state: link
when: old_alerts_wrapper.stat.exists
- name: "copy monitoringctl_common lib"
ansible.builtin.copy:
src: monitoringctl_common
dest: /usr/local/lib/monitoringctl/common
owner: root
group: root
mode: "0644"
force: true

View file

@ -1,29 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
Comment: GPGTools - https://gpgtools.org
mQENBFdDN1ABCADaNd/I3j3tn40deQNgz7hB2NvT+syXe6k4ZmdiEcOfBvFrkS8B
hNS67t93etHsxEy7E0qwsZH32bKazMqe9zDwoa3aVImryjh6SHC9lMtW27JPHFeM
Srkt9YmH1WMwWcRO6eSY9B3PpazquhnvbammLuUojXRIxkDroy6Fw4UKmUNSRr32
9Ej87jRoR1B2/57Kfp2Y4+vFGGzSvh3AFQpBHq51qsNHALU6+8PjLfIt+5TPvaWR
TB+kAZnQZkaIQM2nr1n3oj6ak2RATY/+kjLizgFWzgEfbCrbsyq68UoY5FPBnu4Z
E3iDZpaIqwKr0seUC7iA1xM5eHi5kty1oB7HABEBAAG0Ik5Tb2xpZCA8bnNvbGlk
LWdwZ0Bub2Rlc291cmNlLmNvbT6JATgEEwECACIFAldDN1ACGwMGCwkIBwMCBhUI
AgkKCwQWAgMBAh4BAheAAAoJEC9ZtfmbG+C0y7wH/i4xnab36dtrYW7RZwL8i6Sc
NjMx4j9+U1kr/F6YtqWd+JwCbBdar5zRghxPcYEq/qf7MbgAYcs1eSOuTOb7n7+o
xUwdH2iCtHhKh3Jr2mRw1ks7BbFZPB5KmkxHaEBfLT4d+I91ZuUdPXJ+0SXs9gzk
Dbz65Uhoz3W03aiF8HeL5JNARZFMbHHNVL05U1sTGTCOtu+1c/33f3TulQ/XZ3Y4
hwGCpLe0Tv7g7Lp3iLMZMWYPEa0a7S4u8he5IEJQLd8bE8jltcQvrdr3Fm8kI2Jg
BJmUmX4PSfhuTCFaR/yeCt3UoW883bs9LfbTzIx9DJGpRIu8Y0IL3b4sj/GoZVq5
AQ0EV0M3UAEIAKrTaC62ayzqOIPa7nS90BHHck4Z33a2tZF/uof38xNOiyWGhT8u
JeFoTTHn5SQq5Ftyu4K3K2fbbpuu/APQF05AaljzVkDGNMW4pSkgOasdysj831cu
ssrHX2RYS22wg80k6C/Hwmh5F45faEuNxsV+bPx7oPUrt5n6GMx84vEP3i1+FDBi
0pt/B/QnDFBXki1BGvJ35f5NwDefK8VaInxXP3ZN/WIbtn5dqxppkV/YkO7GiJlp
Jlju9rf3kKUIQzKQWxFsbCAPIHoWv7rH9RSxgDithXtG6Yg5R1aeBbJaPNXL9wpJ
YBJbiMjkAFaz4B95FOqZm3r7oHugiCGsHX0AEQEAAYkBHwQYAQIACQUCV0M3UAIb
DAAKCRAvWbX5mxvgtE/OB/0VN88DR3Y3fuqy7lq/dthkn7Dqm9YXdorZl3L152eE
IF882aG8FE3qZdaLGjQO4oShAyNWmRfSGuoH0XERXAI9n0r8m4mDMxE6rtP7tHet
y/5M8x3CTyuMgx5GLDaEUvBusnTD+/v/fBMwRK/cZ9du5PSG4R50rtst+oYyC2ao
x4I2SgjtF/cY7bECsZDplzatN3gv34PkcdIg8SLHAVlL4N5tzumDeizRspcSyoy2
K2+hwKU4C4+dekLLTg8rjnRROvplV2KtaEk6rxKtIRFDCoQng8wfJuIMrDNKvqZw
FRGt7cbvW5MCnuH8MhItOl9Uxp1wHp6gtav/h8Gp6MBa
=MARt
mQINBFObJLYBEADkFW8HMjsoYRJQ4nCYC/6Eh0yLWHWfCh+/9ZSIj4w/pOe2V6V+
W6DHY3kK3a+2bxrax9EqKe7uxkSKf95gfns+I9+R+RJfRpb1qvljURr54y35IZgs
fMG22Np+TmM2RLgdFCZa18h0+RbH9i0b+ZrB9XPZmLb/h9ou7SowGqQ3wwOtT3Vy
qmif0A2GCcjFTqWW6TXaY8eZJ9BCEqW3k/0Cjw7K/mSy/utxYiUIvZNKgaG/P8U7
89QyvxeRxAf93YFAVzMXhoKxu12IuH4VnSwAfb8gQyxKRyiGOUwk0YoBPpqRnMmD
Dl7SdmY3oQHEJzBelTMjTM8AjbB9mWoPBX5G8t4u47/FZ6PgdfmRg9hsKXhkLJc7
C1btblOHNgDx19fzASWX+xOjZiKpP6MkEEzq1bilUFul6RDtxkTWsTa5TGixgCB/
G2fK8I9JL/yQhDc6OGY9mjPOxMb5PgUlT8ox3v8wt25erWj9z30QoEBwfSg4tzLc
Jq6N/iepQemNfo6Is+TG+JzI6vhXjlsBm/Xmz0ZiFPPObAH/vGCY5I6886vXQ7ft
qWHYHT8jz/R4tigMGC+tvZ/kcmYBsLCCI5uSEP6JJRQQhHrCvOX0UaytItfsQfLm
EYRd2F72o1yGh3yvWWfDIBXRmaBuIGXGpajC0JyBGSOWb9UxMNZY/2LJEwARAQAB
tB9Ob2RlU291cmNlIDxncGdAbm9kZXNvdXJjZS5jb20+iQI4BBMBAgAiBQJTmyS2
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAWVaCraFdigHTmD/9OKhUy
jJ+h8gMRg6ri5EQxOExccSRU0i7UHktecSs0DVC4lZG9AOzBe+Q36cym5Z1di6JQ
kHl69q3zBdV3KTW+H1pdmnZlebYGz8paG9iQ/wS9gpnSeEyx0Enyi167Bzm0O4A1
GK0prkLnz/yROHHEfHjsTgMvFwAnf9uaxwWgE1d1RitIWgJpAnp1DZ5O0uVlsPPm
XAhuBJ32mU8S5BezPTuJJICwBlLYECGb1Y65Cil4OALU7T7sbUqfLCuaRKxuPtcU
VnJ6/qiyPygvKZWhV6Od0Yxlyed1kftMJyYoL8kPHfeHJ+vIyt0s7cropfiwXoka
1iJB5nKyt/eqMnPQ9aRpqkm9ABS/r7AauMA/9RALudQRHBdWIzfIg0Mlqb52yyTI
IgQJHNGNX1T3z1XgZhI+Vi8SLFFSh8x9FeUZC6YJu0VXXj5iz+eZmk/nYjUt4Mtc
pVsVYIB7oIDIbImODm8ggsgrIzqxOzQVP1zsCGek5U6QFc9GYrQ+Wv3/fG8hfkDn
xXLww0OGaEQxfodm8cLFZ5b8JaG3+Yxfe7JkNclwvRimvlAjqIiW5OK0vvfHco+Y
gANhQrlMnTx//IdZssaxvYytSHpPZTYw+qPEjbBJOLpoLrz8ZafN1uekpAqQjffI
AOqW9SdIzq/kSHgl0bzWbPJPw86XzzftewjKNbkCDQRTmyS2ARAAxSSdQi+WpPQZ
fOflkx9sYJa0cWzLl2w++FQnZ1Pn5F09D/kPMNh4qOsyvXWlekaV/SseDZtVziHJ
Km6V8TBG3flmFlC3DWQfNNFwn5+pWSB8WHG4bTA5RyYEEYfpbekMtdoWW/Ro8Kmh
41nuxZDSuBJhDeFIp0ccnN2Lp1o6XfIeDYPegyEPSSZqrudfqLrSZhStDlJgXjea
JjW6UP6txPtYaaila9/Hn6vF87AQ5bR2dEWB/xRJzgNwRiax7KSU0xca6xAuf+TD
xCjZ5pp2JwdCjquXLTmUnbIZ9LGV54UZ/MeiG8yVu6pxbiGnXo4Ekbk6xgi1ewLi
vGmz4QRfVklV0dba3Zj0fRozfZ22qUHxCfDM7ad0eBXMFmHiN8hg3IUHTO+UdlX/
aH3gADFAvSVDv0v8t6dGc6XE9Dr7mGEFnQMHO4zhM1HaS2Nh0TiL2tFLttLbfG5o
QlxCfXX9/nasj3K9qnlEg9G3+4T7lpdPmZRRe1O8cHCI5imVg6cLIiBLPO16e0fK
yHIgYswLdrJFfaHNYM/SWJxHpX795zn+iCwyvZSlLfH9mlegOeVmj9cyhN/VOmS3
QRhlYXoA2z7WZTNoC6iAIlyIpMTcZr+ntaGVtFOLS6fwdBqDXjmSQu66mDKwU5Ek
fNlbyrpzZMyFCDWEYo4AIR/18aGZBYUAEQEAAYkCHwQYAQIACQUCU5sktgIbDAAK
CRAWVaCraFdigIPQEACcYh8rR19wMZZ/hgYv5so6Y1HcJNARuzmffQKozS/rxqec
0xM3wceL1AIMuGhlXFeGd0wRv/RVzeZjnTGwhN1DnCDy1I66hUTgehONsfVanuP1
PZKoL38EAxsMzdYgkYH6T9a4wJH/IPt+uuFTFFy3o8TKMvKaJk98+Jsp2X/QuNxh
qpcIGaVbtQ1bn7m+k5Qe/fz+bFuUeXPivafLLlGc6KbdgMvSW9EVMO7yBy/2JE15
ZJgl7lXKLQ31VQPAHT3an5IV2C/ie12eEqZWlnCiHV/wT+zhOkSpWdrheWfBT+ac
hR4jDH80AS3F8jo3byQATJb3RoCYUCVc3u1ouhNZa5yLgYZ/iZkpk5gKjxHPudFb
DdWjbGflN9k17VCf4Z9yAb9QMqHzHwIGXrb7ryFcuROMCLLVUp07PrTrRxnO9A/4
xxECi0l/BzNxeU1gK88hEaNjIfviPR/h6Gq6KOcNKZ8rVFdwFpjbvwHMQBWhrqfu
G3KaePvbnObKHXpfIKoAM7X2qfO+IFnLGTPyhFTcrl6vZBTMZTfZiC1XDQLuGUnd
sckuXINIU3DFWzZGr0QrqkuE/jyr7FXeUJj9B7cLo+s/TXo+RaVfi3kOc9BoxIvy
/qiNGs/TKy2/Ujqp/affmIMoMXSozKmga81JSwkADO1JMgUy6dApXz9kP4EE3g==
=CLGF
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -24,7 +24,7 @@
- name: Add NodeJS repository (Debian <12)
ansible.builtin.apt_repository:
repo: "deb [signed-by={{ apt_keyring_dir }}/nodesource.asc] https://deb.nodesource.com/{{ nodejs_apt_version }} nodistro main"
repo: "deb [signed-by={{ apt_keyring_dir }}/nodesource.asc] https://deb.nodesource.com/{{ nodejs_apt_version }} {{ ansible_distribution_release }} main"
filename: nodesource
update_cache: yes
state: present

View file

@ -2,7 +2,7 @@
Types: deb
URIs: https://deb.nodesource.com/{{ nodejs_apt_version }}
Suites: nodistro
Suites: {{ ansible_distribution_release }}
Components: main
Signed-by: {{ apt_keyring_dir }}/nodesource.asc
Enabled: yes
Enabled: yes

View file

@ -31,11 +31,11 @@
marker: "## {mark} ANSIBLE MANAGED INPUT RULES FOR VRID {{ vrrp_address.id }}"
block: |
{% if vrrp_address.peers | default([]) | length <= 0 %}
/sbin/iptables -A INPUT -i {{ vrrp_address.interface }} -d 224.0.0.0/8 -j ACCEPT # Allow VRRP input on {{ vrrp_address.interface }} for VRID {{ vrrp_address.id }}
/sbin/iptables -A INPUT -i {{ vrrp_address.interface }} -d 224.0.0.0/8 -j ACCEPT # Allow VRRP input on {{ vrrp_address.interface }} for VRID {{ vrrp_address.id }}
{% else %}
{% for peer in vrrp_address.peers %}
/sbin/iptables -A INPUT -i {{ vrrp_address.interface }} -s {{ peer }} -d 224.0.0.0/8 -j ACCEPT # Allow VRRP input on {{ vrrp_address.interface }} from {{ peer }} for VRID {{ vrrp_address.id }}
{% endfor %}
{% for peer in vrrp_address.peers %}
/sbin/iptables -A INPUT -i {{ vrrp_address.interface }} -s {{ peer }} -d 224.0.0.0/8 -j ACCEPT # Allow VRRP input on {{ vrrp_address.interface }} from {{ peer }} for VRID {{ vrrp_address.id }}
{% endfor %}
{% endif %}
create: yes
mode: "0600"