evodomains: implement config files include and exclude domains, and config file to allow external IPs
All checks were successful
gitea/ansible-roles/pipeline/head This commit looks good
All checks were successful
gitea/ansible-roles/pipeline/head This commit looks good
This commit is contained in:
parent
6f178d92ab
commit
c27c4b1698
|
@ -11,9 +11,9 @@
|
||||||
# Developped by Will & Brice
|
# Developped by Will & Brice
|
||||||
#
|
#
|
||||||
|
|
||||||
list_domains_path = '/usr/local/sbin/list_domains.py'
|
|
||||||
excludes_path = '/etc/evolinux/evodomains_exclude.list'
|
excludes_path = '/etc/evolinux/evodomains_exclude.list'
|
||||||
includes_path = '/etc/evolinux/evodomains_include.list'
|
includes_path = '/etc/evolinux/evodomains_include.list'
|
||||||
|
allowed_ips_path = '/etc/evolinux/evodomains_allowed_ips.list'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
@ -24,9 +24,6 @@ import time
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
|
|
||||||
#import importlib.machinery
|
|
||||||
#list_domains = importlib.machinery.SourceFileLoader('list_domains.py', list_domains_path).load_module()
|
|
||||||
|
|
||||||
|
|
||||||
def execute(cmd):
|
def execute(cmd):
|
||||||
"""Execute Bash command cmd.
|
"""Execute Bash command cmd.
|
||||||
|
@ -41,12 +38,20 @@ def execute(cmd):
|
||||||
return stdout_lines, stderr_lines
|
return stdout_lines, stderr_lines
|
||||||
|
|
||||||
|
|
||||||
def get_my_ips():
|
def get_allowed_ips():
|
||||||
"""Return localhost IPs."""
|
"""Return allowed IPs."""
|
||||||
|
|
||||||
stdout, stderr = execute('hostname -I')
|
stdout, stderr = execute('hostname -I')
|
||||||
if not stdout:
|
if not stdout:
|
||||||
return []
|
return []
|
||||||
return stdout[0].strip(' \t').split()
|
ips = stdout[0].strip(' \t\n').split()
|
||||||
|
|
||||||
|
# Other allowed IPs
|
||||||
|
with open(allowed_ips_path, encoding='utf-8') as f:
|
||||||
|
for line in f:
|
||||||
|
ip = strip_comments(line).strip(' \t;')
|
||||||
|
ips.append(ip)
|
||||||
|
return ips
|
||||||
|
|
||||||
|
|
||||||
def dig(domain):
|
def dig(domain):
|
||||||
|
@ -144,7 +149,7 @@ def list_nginx_domains():
|
||||||
return domains
|
return domains
|
||||||
|
|
||||||
|
|
||||||
class ResolutionThread(threading.Thread):
|
class DNSResolutionThread(threading.Thread):
|
||||||
|
|
||||||
def __init__(self, domain):
|
def __init__(self, domain):
|
||||||
threading.Thread.__init__(self, daemon=True)
|
threading.Thread.__init__(self, daemon=True)
|
||||||
|
@ -177,25 +182,32 @@ def run_check_domains(domains):
|
||||||
excludes = ['_']
|
excludes = ['_']
|
||||||
timeout = 5
|
timeout = 5
|
||||||
|
|
||||||
my_ips = get_my_ips()
|
allowed_ips = get_allowed_ips()
|
||||||
|
|
||||||
domains_noexcludes = [dom for dom in domains if dom not in excludes]
|
with open(excludes_path, encoding='utf-8') as f:
|
||||||
|
for line in f:
|
||||||
|
domain = strip_comments(line).strip(' \t\n')
|
||||||
|
if not domain: continue
|
||||||
|
excludes.append(domain)
|
||||||
|
|
||||||
jobs = []
|
jobs = []
|
||||||
for dom in domains_noexcludes:
|
|
||||||
#print(d)
|
|
||||||
t = ResolutionThread(dom)
|
|
||||||
t.start()
|
|
||||||
jobs.append(t)
|
|
||||||
|
|
||||||
# Let <timeout> secs to DNS servers to answer in jobs threads
|
|
||||||
time.sleep(timeout)
|
|
||||||
|
|
||||||
timeout_domains = []
|
timeout_domains = []
|
||||||
none_domains = []
|
none_domains = []
|
||||||
outside_ips = {}
|
outside_ips = {}
|
||||||
ok_domains = []
|
ok_domains = []
|
||||||
|
|
||||||
|
for d in domains:
|
||||||
|
if d in excludes:
|
||||||
|
ok_domains.append(d)
|
||||||
|
continue
|
||||||
|
|
||||||
|
t = DNSResolutionThread(d)
|
||||||
|
t.start()
|
||||||
|
jobs.append(t)
|
||||||
|
|
||||||
|
# Let <timeout> secs to DNS servers to reply to jobs threads queries
|
||||||
|
time.sleep(timeout)
|
||||||
|
|
||||||
for j in jobs:
|
for j in jobs:
|
||||||
if j.is_alive():
|
if j.is_alive():
|
||||||
timeout_domains.append(j.domain)
|
timeout_domains.append(j.domain)
|
||||||
|
@ -207,7 +219,7 @@ def run_check_domains(domains):
|
||||||
|
|
||||||
is_outside = False
|
is_outside = False
|
||||||
for ip in j.ips:
|
for ip in j.ips:
|
||||||
if ip not in my_ips:
|
if ip not in allowed_ips:
|
||||||
is_outside = True
|
is_outside = True
|
||||||
break
|
break
|
||||||
if is_outside:
|
if is_outside:
|
||||||
|
@ -218,7 +230,7 @@ def run_check_domains(domains):
|
||||||
return timeout_domains, none_domains, outside_ips, ok_domains
|
return timeout_domains, none_domains, outside_ips, ok_domains
|
||||||
|
|
||||||
|
|
||||||
def output_check_mode(timeout_domains, none_domains, outside_ips, ok_domains):
|
def output_nrpe_mode(timeout_domains, none_domains, outside_ips, ok_domains):
|
||||||
"""Output result for check mode.
|
"""Output result for check mode.
|
||||||
For now, consider everyting as warnings to avoid too much alerts.
|
For now, consider everyting as warnings to avoid too much alerts.
|
||||||
"""
|
"""
|
||||||
|
@ -302,10 +314,22 @@ def main(argv):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if args.action == 'check-dns':
|
if args.action == 'check-dns':
|
||||||
|
|
||||||
|
# Add included domains to domains dict
|
||||||
|
with open(includes_path, encoding='utf-8') as f:
|
||||||
|
line_number = 0
|
||||||
|
for line in f:
|
||||||
|
line_number += 1
|
||||||
|
domain = strip_comments(line).strip(' \t\n')
|
||||||
|
if not domain: continue
|
||||||
|
if domain not in doms:
|
||||||
|
doms[domain] = []
|
||||||
|
doms[domain].append('evodomains:{}:{}'.format(includes_path, line_number))
|
||||||
|
|
||||||
timeout_domains, none_domains, outside_ips, ok_domains = run_check_domains(doms.keys())
|
timeout_domains, none_domains, outside_ips, ok_domains = run_check_domains(doms.keys())
|
||||||
|
|
||||||
if args.output_style == 'nrpe':
|
if args.output_style == 'nrpe':
|
||||||
output_check_mode(timeout_domains, none_domains, outside_ips, ok_domains)
|
output_nrpe_mode(timeout_domains, none_domains, outside_ips, ok_domains)
|
||||||
|
|
||||||
elif args.output_style == 'json':
|
elif args.output_style == 'json':
|
||||||
print('Option --output-style json not implemented yet for action check-dns.')
|
print('Option --output-style json not implemented yet for action check-dns.')
|
||||||
|
@ -314,6 +338,7 @@ def main(argv):
|
||||||
output_human_mode(doms, timeout_domains, none_domains, outside_ips)
|
output_human_mode(doms, timeout_domains, none_domains, outside_ips)
|
||||||
|
|
||||||
elif args.action == 'list':
|
elif args.action == 'list':
|
||||||
|
# Note: do not use evodomains include and exclude lists for listing.
|
||||||
|
|
||||||
if args.output_style == 'nrpe':
|
if args.output_style == 'nrpe':
|
||||||
print('Action list is not for --output-style nrpe.')
|
print('Action list is not for --output-style nrpe.')
|
||||||
|
@ -325,6 +350,13 @@ def main(argv):
|
||||||
print('Option --output-style human not implemented yet for action list, fallback to --output-style json.')
|
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))
|
print(json.dumps(doms, sort_keys=True, indent=4))
|
||||||
|
|
||||||
|
#elif args.action == 'brice_action':
|
||||||
|
# #doms est un dict avec le nom de domaine comme clé, pour voir la structure de données :
|
||||||
|
# # evodomains --output-style json list
|
||||||
|
#
|
||||||
|
# print(doms)
|
||||||
|
# brice_function(doms)
|
||||||
|
#
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main(sys.argv[1:])
|
main(sys.argv[1:])
|
||||||
|
|
|
@ -4,5 +4,40 @@
|
||||||
dest: /usr/local/sbin/evodomains
|
dest: /usr/local/sbin/evodomains
|
||||||
mode: '0700'
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Create config file 'evodomains_exclude.list'
|
||||||
|
ansible.builtin.blockinfile:
|
||||||
|
path: /etc/evolinux/evodomains_exclude.list
|
||||||
|
create: true
|
||||||
|
marker: "### {mark} ANSIBLE MANAGED HEADER"
|
||||||
|
insertbefore: BOF
|
||||||
|
block: |
|
||||||
|
# Domains present in vhosts or SSL certificates whose DNS records should
|
||||||
|
# not be checked by 'evodomains --check-dns'.
|
||||||
|
# Note: custom record IPs can also be added to /etc/evolinux/evodomains_allowed_ips.list,
|
||||||
|
# this is useful for load-balanced domains or NAT.
|
||||||
|
# Format: one domain per line, regex and wildcards not supported.
|
||||||
|
|
||||||
|
- name: Create config file 'evodomains_include.list'
|
||||||
|
ansible.builtin.blockinfile:
|
||||||
|
path: /etc/evolinux/evodomains_include.list
|
||||||
|
create: true
|
||||||
|
marker: "### {mark} ANSIBLE MANAGED HEADER"
|
||||||
|
insertbefore: BOF
|
||||||
|
block: |
|
||||||
|
# Domains absent from vhosts or SSL certificates whose DNS records must
|
||||||
|
# be checked by 'evodomains --check-dns'.
|
||||||
|
# Format: one domain per line, regex and wildcards not supported.
|
||||||
|
|
||||||
|
- name: Create config file 'evodomains_allowed_ips.list'
|
||||||
|
ansible.builtin.blockinfile:
|
||||||
|
path: /etc/evolinux/evodomains_allowed_ips.list
|
||||||
|
create: true
|
||||||
|
marker: "### {mark} ANSIBLE MANAGED HEADER"
|
||||||
|
insertbefore: BOF
|
||||||
|
block: |
|
||||||
|
# External IPs the domains of this server are allowed to point for
|
||||||
|
# 'evodomains --check-dns'.
|
||||||
|
# This is useful for load-balanced domains or NAT.
|
||||||
|
# Note: the network interfaces IPs of the server are allowed by default.
|
||||||
|
# Format: one IP per line, regex and wildcards not supported.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue