domains: revert commits moved to dev branch domains

William Hirigoyen 2 weeks ago
parent 0964865c4c
commit c310482ba6
  1. 2
  2. 325
  3. 8
  4. 6
  5. 14
  6. 25
  7. 1
  8. 1

@ -16,7 +16,6 @@ The **patch** part changes is incremented if multiple releases happen the same m
* php: install php-xml with recent PHP versions
* vrrp: add an `ip.yml` task file to help create VRRP addresses
* webapps/nextcloud: Add compatibility with apache2, and apache2 mod_php.
* inspect-domains: Add role
* memcached: NRPE check for multi-instance setup
* proftpd: Add options to override configs (and add a warning if file was overriden)
* proftpd: Allow user auth with ssh keys
@ -28,7 +27,6 @@ The **patch** part changes is incremented if multiple releases happen the same m
* generate-ldif: Support any MariaDB version
* minifirewall: use handlers to restart minifirewall
* openvpn: automate the initialization of the CA and the creation of the server certificate ; use openssl_dhparam module instead of a command
* nagios-nrpe: Add check_domains
* generate-ldif: support any version of MariaDB (instead of only 10.0, 10.1 and 10.3)
* openvpn: Run OpenVPN with the \_openvpn user and group instead of nobody which is originally for NFS
* nagios-nrpe: Upgrade check_mongo

@ -1,325 +0,0 @@
# Vérifie si les domaines listés dans les configurations de Apache,
# Nginx et Haproxy pointent bien sur le serveur.
# Développé par Will
list_domains_path = '/usr/local/sbin/'
excludes_path = '/etc/nagios/domains_exclude.list'
includes_path = '/etc/nagios/domains_include.list'
import os
import sys
import re
import subprocess
import threading
import time
import argparse
import json
#import importlib.machinery
#list_domains = importlib.machinery.SourceFileLoader('', list_domains_path).load_module()
def execute(cmd):
"""Execute Bash command cmd.
Return stdout and stderr as arrays of UTF-8 strings."""
proc = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
stdout_lines = stdout.decode('utf-8').splitlines()
stderr_lines = stderr.decode('utf-8').splitlines()
return stdout_lines, stderr_lines
def get_my_ips():
"""Return localhost IPs."""
stdout, stderr = execute('hostname -I')
if not stdout:
return []
return stdout[0].strip(' \t').split()
def dig(domain):
"""Return dig +short result on domain as a list."""
stdout, stderr = execute('dig +short {}'.format(domain))
return stdout
def strip_comments(string):
"""Return string with any # comment removed."""
return string.split('#')[0]
def list_apache_domains():
"""Return a dict containing :
- key: Apache domain (from command "apache2ctl -D DUMP_VHOSTS").
- value: a list of strings "apache:<VHOST_PATH>:<LINE_IN_BLOCK>"
domains = {}
stdout, stderr = execute('apache2ctl -D DUMP_VHOSTS')
# Apache is not present on the server
return domains
vhost_infos = ''
for line in stdout:
dom = ''
words = line.strip(' \t').split()
if 'namevhost' in line and len(words) >= 5:
# line format: port <PORT> namevhost <DOMAIN> (<VHOST_PATH>:<LINE_IN_BLOCK>)
dom = words[3].strip()
vhost_infos = 'apache:' + words[4].strip('()')
elif 'alias' in line and len(words) >= 2:
# line format: alias <DOMAIN>
dom = words[1].strip() # vhost_infos defined in previous lines
if dom:
if dom not in domains:
domains[dom] = []
if vhost_infos not in domains[dom]:
return domains
def list_nginx_domains():
"""Return a dict containing :
- key: Nginx domain (from command "nginx -T").
- value: a list of strings "nginx:<VHOST_PATH>:<LINE_IN_BLOCK>"
domains = {}
stdout, stderr = execute('nginx -T')
# Nginx is not present on the server
return domains
line_number = 1
config_file_path = ''
for line in stdout:
if '# configuration file' in line:
# line format : # configuration file <PATH>:
words = line.strip(' \t;').split()
config_file_path = words[3].strip(' :')
if 'server_name ' in line:
# TODO: améliorer le if (cas tabulation)
# line format : server_name <DOMAIN1> [<DOMAINS2 ...];
line = strip_comments(line)
words = line.strip(' \t;').split()
for d in words[1:]:
dom = d.strip()
vhost_infos = 'nginx:{}:{}'.format(config_file_path, line_number)
if dom not in domains:
domains[dom] = []
if vhost_infos not in domains[d]:
line_number += 1 # increment line number for next round
if 'server {' in line:
# TODO: améliorer le if (cas plusieurs espaces)
# line format : server {
line_number = 0
return domains
class ResolutionThread(threading.Thread):
def __init__(self, domain):
threading.Thread.__init__(self, daemon=True)
self.domain = domain
self.ips = []
def run(self):
"""Resolve domain with dig."""
dig_results = dig(self.domain)
if not dig_results:
for line in dig_results:
match ='^([0-9abcdef\.:]+)$', line)
if match:
ip =
if ip not in self.ips:
except Exception as e:
def run_check_domains(domains):
"""Check resolution of domains (list)."""
excludes = ['_']
timeout = 5
my_ips = get_my_ips()
domains_noexcludes = [dom for dom in domains if dom not in excludes]
jobs = []
for dom in domains_noexcludes:
t = ResolutionThread(dom)
# Let <timeout> secs to DNS servers to answer in jobs threads
timeout_domains = []
none_domains = []
outside_ips = {}
ok_domains = []
for j in jobs:
if j.is_alive():
if not j.ips:
is_outside = False
for ip in j.ips:
if ip not in my_ips:
is_outside = True
if is_outside:
outside_ips[j.domain] = j.ips
return timeout_domains, none_domains, outside_ips, ok_domains
def output_check_mode(timeout_domains, none_domains, outside_ips, ok_domains):
"""Output result for check mode.
For now, consider everyting as warnings to avoid too much alerts.
n_ok = len(ok_domains)
n_warnings = len(timeout_domains) + len(none_domains) + len(outside_ips)
msg = 'WARNING' if n_warnings else 'OK'
print('{} - 0 UNK / 0 CRIT / {} WARN / {} OK \n'.format(msg, n_warnings, n_ok))
if timeout_domains or none_domains or outside_ips:
for d in timeout_domains:
print('WARNING - timeout resolving {}'.format(d))
for d in none_domains:
print('WARNING - no resolution for {}'.format(d))
for d in outside_ips:
print('WARNING - {} pointing elsewhere ({})'.format(d, ' '.join(outside_ips[d])))
sys.exit(1) if n_warnings else sys.exit(0)
def output_human_mode(doms, timeout_domains, none_domains, outside_ips):
if timeout_domains or none_domains or outside_ips:
if timeout_domains: print('\nTimeouts:')
for d in timeout_domains:
print('\t{} {}'.format(d, ' '.join(doms[d])))
if none_domains: print('\nNo resolution:')
for d in none_domains:
print('\t{} {}'.format(d, ' '.join(doms[d])))
if outside_ips: print('\nPointing elsewhere:')
for d in outside_ips:
print('\t{} {} -> [{}]'.format(d, ' '.join(doms[d]), ' '.join(outside_ips[d])))
print('Domains resolve to right IPs !')
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('action', metavar='ACTION', help='Values: check-dns, list')
parser.add_argument('-o', '--output-style', help='Values: json (default for action list), human (default for action check-dns), nrpe')
parser.add_argument('-a', '--all-domains', action='store_true', help='Include all domains (default).')
parser.add_argument('-ap', '--apache-domains', action='store_true', help='Include Apache domains.')
parser.add_argument('-ng', '--nginx-domains', action='store_true', help='Include Nginx domains.')
parser.add_argument('-ha', '--haproxy-domains', action='store_true', help='Include HaProxy domains (not supported yet).')
args = parser.parse_args()
if args.action not in ['check-dns', 'list']:
if args.output_style == 'nrpe':
print('UNKNOWN - unknown {} action, use -h option for help.'.format(args.action))
print('Unknown {} action, use -h option for help.'.format(args.action))
if not (args.all_domains or args.apache_domains or args.nginx_domains or args.haproxy_domains):
print('Domains scope not specified, looking for all domains.')
args.all_domains = True
doms = {}
if args.all_domains:
if args.apache_domains:
if args.nginx_domains:
if args.haproxy_domains:
print('Option --haproxy-domains not supported yet.')
if not doms:
if args.output_style == 'nrpe':
print('UNKNOWN - No domain found on this server.')
else: # == 'json' or 'human'
print('No domain found on this server.')
if args.action == 'check-dns':
timeout_domains, none_domains, outside_ips, ok_domains = run_check_domains(doms.keys())
if args.output_style == 'nrpe':
output_check_mode(timeout_domains, none_domains, outside_ips, ok_domains)
elif args.output_style == 'json':
print('Option --output-style json not implemented yet for action check-dns.')
else: # args.output_style == 'human'
output_human_mode(doms, timeout_domains, none_domains, outside_ips)
elif args.action == 'list':
if args.output_style == 'nrpe':
print('Action list is not for --output-style nrpe.')
elif args.output_style == 'json':
print(json.dumps(doms, sort_keys=True, indent=4))
print('Option --output-style human not implemented yet for action list, fallback to --output-style json.')
print(json.dumps(doms, sort_keys=True, indent=4))
if __name__ == '__main__':

@ -1,8 +0,0 @@
- name: Copy inspect-domains script to local sbin
dest: /usr/local/sbin/domains
mode: '0700'

@ -12,9 +12,3 @@ Everything is in the `tasks/main.yml` file.
* `nagios_nrpe_force_update_allowed_hosts` : force update list of allowed hosts (default: `False`)
The full list of variables (with default values) can be found in `defaults/main.yml`.
## Available tags
* `nagios-nrpe` : install Nagios and plugins (idempotent)
* `nagios-plugins` : install only plugins (idempotent)

@ -1,14 +0,0 @@
# Check domains using script domains.
# Written by Will
if ! command -v domains >/dev/null; then
echo 'UNKNOWN - Missing dependency domains.'
exit 3
domains -o nrpe -a check-dns

@ -1,25 +0,0 @@
- name: Install check_domains dependency
name: domains
- name: Configure check_domains in /etc/nagios/nrpe.d/evolix.cfg
path: /etc/nagios/nrpe.d/evolix.cfg
regexp: '^command\[check_domains\]='
line: command[check_domains]=sudo {{ nagios_plugins_directory }}/check_domains
notify: restart nagios-nrpe-server
- name: Is evolinux sudoers installed?
path: /etc/sudoers.d/evolinux
register: sudoers_evolinux
- name: Allow nagios user to execute check_domains without sudo password
path: /etc/sudoers.d/evolinux
regexp: 'check_domains'
line: 'nagios ALL = NOPASSWD: {{ nagios_plugins_directory }}/check_domains'
insertafter: '^nagios'
validate: "visudo -cf %s"
when: sudoers_evolinux.stat.exists

@ -22,7 +22,6 @@
- ansible_distribution == "Debian"
- ansible_distribution_major_version is version('10', '>=')
- nagios-nrpe
- nagios-plugins
- name: custom configuration is present

@ -47,7 +47,6 @@ command[check_proxy]=/usr/lib/nagios/plugins/check_http -H {{ nagios_nrpe_check_
command[check_redis]=/usr/lib/nagios/plugins/check_tcp -p 6379
command[check_clamd]=/usr/lib/nagios/plugins/check_clamd -H /var/run/clamav/clamd.ctl -v
command[check_clamav_db]=/usr/lib/nagios/plugins/check_file_age -w 86400 -c 172800 -f /var/lib/clamav/evolix.ndb
command[check_domains]=sudo {{ nagios_plugins_directory }}/check_domains
command[check_ssl]=/usr/lib/nagios/plugins/check_http -f follow -I -S -p 443 -H -C 15,5
command[check_ssl_local]={{ nagios_plugins_directory }}/check_ssl_local
command[check_elasticsearch]=/usr/lib/nagios/plugins/check_http -I -u /_cat/health?h=st -p 9200 -r 'red' --invert-regex