Update icinga2_server role
This commit is contained in:
parent
36eb8aa939
commit
c10b6ab95c
|
@ -74,6 +74,7 @@ icinga2_server_api_users:
|
||||||
|
|
||||||
icinga2_server_icingaweb2_main_user: john
|
icinga2_server_icingaweb2_main_user: john
|
||||||
icinga2_server_icingaweb2_main_user_password: needToBeChanged
|
icinga2_server_icingaweb2_main_user_password: needToBeChanged
|
||||||
|
icinga2_server_icingaweb2_main_user_email: "needToBeChange@example.org"
|
||||||
icinga2_server_apache2_service: apache2
|
icinga2_server_apache2_service: apache2
|
||||||
icinga2_server_apache2_default_index: "/var/www/html/index.html"
|
icinga2_server_apache2_default_index: "/var/www/html/index.html"
|
||||||
icinga2_server_apache2_user: "www-data"
|
icinga2_server_apache2_user: "www-data"
|
||||||
|
@ -86,3 +87,7 @@ icinga2_server_apache2_modules_to_disable:
|
||||||
- negociation
|
- negociation
|
||||||
|
|
||||||
icinga2_server_icingaweb2_main_user_password_hash_manual: needToBeChanged
|
icinga2_server_icingaweb2_main_user_password_hash_manual: needToBeChanged
|
||||||
|
icinga2_server_ticket_salt: ""
|
||||||
|
icinga2_server_custom_hostgroup: wirebrass
|
||||||
|
|
||||||
|
icinga2_server_nagios_plugins_location: "/usr/lib/nagios/plugins/"
|
||||||
|
|
440
roles/icinga2_server/files/check_dane
Normal file
440
roles/icinga2_server/files/check_dane
Normal file
|
@ -0,0 +1,440 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2014-2016 Felix Geyer <debfx@fobos.de>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 2 or (at your option)
|
||||||
|
# version 3 of the License.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import datetime
|
||||||
|
import dns.exception
|
||||||
|
import dns.flags
|
||||||
|
import dns.rdatatype
|
||||||
|
import dns.rdtypes.ANY.TLSA
|
||||||
|
import dns.resolver
|
||||||
|
import hashlib
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import ssl
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
VERSION = "1.1"
|
||||||
|
|
||||||
|
|
||||||
|
class ProtocolError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def nagios_ok(msg: str) -> None:
|
||||||
|
print("DANE OK - " + msg)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def nagios_warning(msg: str) -> None:
|
||||||
|
print("DANE WARNING - " + msg)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def nagios_critical(msg: str) -> None:
|
||||||
|
print("DANE CRITICAL - " + msg)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
|
def nagios_unknown(msg: str) -> None:
|
||||||
|
print("DANE UNKONWN - " + msg)
|
||||||
|
sys.exit(3)
|
||||||
|
|
||||||
|
|
||||||
|
def create_resolver(dnssec: bool = True,
|
||||||
|
timeout: int = None,
|
||||||
|
nameserver: str = None) -> dns.resolver.Resolver:
|
||||||
|
resolver = dns.resolver.Resolver()
|
||||||
|
|
||||||
|
if timeout and timeout != 0:
|
||||||
|
resolver.lifetime = timeout
|
||||||
|
|
||||||
|
if nameserver:
|
||||||
|
resolver.nameservers = [nameserver]
|
||||||
|
|
||||||
|
if dnssec:
|
||||||
|
resolver.edns = 0
|
||||||
|
resolver.payload = 1280
|
||||||
|
resolver.ednsflags = dns.flags.DO
|
||||||
|
|
||||||
|
return resolver
|
||||||
|
|
||||||
|
|
||||||
|
def check_dns_response_auth(response: dns.resolver.Answer) -> bool:
|
||||||
|
if response.response.flags & dns.flags.AD:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def extract_pubkey(cert_binary: bytes) -> bytes:
|
||||||
|
# should really be done with a python 3 module that exposes this openssl api
|
||||||
|
|
||||||
|
# extract public key in pem format
|
||||||
|
pubkey_pem = subprocess.check_output(["openssl", "x509", "-pubkey", "-inform", "der", "-noout"], input=cert_binary)
|
||||||
|
# conver to binary / der format
|
||||||
|
pubkey_binary = subprocess.check_output(["openssl", "pkey", "-pubin", "-outform", "der"], input=pubkey_pem)
|
||||||
|
|
||||||
|
return pubkey_binary
|
||||||
|
|
||||||
|
|
||||||
|
def get_tlsa_records(args: argparse.Namespace) -> dns.resolver.Answer:
|
||||||
|
resolver = create_resolver(dnssec=args.dnssec, timeout=args.timeout, nameserver=args.nameserver)
|
||||||
|
|
||||||
|
tlsa_domain = "_{}._tcp.{}".format(args.port, args.host)
|
||||||
|
|
||||||
|
try:
|
||||||
|
tlsa_records = resolver.query(tlsa_domain, dns.rdatatype.TLSA)
|
||||||
|
except dns.resolver.NXDOMAIN:
|
||||||
|
nagios_critical("No DNS TLSA record found: {}".format(tlsa_domain))
|
||||||
|
except dns.exception.Timeout:
|
||||||
|
nagios_unknown("DNS query timeout: {}".format(tlsa_domain))
|
||||||
|
|
||||||
|
if args.dnssec and not check_dns_response_auth(tlsa_records):
|
||||||
|
nagios_unknown("DNS query not DNSSEC validated")
|
||||||
|
|
||||||
|
return tlsa_records
|
||||||
|
|
||||||
|
|
||||||
|
def validate_dane(cert_binary: bytes,
|
||||||
|
pkix_valid: bool,
|
||||||
|
tlsa_record: dns.rdtypes.ANY.TLSA.TLSA) -> bool:
|
||||||
|
if tlsa_record.usage == 3:
|
||||||
|
pass
|
||||||
|
elif tlsa_record.usage == 1 and pkix_valid:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# usage=2 unsupported
|
||||||
|
return False
|
||||||
|
|
||||||
|
if tlsa_record.selector == 0:
|
||||||
|
data = cert_binary
|
||||||
|
elif tlsa_record.selector == 1:
|
||||||
|
data = extract_pubkey(cert_binary)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if tlsa_record.mtype == 0:
|
||||||
|
hashed = data
|
||||||
|
elif tlsa_record.mtype == 1:
|
||||||
|
hashed = hashlib.sha256(data).digest()
|
||||||
|
elif tlsa_record.mtype == 2:
|
||||||
|
hashed = hashlib.sha512(data).digest()
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return hashed == tlsa_record.cert
|
||||||
|
|
||||||
|
|
||||||
|
def check_cert_expiry(args: argparse.Namespace,
|
||||||
|
cert: dict,
|
||||||
|
days_warning: int,
|
||||||
|
days_critical: int = None) -> datetime.timedelta:
|
||||||
|
not_after = datetime.datetime.strptime(cert["notAfter"], "%b %d %H:%M:%S %Y %Z")
|
||||||
|
date_diff = not_after - datetime.datetime.now()
|
||||||
|
|
||||||
|
if days_critical:
|
||||||
|
if date_diff <= datetime.timedelta(days_critical):
|
||||||
|
nagios_critical("{}:{} cert expires in {} days".format(args.host, args.port, date_diff.days))
|
||||||
|
|
||||||
|
if date_diff <= datetime.timedelta(days_warning):
|
||||||
|
nagios_warning("{}:{} cert expires in {} days".format(args.host, args.port, date_diff.days))
|
||||||
|
|
||||||
|
return date_diff
|
||||||
|
|
||||||
|
|
||||||
|
def connect_to_host(connect_host: str,
|
||||||
|
connect_port: int,
|
||||||
|
args: argparse.Namespace,
|
||||||
|
check_cert: bool) -> ssl.SSLSocket:
|
||||||
|
if args.timeout == 0:
|
||||||
|
socket.setdefaulttimeout(None)
|
||||||
|
else:
|
||||||
|
socket.setdefaulttimeout(args.timeout)
|
||||||
|
|
||||||
|
context = ssl.create_default_context()
|
||||||
|
if not check_cert:
|
||||||
|
context.check_hostname = False
|
||||||
|
context.verify_mode = ssl.CERT_NONE
|
||||||
|
|
||||||
|
# TODO: use our resolver
|
||||||
|
try:
|
||||||
|
sock = socket.create_connection((connect_host, connect_port))
|
||||||
|
except OSError as e:
|
||||||
|
nagios_unknown("Can't establish a connection to {}:{}:\n{}"
|
||||||
|
.format(connect_host, connect_port, str(e)))
|
||||||
|
|
||||||
|
peername = sock.getpeername()[0]
|
||||||
|
if ":" in peername:
|
||||||
|
peername = "[{}]".format(peername)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if args.starttls == "smtp":
|
||||||
|
connect_smtp(sock)
|
||||||
|
elif args.starttls == "ftp":
|
||||||
|
connect_ftp(sock)
|
||||||
|
elif args.starttls == "imap":
|
||||||
|
connect_imap(sock)
|
||||||
|
elif args.starttls == "xmpp":
|
||||||
|
connect_xmpp(sock, args.host)
|
||||||
|
elif args.starttls == "quassel":
|
||||||
|
connect_quassel(sock, args.host)
|
||||||
|
except (ProtocolError, OSError) as e:
|
||||||
|
nagios_unknown("Failed to initiate STARTTLS to {} ({}:{}):\n{}"
|
||||||
|
.format(connect_host, peername, connect_port, str(e)))
|
||||||
|
|
||||||
|
try:
|
||||||
|
return context.wrap_socket(sock, server_hostname=args.host)
|
||||||
|
except (ProtocolError, ssl.SSLError, OSError) as e:
|
||||||
|
if isinstance(e, ssl.SSLError) and e.reason == "CERTIFICATE_VERIFY_FAILED":
|
||||||
|
# pass exceptions concerning certificate validation to the caller
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
nagios_unknown("Can't establish a TLS connection to {} ({}:{}):\n{}"
|
||||||
|
.format(connect_host, peername, connect_port, str(e)))
|
||||||
|
|
||||||
|
|
||||||
|
def smtp_read_response(sock: socket.socket) -> str:
|
||||||
|
response = ""
|
||||||
|
line_end = False
|
||||||
|
while not line_end:
|
||||||
|
line = sock.recv(1024)
|
||||||
|
response += line.decode("ASCII")
|
||||||
|
if len(line) < 4 or line[3] != "-":
|
||||||
|
line_end = True
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def connect_smtp(sock: socket.socket) -> None:
|
||||||
|
smtp_read_response(sock)
|
||||||
|
sock.sendall(b"EHLO openssl.client.net\r\n")
|
||||||
|
|
||||||
|
response = smtp_read_response(sock)
|
||||||
|
if "STARTTLS" not in response:
|
||||||
|
raise ProtocolError("Server doesn't support STARTTLS")
|
||||||
|
|
||||||
|
sock.sendall(b"STARTTLS\r\n")
|
||||||
|
|
||||||
|
smtp_read_response(sock)
|
||||||
|
|
||||||
|
|
||||||
|
def connect_ftp(sock: socket.socket) -> None:
|
||||||
|
buf = sock.recv(1024)
|
||||||
|
|
||||||
|
sock.sendall(b"AUTH TLS\r\n")
|
||||||
|
|
||||||
|
response = sock.recv(1024).decode("ASCII").strip("\r\n\t ")
|
||||||
|
if not re.search(r"^2\d\d", response):
|
||||||
|
raise ProtocolError("Server doesn't support STARTTLS ({})".format(response))
|
||||||
|
|
||||||
|
|
||||||
|
def connect_imap(sock: socket.socket) -> None:
|
||||||
|
sock.recv(1024)
|
||||||
|
sock.sendall(b". CAPABILITY\n")
|
||||||
|
|
||||||
|
response = smtp_read_response(sock)
|
||||||
|
if "STARTTLS" not in response:
|
||||||
|
raise ProtocolError("Server doesn't support STARTTLS")
|
||||||
|
|
||||||
|
sock.sendall(b". STARTTLS\n")
|
||||||
|
|
||||||
|
smtp_read_response(sock)
|
||||||
|
|
||||||
|
|
||||||
|
def connect_xmpp(sock: socket.socket, host: str) -> None:
|
||||||
|
sock.sendall("<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "
|
||||||
|
"xmlns='jabber:client' to='{}' version='1.0'>".format(host).encode("ASCII"))
|
||||||
|
|
||||||
|
buf = sock.recv(1024)
|
||||||
|
if "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'" not in buf.decode("ASCII"):
|
||||||
|
raise ProtocolError("Server doesn't support STARTTLS")
|
||||||
|
|
||||||
|
sock.sendall(b"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>")
|
||||||
|
|
||||||
|
buf = sock.recv(1024)
|
||||||
|
if "<proceed" not in buf.decode("ASCII"):
|
||||||
|
raise ProtocolError("Server doesn't support STARTTLS")
|
||||||
|
|
||||||
|
|
||||||
|
def connect_quassel(sock: socket.socket, host: str) -> None:
|
||||||
|
MAGIC = 0x42b33f00
|
||||||
|
FEATURE_ENCRYPTION = 0x1
|
||||||
|
PROTOCOL_DATAGRAM = 0x2
|
||||||
|
PROTOCOL_END = (0x1 << 31)
|
||||||
|
|
||||||
|
sock.sendall(struct.pack("!I", MAGIC | FEATURE_ENCRYPTION))
|
||||||
|
sock.sendall(struct.pack("!I", PROTOCOL_DATAGRAM | PROTOCOL_END))
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = struct.unpack("!I", sock.recv(4))[0]
|
||||||
|
except struct.error:
|
||||||
|
raise ProtocolError("No valid response from server")
|
||||||
|
|
||||||
|
protocol_type = (response & 0xff)
|
||||||
|
connection_features = (response >> 24)
|
||||||
|
|
||||||
|
if not (protocol_type & PROTOCOL_DATAGRAM):
|
||||||
|
raise ProtocolError("Server doesn't support the protocol")
|
||||||
|
|
||||||
|
if not (connection_features & FEATURE_ENCRYPTION):
|
||||||
|
raise ProtocolError("Server doesn't support TLS")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser(description=""" Nagios/Icinga plugin for checking DANE/TLSA records.
|
||||||
|
It compares the DANE/TLSA record against the TLS certificate provided
|
||||||
|
by a service.""")
|
||||||
|
|
||||||
|
parser.add_argument("--host", "-H", dest="host", required=True, help="Hostname to check.")
|
||||||
|
parser.add_argument("--port", "-p", type=int, required=True, help="TCP port to check.")
|
||||||
|
parser.add_argument("--connect-host", "--ip", "-I", dest="connect_host",
|
||||||
|
help="Connect to this host instead of --host.")
|
||||||
|
parser.add_argument("--connect-port", dest="connect_port", help="Connect to this port instead of --port.")
|
||||||
|
parser.add_argument("--starttls",
|
||||||
|
choices=["smtp", "ftp", "imap", "xmpp", "quassel"],
|
||||||
|
help="Send the protocol-specific messages to enable TLS.")
|
||||||
|
parser = argparse.ArgumentParser(description=""" Nagios/Icinga plugin for checking DANE/TLSA records.
|
||||||
|
It compares the DANE/TLSA record against the TLS certificate provided
|
||||||
|
by a service.""")
|
||||||
|
|
||||||
|
parser.add_argument("--host", "-H", dest="host", required=True, help="Hostname to check.")
|
||||||
|
parser.add_argument("--port", "-p", type=int, required=True, help="TCP port to check.")
|
||||||
|
parser.add_argument("--connect-host", "--ip", "-I", dest="connect_host",
|
||||||
|
help="Connect to this host instead of --host.")
|
||||||
|
parser.add_argument("--connect-port", dest="connect_port", help="Connect to this port instead of --port.")
|
||||||
|
parser.add_argument("--starttls",
|
||||||
|
choices=["smtp", "ftp", "imap", "xmpp", "quassel"],
|
||||||
|
help="Send the protocol-specific messages to enable TLS.")
|
||||||
|
parser.add_argument("--check-pkix", action="store_true",
|
||||||
|
help="Additionally perform traditional checks on the certificate "
|
||||||
|
"(ca trust path, hostname, expiry).")
|
||||||
|
parser.add_argument("--min-days-valid", help="Minimum number of days a certificate has to be valid. "
|
||||||
|
"Format: INTEGER[,INTEGER]. "
|
||||||
|
"1st is #days for warning, 2nd is critical.")
|
||||||
|
parser.add_argument("--no-dnssec", dest="dnssec", action="store_false",
|
||||||
|
help="Continue even when DNS replies aren't DNSSEC authenticated.")
|
||||||
|
parser.add_argument("--nameserver", help="Use a custom nameserver.")
|
||||||
|
parser.add_argument("--timeout", type=int, default=10, help="Network timeout in sec. Default: 10")
|
||||||
|
parser.add_argument("--version", action="version", version="%(prog)s " + VERSION)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
pyver = sys.version_info
|
||||||
|
if pyver[0] < 3 or (pyver[0] == 3 and pyver[1] < 4):
|
||||||
|
nagios_unknown("check_dane requires Python >= 3.4")
|
||||||
|
|
||||||
|
if args.port < 1 or args.port > 65535:
|
||||||
|
nagios_unknown("Invalid port")
|
||||||
|
|
||||||
|
if args.min_days_valid and not re.search(r"^\d+(,\d+)?$", args.min_days_valid):
|
||||||
|
nagios_unknown("--check-cert-expire takes INTEGER[,INTEGER] as arguments")
|
||||||
|
|
||||||
|
if args.timeout < 0:
|
||||||
|
nagios_unknown("Invalid timeout argument")
|
||||||
|
|
||||||
|
if args.connect_host:
|
||||||
|
connect_host = args.connect_host
|
||||||
|
else:
|
||||||
|
connect_host = args.host
|
||||||
|
|
||||||
|
if args.connect_port:
|
||||||
|
connect_port = args.connect_port
|
||||||
|
else:
|
||||||
|
connect_port = args.port
|
||||||
|
|
||||||
|
tlsa_records = get_tlsa_records(args)
|
||||||
|
|
||||||
|
has_usage1_tlsa = False
|
||||||
|
for record in tlsa_records:
|
||||||
|
if record.usage == 1:
|
||||||
|
has_usage1_tlsa = True
|
||||||
|
break
|
||||||
|
|
||||||
|
initial_check_pkix = (args.check_pkix or has_usage1_tlsa)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# validate against PKIX if manually requested or we've found a usage=1 tlsa record
|
||||||
|
ssl_sock = connect_to_host(connect_host, connect_port, args, initial_check_pkix)
|
||||||
|
pkix_valid = initial_check_pkix
|
||||||
|
except (ssl.CertificateError, ssl.SSLError) as e:
|
||||||
|
if args.check_pkix:
|
||||||
|
nagios_critical(str(e))
|
||||||
|
else:
|
||||||
|
ssl_sock = connect_to_host(connect_host, connect_port, args, False)
|
||||||
|
pkix_valid = False
|
||||||
|
pkix_error = str(e)
|
||||||
|
|
||||||
|
cert_binary = ssl_sock.getpeercert(binary_form=True)
|
||||||
|
cert_dict = ssl_sock.getpeercert()
|
||||||
|
ssl_sock.close()
|
||||||
|
|
||||||
|
dane_valid_cert = False
|
||||||
|
|
||||||
|
for tlsa in tlsa_records:
|
||||||
|
if validate_dane(cert_binary, pkix_valid, tlsa):
|
||||||
|
dane_valid_cert = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not dane_valid_cert:
|
||||||
|
# test if it would match if it were pkix_valid
|
||||||
|
additional_msg = ""
|
||||||
|
for tlsa in tlsa_records:
|
||||||
|
if validate_dane(cert_binary, True, tlsa):
|
||||||
|
additional_msg = "\nIt matches a TLSA usage=1 record but fails PKIX validation:\n" + pkix_error
|
||||||
|
break
|
||||||
|
|
||||||
|
nagios_critical("Certificate doesn't match TLSA record" + additional_msg)
|
||||||
|
|
||||||
|
if pkix_valid and args.min_days_valid:
|
||||||
|
days_parts = args.min_days_valid.split(",")
|
||||||
|
|
||||||
|
if len(days_parts) == 2:
|
||||||
|
timedelta_valid = check_cert_expiry(args, cert_dict, int(days_parts[0]), int(days_parts[1]))
|
||||||
|
else:
|
||||||
|
timedelta_valid = check_cert_expiry(args, cert_dict, int(days_parts[0]))
|
||||||
|
|
||||||
|
expire_str = ", expires in {} days".format(timedelta_valid.days)
|
||||||
|
else:
|
||||||
|
expire_str = ""
|
||||||
|
|
||||||
|
message = "{}:{} cert matches TLSA record".format(args.host, args.port)
|
||||||
|
if not args.dnssec:
|
||||||
|
message += " (DNSSEC not validated)"
|
||||||
|
message += expire_str
|
||||||
|
|
||||||
|
nagios_ok(message)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
message = "{}:{} cert matches TLSA record".format(args.host, args.port)
|
||||||
|
if not args.dnssec:
|
||||||
|
message += " (DNSSEC not validated)"
|
||||||
|
message += expire_str
|
||||||
|
|
||||||
|
nagios_ok(message)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
# kate: space-indent on; indent-width 4;
|
||||||
|
|
187
roles/icinga2_server/files/check_openvpn
Normal file
187
roles/icinga2_server/files/check_openvpn
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Check if an OpenVPN server runs on a given UDP or TCP port.
|
||||||
|
#
|
||||||
|
# Copyright 2013 Roland Wolters
|
||||||
|
# Copyright 2016 Alarig Le Lay
|
||||||
|
#
|
||||||
|
# Version 20160803
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
# a copy of this software and associated documentation files (the
|
||||||
|
# "Software"), to deal in the Software without restriction, including
|
||||||
|
# without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
# permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
# the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import hmac
|
||||||
|
import hashlib
|
||||||
|
import struct
|
||||||
|
import socket
|
||||||
|
import argparse
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
HMAC_CLIENT_KEY_START = 192
|
||||||
|
BUFFER_SIZE = 1024
|
||||||
|
|
||||||
|
ALGORITHMS_AVAILABLE = hashlib.algorithms_available \
|
||||||
|
if hasattr(hashlib, "algorithms_available") else hashlib.algorithms
|
||||||
|
|
||||||
|
def ok(msg):
|
||||||
|
print('OK: %s' % msg)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def critical(msg):
|
||||||
|
print('CRIT: %s' % msg)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def buildpacket(tcp, key, digestmod):
|
||||||
|
packet = 1
|
||||||
|
ts = int(time.time())
|
||||||
|
session = os.urandom(8)
|
||||||
|
|
||||||
|
if key:
|
||||||
|
# hmac
|
||||||
|
h = hmac.new(key, digestmod=digestmod)
|
||||||
|
h.update(struct.pack('>I', packet)) # packet id
|
||||||
|
h.update(struct.pack('>I', ts)) # net time
|
||||||
|
h.update(b'\x38') # type
|
||||||
|
h.update(session) # session id
|
||||||
|
h.update(struct.pack('>B', 0)) # message packet id array length
|
||||||
|
h.update(struct.pack('>I', 0)) # message packet id
|
||||||
|
|
||||||
|
# packet
|
||||||
|
result = b''
|
||||||
|
result += b'\x38' # type
|
||||||
|
result += session # session id
|
||||||
|
if key: result += h.digest() # hmac
|
||||||
|
result += struct.pack('>I', packet) # packet id
|
||||||
|
result += struct.pack('>I', ts) # net time
|
||||||
|
result += struct.pack('>B', 0) # message packet id array length
|
||||||
|
result += struct.pack('>I', 0) # message packet id
|
||||||
|
if tcp: result = struct.pack('>H', len(result)) + result
|
||||||
|
return result
|
||||||
|
|
||||||
|
def checkserver(host, port, tcp, timeout, key, digest):
|
||||||
|
packet = buildpacket(tcp, key, digest)
|
||||||
|
check = checkserver_tcp if tcp else checkserver_udp
|
||||||
|
return check(host, port, timeout, packet)
|
||||||
|
|
||||||
|
def checkserver_udp(host, port, timeout, packet):
|
||||||
|
# thanks to glucas for the idea
|
||||||
|
try:
|
||||||
|
af, socktype, proto, canonname, sa = socket.getaddrinfo(host, port, \
|
||||||
|
socket.AF_UNSPEC, socket.SOCK_DGRAM)[0]
|
||||||
|
s = socket.socket(af, socktype, proto)
|
||||||
|
s.settimeout(timeout)
|
||||||
|
except socket.error:
|
||||||
|
return critical('Unable to create UDP socket')
|
||||||
|
|
||||||
|
try:
|
||||||
|
s.sendto(packet, (host, port))
|
||||||
|
data, _ = s.recvfrom(BUFFER_SIZE)
|
||||||
|
reply = binascii.hexlify(data)
|
||||||
|
return ok('OpenVPN UDP server response (hex): %s' % reply)
|
||||||
|
except:
|
||||||
|
return critical('OpenVPN UDP server not responding')
|
||||||
|
finally:
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
def checkserver_tcp(host, port, timeout, packet):
|
||||||
|
try:
|
||||||
|
af, socktype, proto, canonname, sa = socket.getaddrinfo(host, port, \
|
||||||
|
socket.AF_UNSPEC, socket.SOCK_STREAM)[0]
|
||||||
|
s = socket.socket(af, socktype, proto)
|
||||||
|
s.settimeout(timeout)
|
||||||
|
except socket.error:
|
||||||
|
return critical('Unable to create TCP socket')
|
||||||
|
|
||||||
|
try:
|
||||||
|
s.connect((host, port))
|
||||||
|
s.send(packet)
|
||||||
|
data = s.recv(BUFFER_SIZE)
|
||||||
|
if len(data) <= 0: raise RuntimeError
|
||||||
|
reply = binascii.hexlify(data)
|
||||||
|
return ok('OpenVPN TCP server response (hex): %s' % reply)
|
||||||
|
except:
|
||||||
|
return critical('OpenVPN TCP server not responding')
|
||||||
|
finally:
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
def readkey(path):
|
||||||
|
key = None
|
||||||
|
try:
|
||||||
|
with open(path, 'r') as myfile: key = myfile.read()
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
index_start = key.find('-\n');
|
||||||
|
index_end = key.find('\n-', index_start);
|
||||||
|
if index_start < 0 or index_end < 0 or index_end <= index_start:
|
||||||
|
return None
|
||||||
|
index_start += 2
|
||||||
|
key = key[index_start:index_end].replace('\n', '').replace('\r', '')
|
||||||
|
return key
|
||||||
|
|
||||||
|
def optionsparser(argv=None):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-p', '--port', help='set port number (default is %(default)d)', type=int, default=1194)
|
||||||
|
parser.add_argument('-t', '--tcp', help='use tcp instead of udp', action='store_true')
|
||||||
|
parser.add_argument('--timeout', help='set timeout (default is %(default)d)', type=int, default=5)
|
||||||
|
parser.add_argument('--digest', help='set HMAC digest (default is "%(default)s")', default='sha1')
|
||||||
|
parser.add_argument('--digest-size', help='set HMAC digest size', type=int)
|
||||||
|
parser.add_argument('--digest-key', help='set HMAC key')
|
||||||
|
parser.add_argument('--tls-auth', help='set tls-auth file')
|
||||||
|
parser.add_argument('host', help='the OpenVPN host name or IP')
|
||||||
|
return parser.parse_args(argv)
|
||||||
|
|
||||||
|
def main(argv=None):
|
||||||
|
args = optionsparser(argv)
|
||||||
|
|
||||||
|
if args.digest_size and args.digest_size < 0:
|
||||||
|
critical('digest size must be positive')
|
||||||
|
if args.tls_auth and args.digest_key:
|
||||||
|
critical('--tls-auth cannot go with --digest-key')
|
||||||
|
|
||||||
|
key = args.digest_key
|
||||||
|
digest = args.digest
|
||||||
|
digest_size = args.digest_size
|
||||||
|
|
||||||
|
digest = digest.lower()
|
||||||
|
if digest not in ALGORITHMS_AVAILABLE:
|
||||||
|
return critical('digest not available')
|
||||||
|
try:
|
||||||
|
digest = getattr(hashlib, digest)
|
||||||
|
if not digest_size: digest_size = digest().digest_size
|
||||||
|
except:
|
||||||
|
return critical('digest creation failed')
|
||||||
|
|
||||||
|
if args.tls_auth:
|
||||||
|
key = readkey(args.tls_auth)
|
||||||
|
if key == None: return critical('cannot read tls auth file')
|
||||||
|
index_start = HMAC_CLIENT_KEY_START * 2
|
||||||
|
index_end = (HMAC_CLIENT_KEY_START + digest_size) * 2
|
||||||
|
key = key[index_start:index_end]
|
||||||
|
|
||||||
|
if key: key = binascii.unhexlify(key)
|
||||||
|
|
||||||
|
return checkserver(args.host, args.port, args.tcp, args.timeout, key, digest)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
code = main()
|
||||||
|
sys.exit(code)
|
||||||
|
|
144
roles/icinga2_server/files/check_rdns
Normal file
144
roles/icinga2_server/files/check_rdns
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Copyright (c) 2013 Stefan Huber <shuber@sthu.org>
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person
|
||||||
|
# obtaining a copy of this software and associated documentation
|
||||||
|
# files (the "Software"), to deal in the Software without
|
||||||
|
# restriction, including without limitation the rights to use,
|
||||||
|
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the
|
||||||
|
# Software is furnished to do so, subject to the following
|
||||||
|
# conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
# OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
. $(dirname $0)/utils.sh
|
||||||
|
|
||||||
|
|
||||||
|
PROGNAME=$(basename $0)
|
||||||
|
REVISION="0.1"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
check_rdns v$REVISION
|
||||||
|
Copyright (c) 2013 Stefan Huber <shuber@sthu.org>
|
||||||
|
|
||||||
|
Usage: $PROGNAME -H ip-address [OPTIONS]
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
-H, --address IP-address The ip-addres on which reverse-DNS is performed.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Print this text.
|
||||||
|
-a, --expect=HOST The expected result.
|
||||||
|
-s, --server=HOST The DNS server to contact.
|
||||||
|
-t, --timeout=SEC Seconds before lookup times out. (Default: 10)
|
||||||
|
-w, --warning=MSEC Return warning if lookup time exceeds value.
|
||||||
|
-c, --critical=MSEC Return critical if lookup time exceeds value.
|
||||||
|
-V, --version Print version info.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEMP=`getopt -o "H:a:c:hs:t:w:V" --long "help,address:,expect:,critical:,server:,timeout:,warning:,version" -n "$PROGNAME" -- "$@"`
|
||||||
|
eval set - "$TEMP"
|
||||||
|
|
||||||
|
ADDRESS=
|
||||||
|
EXPECT=
|
||||||
|
SERVER=
|
||||||
|
TIMEOUT=10
|
||||||
|
WARNING=
|
||||||
|
CRITICAL=
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
-h | --help )
|
||||||
|
usage
|
||||||
|
exit $STATE_OK ;;
|
||||||
|
-V | --version )
|
||||||
|
echo "$PROGNAME v$REVISION"
|
||||||
|
exit $STATE_OK ;;
|
||||||
|
-H | --address )
|
||||||
|
ADDRESS="$2"; shift 2 ;;
|
||||||
|
-a | --expect )
|
||||||
|
EXPECT="$2"; shift 2 ;;
|
||||||
|
-s | --server )
|
||||||
|
SERVER="$2"; shift 2 ;;
|
||||||
|
-t | --timeout )
|
||||||
|
TIMEOUT="$2"; shift 2 ;;
|
||||||
|
-w | --warning )
|
||||||
|
WARNING="$2"; shift 2 ;;
|
||||||
|
-c | --critical )
|
||||||
|
CRITICAL="$2"; shift 2 ;;
|
||||||
|
-- )
|
||||||
|
shift
|
||||||
|
break ;;
|
||||||
|
* )
|
||||||
|
break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$ADDRESS" ]; then
|
||||||
|
echo "Error: No address given."
|
||||||
|
usage
|
||||||
|
exit $STATE_CRITICAL
|
||||||
|
fi
|
||||||
|
|
||||||
|
DIGOPTS="+time=$TIMEOUT +noquestion +noauthority -t PTR"
|
||||||
|
[ -z "$SERVER" ] || DIGOPTS="@$SERVER $DIGOPTS"
|
||||||
|
|
||||||
|
RESULT=$(dig $DIGOPTS -x "$ADDRESS"):
|
||||||
|
DIGSTATUS=$?
|
||||||
|
|
||||||
|
if [ $DIGSTATUS != "0" ]; then
|
||||||
|
echo "DNS failed: dig exit code $DIGSTATUS |"
|
||||||
|
exit $STATE_CRITICAL
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the actual result
|
||||||
|
HOST=$(echo "$RESULT" | grep -m 1 -o "[[:space:]]IN[[:space:]]*PTR[[:space:]].*\.$" | awk '{ print $3 }' )
|
||||||
|
if [ -z "$HOST" ]; then
|
||||||
|
echo "DNS failed: reverse DNS gave no answer. |"
|
||||||
|
exit $STATE_CRITICAL
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Get the query time in msec
|
||||||
|
QUERYTIME=$(echo "$RESULT" | grep -m 1 "Query time:" | cut -d ":" -f 2 | awk '{ print $1 }')
|
||||||
|
|
||||||
|
|
||||||
|
MATCHED=
|
||||||
|
if [ -n "$EXPECT" ]; then
|
||||||
|
if [ "$EXPECT" != "$HOST" ]; then
|
||||||
|
echo "DNS critical - query result \"$HOST\" != \"$EXPECT\", query time: $QUERYTIME msec |"
|
||||||
|
exit $STATE_CRITICAL
|
||||||
|
else
|
||||||
|
MATCHED=" (match ok)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$CRITICAL" ] && [ "$QUERYTIME" -gt "$CRITICAL" ]; then
|
||||||
|
echo "DNS critical - query time $QUERYTIME msec too large ($CRITICAL msec), query result: \"$HOST\"$MATCHED |"
|
||||||
|
exit $STATE_CRITICAL
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$WARNING" ] && [ "$QUERYTIME" -gt "$WARNING" ]; then
|
||||||
|
echo "DNS warning - query time $QUERYTIME msec too large ($WARNING msec), query result: \"$HOST\"$MATCHED |"
|
||||||
|
exit $STATE_WARNING
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "DNS OK - query time $QUERYTIME msec, query result: \"$HOST\"$MATCHED |"
|
||||||
|
exit $STATE_OK
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
group: "{{ icinga2_server_group }}"
|
group: "{{ icinga2_server_group }}"
|
||||||
mode: 0600
|
mode: 0600
|
||||||
notify: restart icinga2
|
notify: restart icinga2
|
||||||
# no_log: True
|
no_log: True
|
||||||
|
|
||||||
- name: execute icinga2 api setup command
|
- name: execute icinga2 api setup command
|
||||||
command: icinga2 api setup
|
command: icinga2 api setup
|
||||||
|
@ -103,5 +103,15 @@
|
||||||
state: present
|
state: present
|
||||||
notify: restart icinga2
|
notify: restart icinga2
|
||||||
|
|
||||||
|
- name: constants.conf file installed
|
||||||
|
template:
|
||||||
|
src: constants.conf.j2
|
||||||
|
dest: /etc/icinga2/constants.conf
|
||||||
|
owner: "{{ icinga2_server_user }}"
|
||||||
|
group: "{{ icinga2_server_group }}"
|
||||||
|
mode: 0644
|
||||||
|
notify: restart icinga2
|
||||||
|
no_log: True
|
||||||
|
|
||||||
- name: Flush handlers
|
- name: Flush handlers
|
||||||
meta: flush_handlers
|
meta: flush_handlers
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#- import_tasks: install_icinga2.yml
|
#- import_tasks: install_icinga2.yml
|
||||||
#- import_tasks: install_mariadb.yml
|
#- import_tasks: install_mariadb.yml
|
||||||
#- import_tasks: install_ido.yml
|
#- import_tasks: install_ido.yml
|
||||||
- import_tasks: configure_icinga2_api_feature.yml
|
#- import_tasks: configure_icinga2_api_feature.yml
|
||||||
#- import_tasks: install_icingaweb2.yml
|
#- import_tasks: install_icingaweb2.yml
|
||||||
#- import_tasks: configure_icingaweb2.yml
|
#- import_tasks: configure_icingaweb2.yml
|
||||||
|
- import_tasks: postconfigure_icinga2.yml
|
||||||
|
|
40
roles/icinga2_server/tasks/postconfigure_icinga2.yml
Normal file
40
roles/icinga2_server/tasks/postconfigure_icinga2.yml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
- name: Icinga2 post config file deployed
|
||||||
|
template:
|
||||||
|
src: 'conf.d/{{ item }}.j2'
|
||||||
|
dest: '/etc/icinga2/conf.d/{{ item }}'
|
||||||
|
owner: "{{ icinga2_server_user }}"
|
||||||
|
group: "{{ icinga2_server_group }}"
|
||||||
|
mode: 0644
|
||||||
|
loop:
|
||||||
|
- commands.conf
|
||||||
|
- groups.conf
|
||||||
|
- notifications.conf
|
||||||
|
- services.conf
|
||||||
|
- templates.conf
|
||||||
|
- users.conf
|
||||||
|
- timeperiods.conf
|
||||||
|
notify: restart icinga2
|
||||||
|
|
||||||
|
- name: Icinga2 custom commands deployed
|
||||||
|
template:
|
||||||
|
src: 'conf.d/command-custom.conf.j2'
|
||||||
|
dest: '/usr/share/icinga2/include/command-custom.conf'
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0644
|
||||||
|
notify: restart icinga2
|
||||||
|
|
||||||
|
- name: custom nagios plugins deployed
|
||||||
|
copy:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: "{{ icinga2_server_nagios_plugins_location }}/{{ item }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0755
|
||||||
|
loop:
|
||||||
|
- check_dane
|
||||||
|
- check_openvpn
|
||||||
|
- check_rdns
|
||||||
|
notify: restart icinga2
|
||||||
|
|
143
roles/icinga2_server/templates/conf.d/command-custom.conf.j2
Normal file
143
roles/icinga2_server/templates/conf.d/command-custom.conf.j2
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
object CheckCommand "dane" {
|
||||||
|
import "plugin-check-command"
|
||||||
|
|
||||||
|
command = [ PluginDir + "/check_dane" ]
|
||||||
|
|
||||||
|
arguments = {
|
||||||
|
"--host" = {
|
||||||
|
value = "$dane_host$"
|
||||||
|
required = true
|
||||||
|
description = "Hostname to check"
|
||||||
|
}
|
||||||
|
"--port" = {
|
||||||
|
value = "$dane_port$"
|
||||||
|
required = true
|
||||||
|
description = "TCP port to check"
|
||||||
|
}
|
||||||
|
"--connect-host" = {
|
||||||
|
value = "$dane_connect_host$"
|
||||||
|
description = "Connect to this host instead of $dane_host$"
|
||||||
|
}
|
||||||
|
"--connect-port" = {
|
||||||
|
value = "$dane_connect_port$"
|
||||||
|
description = "Connect to this host instead of $dane_port$"
|
||||||
|
}
|
||||||
|
"--starttls" = {
|
||||||
|
value = "$dane_starttls$"
|
||||||
|
description = "Send the protocol-specific messages to enable TLS. Possible values: smtp, imap, xmpp, quassel"
|
||||||
|
}
|
||||||
|
"--check-pkix" = {
|
||||||
|
set_if = "$dane_check_pkix$"
|
||||||
|
description = "Additionally perform traditional checks on the certificate (ca trust path, hostname, expiry)."
|
||||||
|
}
|
||||||
|
"--nameserver" = {
|
||||||
|
value = "$dane_nameserver$"
|
||||||
|
description = "Use a custom nameserver."
|
||||||
|
}
|
||||||
|
"--min-days-valid" = {
|
||||||
|
value = "$dane_min_days_valid$"
|
||||||
|
description = "Minimum number of days a certificate has to be valid. Format: INTEGER[,INTEGER]. 1st is #days for warning, 2nd is critical."
|
||||||
|
}
|
||||||
|
"--timeout" = {
|
||||||
|
value = "$dane_timeout$"
|
||||||
|
description = "Network timeout in sec. Default: 10"
|
||||||
|
}
|
||||||
|
"--no-dnssec" = {
|
||||||
|
set_if = "$dane_no_dnssec$"
|
||||||
|
description = "Continue even when DNS replies aren't DNSSEC authenticated."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object CheckCommand "openvpn" {
|
||||||
|
import "ipv4-or-ipv6"
|
||||||
|
|
||||||
|
command = [ PluginDir + "/check_openvpn", "$openvpn_address$" ]
|
||||||
|
|
||||||
|
arguments = {
|
||||||
|
"-p" = {
|
||||||
|
value = "$openvpn_port$"
|
||||||
|
description = "set port number (default is 1194)"
|
||||||
|
}
|
||||||
|
"-t" = {
|
||||||
|
set_if = "$openvpn_tcp$"
|
||||||
|
description = "use tcp instead of udp"
|
||||||
|
}
|
||||||
|
"--timeout" = {
|
||||||
|
value = "$openvpn_timeout$"
|
||||||
|
description = "set timeout in seconds, for udp counted per packet (default is 2)"
|
||||||
|
}
|
||||||
|
"--digest" = {
|
||||||
|
value = "$openvpn_digest$"
|
||||||
|
description = "set digest algorithm (default is 'sha1')"
|
||||||
|
}
|
||||||
|
"--digest-size" = {
|
||||||
|
value = "$openvpn_digest_size$"
|
||||||
|
description = "set HMAC digest size"
|
||||||
|
}
|
||||||
|
"--digest-key-client" = {
|
||||||
|
value = "$openvpn_digest_key_client$"
|
||||||
|
description = "set client HMAC key"
|
||||||
|
}
|
||||||
|
"--digest-key-server" = {
|
||||||
|
value = "$openvpn_key_server$"
|
||||||
|
description = "set server HMAC key for packet validation"
|
||||||
|
}
|
||||||
|
"--tls-auth" = {
|
||||||
|
value = "$openvpn_tls_auth$"
|
||||||
|
description = "set tls-auth file"
|
||||||
|
}
|
||||||
|
"--tls-auth-inverse" = {
|
||||||
|
value = "$openvpn_tls_auth_inverse$"
|
||||||
|
description = "set tls-auth file direction to inverse (1)"
|
||||||
|
}
|
||||||
|
"--retrycount" = {
|
||||||
|
value = "$openvpn_retrycount$"
|
||||||
|
description = "number of udp retries before giving up (default is 3)"
|
||||||
|
}
|
||||||
|
"--no-validation" = {
|
||||||
|
value = "$openvpn_no_validation$"
|
||||||
|
description = "do not validate response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vars.openvpn_address = "$check_address$"
|
||||||
|
vars.openvpn_tls_auth = "$openvpn_takey$"
|
||||||
|
}
|
||||||
|
|
||||||
|
object CheckCommand "by_ssh_wirebrass" {
|
||||||
|
import "by_ssh"
|
||||||
|
|
||||||
|
vars.by_ssh_custom_plugins_path = "{{ icinga2_server_nagios_plugins_location }}"
|
||||||
|
vars.by_ssh_logname = "nagios"
|
||||||
|
vars.by_ssh_identity = "/var/lib/icinga2/.ssh/id_rsa"
|
||||||
|
vars.by_ssh_options = [ "ControlMaster=auto","ControlPath=/var/run/icinga2/$host.name$","ControlPersist=10m"]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object CheckCommand "rdns" {
|
||||||
|
|
||||||
|
import "plugin-check-command"
|
||||||
|
|
||||||
|
command = [ PluginDir + "/check_rdns" ]
|
||||||
|
|
||||||
|
arguments = {
|
||||||
|
"-H" = {
|
||||||
|
value = "$rdns_address$"
|
||||||
|
required = true
|
||||||
|
description = "Address to reverse"
|
||||||
|
}
|
||||||
|
"-a" = {
|
||||||
|
value = "$rdns_expect$"
|
||||||
|
required = false
|
||||||
|
description = "Expected result"
|
||||||
|
}
|
||||||
|
"-s" = {
|
||||||
|
value = "$rdns_server$"
|
||||||
|
required = false
|
||||||
|
description = "The DNS server to contact"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
187
roles/icinga2_server/templates/conf.d/commands.conf.j2
Normal file
187
roles/icinga2_server/templates/conf.d/commands.conf.j2
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
/* Command objects */
|
||||||
|
|
||||||
|
/* Notification Commands
|
||||||
|
*
|
||||||
|
* Please check the documentation for all required and
|
||||||
|
* optional parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
object NotificationCommand "mail-host-notification" {
|
||||||
|
command = [ ConfigDir + "/scripts/mail-host-notification.sh" ]
|
||||||
|
|
||||||
|
arguments += {
|
||||||
|
"-4" = "$notification_address$"
|
||||||
|
"-6" = "$notification_address6$"
|
||||||
|
"-b" = "$notification_author$"
|
||||||
|
"-c" = "$notification_comment$"
|
||||||
|
"-d" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_date$"
|
||||||
|
}
|
||||||
|
"-f" = {
|
||||||
|
value = "$notification_from$"
|
||||||
|
description = "Set from address. Requires GNU mailutils (Debian/Ubuntu) or mailx (RHEL/SUSE)"
|
||||||
|
}
|
||||||
|
"-i" = "$notification_icingaweb2url$"
|
||||||
|
"-l" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_hostname$"
|
||||||
|
}
|
||||||
|
"-n" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_hostdisplayname$"
|
||||||
|
}
|
||||||
|
"-o" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_hostoutput$"
|
||||||
|
}
|
||||||
|
"-r" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_useremail$"
|
||||||
|
}
|
||||||
|
"-s" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_hoststate$"
|
||||||
|
}
|
||||||
|
"-t" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_type$"
|
||||||
|
}
|
||||||
|
"-v" = "$notification_logtosyslog$"
|
||||||
|
}
|
||||||
|
|
||||||
|
vars += {
|
||||||
|
notification_address = "$address$"
|
||||||
|
notification_address6 = "$address6$"
|
||||||
|
notification_author = "$notification.author$"
|
||||||
|
notification_comment = "$notification.comment$"
|
||||||
|
notification_type = "$notification.type$"
|
||||||
|
notification_date = "$icinga.long_date_time$"
|
||||||
|
notification_hostname = "$host.name$"
|
||||||
|
notification_hostdisplayname = "$host.display_name$"
|
||||||
|
notification_hostoutput = "$host.output$"
|
||||||
|
notification_hoststate = "$host.state$"
|
||||||
|
notification_useremail = "$user.email$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object NotificationCommand "mail-service-notification" {
|
||||||
|
command = [ ConfigDir + "/scripts/mail-service-notification.sh" ]
|
||||||
|
|
||||||
|
arguments += {
|
||||||
|
"-4" = "$notification_address$"
|
||||||
|
"-6" = "$notification_address6$"
|
||||||
|
"-b" = "$notification_author$"
|
||||||
|
"-c" = "$notification_comment$"
|
||||||
|
"-d" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_date$"
|
||||||
|
}
|
||||||
|
"-e" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_servicename$"
|
||||||
|
}
|
||||||
|
"-f" = {
|
||||||
|
value = "$notification_from$"
|
||||||
|
description = "Set from address. Requires GNU mailutils (Debian/Ubuntu) or mailx (RHEL/SUSE)"
|
||||||
|
}
|
||||||
|
"-i" = "$notification_icingaweb2url$"
|
||||||
|
"-l" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_hostname$"
|
||||||
|
}
|
||||||
|
"-n" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_hostdisplayname$"
|
||||||
|
}
|
||||||
|
"-o" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_serviceoutput$"
|
||||||
|
}
|
||||||
|
"-r" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_useremail$"
|
||||||
|
}
|
||||||
|
"-s" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_servicestate$"
|
||||||
|
}
|
||||||
|
"-t" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_type$"
|
||||||
|
}
|
||||||
|
"-u" = {
|
||||||
|
required = true
|
||||||
|
value = "$notification_servicedisplayname$"
|
||||||
|
}
|
||||||
|
"-v" = "$notification_logtosyslog$"
|
||||||
|
}
|
||||||
|
|
||||||
|
vars += {
|
||||||
|
notification_address = "$address$"
|
||||||
|
notification_address6 = "$address6$"
|
||||||
|
notification_author = "$notification.author$"
|
||||||
|
notification_comment = "$notification.comment$"
|
||||||
|
notification_type = "$notification.type$"
|
||||||
|
notification_date = "$icinga.long_date_time$"
|
||||||
|
notification_hostname = "$host.name$"
|
||||||
|
notification_hostdisplayname = "$host.display_name$"
|
||||||
|
notification_servicename = "$service.name$"
|
||||||
|
notification_serviceoutput = "$service.output$"
|
||||||
|
notification_servicestate = "$service.state$"
|
||||||
|
notification_useremail = "$user.email$"
|
||||||
|
notification_servicedisplayname = "$service.display_name$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you prefer to use the notification scripts with environment
|
||||||
|
* variables instead of command line parameters, you can use
|
||||||
|
* the following commands. They have been updated from < 2.7
|
||||||
|
* to support the new notification scripts and should help
|
||||||
|
* with an upgrade.
|
||||||
|
* Remove the comment blocks and comment the notification commands above.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
object NotificationCommand "mail-host-notification" {
|
||||||
|
command = [ ConfigDir + "/scripts/mail-host-notification.sh" ]
|
||||||
|
|
||||||
|
env = {
|
||||||
|
NOTIFICATIONTYPE = "$notification.type$"
|
||||||
|
HOSTDISPLAYNAME = "$host.display_name$"
|
||||||
|
HOSTNAME = "$host.name$"
|
||||||
|
HOSTADDRESS = "$address$"
|
||||||
|
HOSTSTATE = "$host.state$"
|
||||||
|
LONGDATETIME = "$icinga.long_date_time$"
|
||||||
|
HOSTOUTPUT = "$host.output$"
|
||||||
|
NOTIFICATIONAUTHORNAME = "$notification.author$"
|
||||||
|
NOTIFICATIONCOMMENT = "$notification.comment$"
|
||||||
|
HOSTDISPLAYNAME = "$host.display_name$"
|
||||||
|
USEREMAIL = "$user.email$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object NotificationCommand "mail-service-notification" {
|
||||||
|
command = [ ConfigDir + "/scripts/mail-service-notification.sh" ]
|
||||||
|
|
||||||
|
env = {
|
||||||
|
NOTIFICATIONTYPE = "$notification.type$"
|
||||||
|
SERVICENAME = "$service.name$"
|
||||||
|
HOSTNAME = "$host.name$"
|
||||||
|
HOSTDISPLAYNAME = "$host.display_name$"
|
||||||
|
HOSTADDRESS = "$address$"
|
||||||
|
SERVICESTATE = "$service.state$"
|
||||||
|
LONGDATETIME = "$icinga.long_date_time$"
|
||||||
|
SERVICEOUTPUT = "$service.output$"
|
||||||
|
NOTIFICATIONAUTHORNAME = "$notification.author$"
|
||||||
|
NOTIFICATIONCOMMENT = "$notification.comment$"
|
||||||
|
HOSTDISPLAYNAME = "$host.display_name$"
|
||||||
|
SERVICEDISPLAYNAME = "$service.display_name$"
|
||||||
|
USEREMAIL = "$user.email$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
include "/usr/share/icinga2/include/command-custom.conf"
|
44
roles/icinga2_server/templates/conf.d/groups.conf.j2
Normal file
44
roles/icinga2_server/templates/conf.d/groups.conf.j2
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Host group examples.
|
||||||
|
*/
|
||||||
|
|
||||||
|
object HostGroup "linux-servers" {
|
||||||
|
display_name = "Linux Servers"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux"
|
||||||
|
}
|
||||||
|
|
||||||
|
object HostGroup "windows-servers" {
|
||||||
|
display_name = "Windows Servers"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Windows"
|
||||||
|
}
|
||||||
|
|
||||||
|
{% if icinga2_server_custom_hostgroup is defined %}
|
||||||
|
object HostGroup "{{ icinga2_server_custom_hostgroup }}" {
|
||||||
|
display_name = "{{ icinga2_server_custom_hostgroup }}"
|
||||||
|
assign where host.vars.owner == "{{ icinga2_server_custom_hostgroup }}"
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
/**
|
||||||
|
* Service group examples.
|
||||||
|
*/
|
||||||
|
|
||||||
|
object ServiceGroup "ping" {
|
||||||
|
display_name = "Ping Checks"
|
||||||
|
|
||||||
|
assign where match("ping*", service.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
object ServiceGroup "http" {
|
||||||
|
display_name = "HTTP Checks"
|
||||||
|
|
||||||
|
assign where match("http*", service.check_command)
|
||||||
|
}
|
||||||
|
|
||||||
|
object ServiceGroup "disk" {
|
||||||
|
display_name = "Disk Checks"
|
||||||
|
|
||||||
|
assign where match("disk*", service.check_command)
|
||||||
|
}
|
||||||
|
|
33
roles/icinga2_server/templates/conf.d/notifications.conf.j2
Normal file
33
roles/icinga2_server/templates/conf.d/notifications.conf.j2
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* The example notification apply rules.
|
||||||
|
*
|
||||||
|
* Only applied if host/service objects have
|
||||||
|
* the custom variable `notification` defined
|
||||||
|
* and containing `mail` as key.
|
||||||
|
*
|
||||||
|
* Check `hosts.conf` for an example.
|
||||||
|
*/
|
||||||
|
|
||||||
|
apply Notification "mail-icingaadmin" to Host {
|
||||||
|
import "mail-host-notification"
|
||||||
|
user_groups = host.vars.notification.mail.groups
|
||||||
|
users = host.vars.notification.mail.users
|
||||||
|
|
||||||
|
interval = 1h
|
||||||
|
|
||||||
|
//vars.notification_logtosyslog = true
|
||||||
|
|
||||||
|
assign where host.vars.notification.mail
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Notification "mail-icingaadmin" to Service {
|
||||||
|
import "mail-service-notification"
|
||||||
|
user_groups = host.vars.notification.mail.groups
|
||||||
|
users = host.vars.notification.mail.users
|
||||||
|
|
||||||
|
interval = 1h
|
||||||
|
|
||||||
|
//vars.notification_logtosyslog = true
|
||||||
|
|
||||||
|
assign where host.vars.notification.mail
|
||||||
|
}
|
277
roles/icinga2_server/templates/conf.d/services.conf.j2
Normal file
277
roles/icinga2_server/templates/conf.d/services.conf.j2
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
/*
|
||||||
|
* Service apply rules.
|
||||||
|
*
|
||||||
|
* The CheckCommand objects `ping4`, `ping6`, etc
|
||||||
|
* are provided by the plugin check command templates.
|
||||||
|
* Check the documentation for details.
|
||||||
|
*
|
||||||
|
* Tip: Use `icinga2 object list --type Service` to
|
||||||
|
* list all service objects after running
|
||||||
|
* configuration validation (`icinga2 daemon -C`).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an example host based on your
|
||||||
|
* local host's FQDN. Specify the NodeName
|
||||||
|
* constant in `constants.conf` or use your
|
||||||
|
* own description, e.g. "db-host-1".
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are generic `ping4` and `ping6`
|
||||||
|
* checks applied to all hosts having the
|
||||||
|
* `address` resp. `address6` attribute
|
||||||
|
* defined.
|
||||||
|
*/
|
||||||
|
apply Service "ping4" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "ping4"
|
||||||
|
|
||||||
|
assign where host.address
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "ping6" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "ping6"
|
||||||
|
|
||||||
|
assign where host.address6
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Apply the `ssh` service to all hosts
|
||||||
|
* with the `address` attribute defined and
|
||||||
|
* the custom attribute `os` set to `Linux`.
|
||||||
|
*/
|
||||||
|
apply Service "ssh" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "ssh"
|
||||||
|
|
||||||
|
assign where (host.address || host.address6) && host.vars.os == "Linux"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "dns-forward-ipv4" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "dig"
|
||||||
|
vars.dig_lookup = "$host_name$"
|
||||||
|
vars.dig_server = "80.67.169.40"
|
||||||
|
vars.dig_record_type = "A"
|
||||||
|
vars.dig_ipv4 = "true"
|
||||||
|
|
||||||
|
if (host.vars.dig_expected_address) {
|
||||||
|
vars.dig_expected_address = host.vars.dig_expected_address
|
||||||
|
} else {
|
||||||
|
vars.dig_expected_address = "$address$"
|
||||||
|
}
|
||||||
|
|
||||||
|
assign where (host.address) && host.vars.os == "Linux"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "dns-forward-ipv6" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "dig"
|
||||||
|
vars.dig_lookup = "$host_name$"
|
||||||
|
vars.dig_server = "2001:910:800::12"
|
||||||
|
vars.dig_record_type = "AAAA"
|
||||||
|
vars.dig_ipv6 = "true"
|
||||||
|
|
||||||
|
if (host.vars.dig_expected_address6) {
|
||||||
|
vars.dig_expected_address = host.vars.dig_expected_address6
|
||||||
|
} else {
|
||||||
|
vars.dig_expected_address = "$address6$"
|
||||||
|
}
|
||||||
|
|
||||||
|
assign where (host.address6) && host.vars.os == "Linux"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "dns-reverse-ipv4" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "rdns"
|
||||||
|
vars.sla = "24x7"
|
||||||
|
vars.rdns_server = "80.67.169.40"
|
||||||
|
|
||||||
|
if (host.vars.rdns_expect) {
|
||||||
|
vars.rdns_expect = host.vars.rdns_expect
|
||||||
|
} else {
|
||||||
|
vars.rdns_expect = "$host_name$."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host.vars.rdns_address) {
|
||||||
|
vars.rdns_address = host.vars.rdns_address
|
||||||
|
} else {
|
||||||
|
vars.rdns_address = "$address$"
|
||||||
|
}
|
||||||
|
|
||||||
|
assign where (host.address) && host.vars.os == "Linux"# && host.name != "vm-mw-01.wirebrass.fr"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "dns-reverse-ipv6" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "rdns"
|
||||||
|
vars.sla = "24x7"
|
||||||
|
vars.rdns_server = "2001:910:800::12"
|
||||||
|
|
||||||
|
if (host.vars.rdns_expect6) {
|
||||||
|
vars.rdns_expect = host.vars.rdns_expect6
|
||||||
|
} else {
|
||||||
|
vars.rdns_expect = "$host_name$."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host.vars.rdns_address6) {
|
||||||
|
vars.rdns_address = host.vars.rdns_address6
|
||||||
|
} else {
|
||||||
|
vars.rdns_address = "$address6$"
|
||||||
|
}
|
||||||
|
|
||||||
|
assign where (host.address6) && host.vars.os == "Linux" && host.name != "vm-ttn-01.wirebrass.fr" && host.name != "vm-fma-01.wirebrass.fr"# && host.name != "vm-mw-01.wirebrass.fr"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "ntp_by_ssh" {
|
||||||
|
import "generic-service"
|
||||||
|
check_command = "by_ssh_wirebrass"
|
||||||
|
|
||||||
|
vars.by_ssh_timeout = 30
|
||||||
|
vars.by_ssh_command = "$by_ssh_custom_plugins_path$check_ntp_time -H pool.ntp.org"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux" && host.vars.agent_type == "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "uptime_by_ssh" {
|
||||||
|
import "generic-service"
|
||||||
|
check_command = "by_ssh_wirebrass"
|
||||||
|
|
||||||
|
vars.by_ssh_custom_uptime = 5184000
|
||||||
|
vars.by_ssh_command = "test $$(cut -d. -f1 /proc/uptime) -lt $by_ssh_custom_uptime$"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux" && host.vars.agent_type == "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "load_by_ssh" {
|
||||||
|
import "generic-service"
|
||||||
|
check_command = "by_ssh_wirebrass"
|
||||||
|
|
||||||
|
vars.load_by_ssh_warn = "7.0,6.0,6.0"
|
||||||
|
vars.load_by_ssh_crit = "8.0,7.0,7.5"
|
||||||
|
|
||||||
|
vars.by_ssh_command = "$by_ssh_custom_plugins_path$check_load -w $load_by_ssh_warn$ -c $load_by_ssh_crit$"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux" && host.vars.agent_type == "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "users_by_ssh" {
|
||||||
|
import "generic-service"
|
||||||
|
check_command = "by_ssh_wirebrass"
|
||||||
|
|
||||||
|
vars.users_wgreater = 5
|
||||||
|
vars.users_cgreater = 10
|
||||||
|
|
||||||
|
vars.by_ssh_command = "$by_ssh_custom_plugins_path$check_users -w $users_wgreater$ -c $users_cgreater$"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux" && host.vars.agent_type == "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "disk_by_ssh_device" {
|
||||||
|
import "generic-service"
|
||||||
|
check_command = "by_ssh_wirebrass"
|
||||||
|
|
||||||
|
vars.by_ssh_command = "$by_ssh_custom_plugins_path$check_disk -w 20% -c 10% -A -x /sys/kernel/debug/tracing -x nsfs -x shm -x overlay"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux" && host.vars.agent_type == "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "procs_zombie_by_ssh" {
|
||||||
|
import "generic-service"
|
||||||
|
check_command = "by_ssh_wirebrass"
|
||||||
|
|
||||||
|
vars.by_ssh_command = "$by_ssh_custom_plugins_path$check_procs -w 5 -c 10 -s Z"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux" && host.vars.agent_type == "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "lastupdate_by_ssh" {
|
||||||
|
import "generic-service"
|
||||||
|
check_command = "by_ssh_wirebrass"
|
||||||
|
|
||||||
|
vars.by_ssh_command = "$by_ssh_custom_plugins_path$check_file_age -w 93600 -c 180000 -f /var/lastupdate"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux" && host.vars.agent_type == "ssh" && host.name != "hv01.wirebrass.fr" && host.name != "hv02.wirebrass.fr" && host.name != "hv03.wirebrass.fr" && host.name != "radiosupinfo.wirebrass.fr" && host.name != "radio.supinfo.com.wirebrass.fr"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "procs_by_ssh" {
|
||||||
|
import "generic-service"
|
||||||
|
check_command = "by_ssh_wirebrass"
|
||||||
|
|
||||||
|
vars.procs_by_ssh_warn = 400
|
||||||
|
vars.procs_by_ssh_crit = 500
|
||||||
|
|
||||||
|
vars.by_ssh_command = "$by_ssh_custom_plugins_path$check_procs -w $procs_by_ssh_warn$ -c $procs_by_ssh_crit$"
|
||||||
|
|
||||||
|
assign where host.vars.os == "Linux" && host.vars.agent_type == "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service for (http_vhost => config in host.vars.http_vhosts) {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "http"
|
||||||
|
|
||||||
|
vars += config
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service for (disk => config in host.vars.disks) {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "disk"
|
||||||
|
|
||||||
|
vars += config
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "icinga" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "icinga"
|
||||||
|
|
||||||
|
assign where host.name == NodeName
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
apply Service "load" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "load"
|
||||||
|
*/
|
||||||
|
/* Used by the ScheduledDowntime apply rule in `downtimes.conf`. */
|
||||||
|
/*vars.backup_downtime = "02:00-03:00"
|
||||||
|
|
||||||
|
assign where host.name == NodeName
|
||||||
|
}*/
|
||||||
|
|
||||||
|
apply Service "procs" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "procs"
|
||||||
|
|
||||||
|
assign where host.name == NodeName
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "swap" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "swap"
|
||||||
|
|
||||||
|
assign where host.name == NodeName
|
||||||
|
}
|
||||||
|
|
||||||
|
apply Service "users" {
|
||||||
|
import "generic-service"
|
||||||
|
|
||||||
|
check_command = "users"
|
||||||
|
|
||||||
|
assign where host.name == NodeName
|
||||||
|
}
|
||||||
|
|
95
roles/icinga2_server/templates/conf.d/templates.conf.j2
Normal file
95
roles/icinga2_server/templates/conf.d/templates.conf.j2
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Generic template examples.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides default settings for hosts. By convention
|
||||||
|
* all hosts should import this template.
|
||||||
|
*
|
||||||
|
* The CheckCommand object `hostalive` is provided by
|
||||||
|
* the plugin check command templates.
|
||||||
|
* Check the documentation for details.
|
||||||
|
*/
|
||||||
|
template Host "generic-host" {
|
||||||
|
max_check_attempts = 5
|
||||||
|
check_interval = 2m
|
||||||
|
retry_interval = 1m
|
||||||
|
|
||||||
|
check_command = "hostalive"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides default settings for services. By convention
|
||||||
|
* all services should import this template.
|
||||||
|
*/
|
||||||
|
template Service "generic-service" {
|
||||||
|
max_check_attempts = 5
|
||||||
|
check_interval = 2m
|
||||||
|
retry_interval = 1m
|
||||||
|
}
|
||||||
|
|
||||||
|
template Host "{{ icinga2_server_custom_hostgroup }}-host" {
|
||||||
|
import "generic-host"
|
||||||
|
|
||||||
|
vars.owner = "{{ icinga2_server_custom_hostgroup }}"
|
||||||
|
vars.notification["mail"] = {
|
||||||
|
groups = [ "{{ icinga2_server_custom_hostgroup }}" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides default settings for users. By convention
|
||||||
|
* all users should inherit from this template.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template User "generic-user" {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides default settings for host notifications.
|
||||||
|
* By convention all host notifications should import
|
||||||
|
* this template.
|
||||||
|
*/
|
||||||
|
template Notification "mail-host-notification" {
|
||||||
|
command = "mail-host-notification"
|
||||||
|
|
||||||
|
states = [ Up, Down ]
|
||||||
|
types = [ Problem, Acknowledgement, Recovery, Custom,
|
||||||
|
FlappingStart, FlappingEnd,
|
||||||
|
DowntimeStart, DowntimeEnd, DowntimeRemoved ]
|
||||||
|
|
||||||
|
vars += {
|
||||||
|
// notification_icingaweb2url = "https://www.example.com/icingaweb2"
|
||||||
|
// notification_from = "Icinga 2 Host Monitoring <icinga@example.com>"
|
||||||
|
notification_logtosyslog = false
|
||||||
|
}
|
||||||
|
|
||||||
|
//period = "24x7"
|
||||||
|
period = "24x7minus4to5"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides default settings for service notifications.
|
||||||
|
* By convention all service notifications should import
|
||||||
|
* this template.
|
||||||
|
*/
|
||||||
|
template Notification "mail-service-notification" {
|
||||||
|
command = "mail-service-notification"
|
||||||
|
|
||||||
|
states = [ OK, Warning, Critical, Unknown ]
|
||||||
|
types = [ Problem, Acknowledgement, Recovery, Custom,
|
||||||
|
FlappingStart, FlappingEnd,
|
||||||
|
DowntimeStart, DowntimeEnd, DowntimeRemoved ]
|
||||||
|
|
||||||
|
vars += {
|
||||||
|
// notification_icingaweb2url = "https://www.example.com/icingaweb2"
|
||||||
|
// notification_from = "Icinga 2 Service Monitoring <icinga@example.com>"
|
||||||
|
notification_logtosyslog = false
|
||||||
|
}
|
||||||
|
|
||||||
|
//period = "24x7"
|
||||||
|
period = "24x7minus4to5"
|
||||||
|
}
|
||||||
|
|
61
roles/icinga2_server/templates/conf.d/timeperiods.conf.j2
Normal file
61
roles/icinga2_server/templates/conf.d/timeperiods.conf.j2
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* Sample timeperiods for Icinga 2.
|
||||||
|
* Check the documentation for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
object TimePeriod "24x7" {
|
||||||
|
display_name = "Icinga 2 24x7 TimePeriod"
|
||||||
|
ranges = {
|
||||||
|
"monday" = "00:00-24:00"
|
||||||
|
"tuesday" = "00:00-24:00"
|
||||||
|
"wednesday" = "00:00-24:00"
|
||||||
|
"thursday" = "00:00-24:00"
|
||||||
|
"friday" = "00:00-24:00"
|
||||||
|
"saturday" = "00:00-24:00"
|
||||||
|
"sunday" = "00:00-24:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TimePeriod "24x7minus2to3" {
|
||||||
|
display_name = "Icinga 2 24x7 TimePeriod without 2:00-2:30"
|
||||||
|
ranges = {
|
||||||
|
"monday" = "00:00-02:00,02:30-24:00"
|
||||||
|
"tuesday" = "00:00-02:00,02:30-24:00"
|
||||||
|
"wednesday" = "00:00-02:00,02:30-24:00"
|
||||||
|
"thursday" = "00:00-02:00,02:30-24:00"
|
||||||
|
"friday" = "00:00-02:00,02:30-24:00"
|
||||||
|
"saturday" = "00:00-02:00,02:30-24:00"
|
||||||
|
"sunday" = "00:00-02:00,02:30-24:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TimePeriod "24x7minus4to5" {
|
||||||
|
display_name = "Icinga 2 24x7 TimePeriod without 4:00-5:00"
|
||||||
|
ranges = {
|
||||||
|
"monday" = "00:00-04:00,05:00-24:00"
|
||||||
|
"tuesday" = "00:00-04:00,05:00-24:00"
|
||||||
|
"wednesday" = "00:00-04:00,05:00-24:00"
|
||||||
|
"thursday" = "00:00-04:00,05:00-24:00"
|
||||||
|
"friday" = "00:00-04:00,05:00-24:00"
|
||||||
|
"saturday" = "00:00-04:00,05:00-24:00"
|
||||||
|
"sunday" = "00:00-04:00,05:00-24:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TimePeriod "9to5" {
|
||||||
|
display_name = "Icinga 2 9to5 TimePeriod"
|
||||||
|
ranges = {
|
||||||
|
"monday" = "09:00-17:00"
|
||||||
|
"tuesday" = "09:00-17:00"
|
||||||
|
"wednesday" = "09:00-17:00"
|
||||||
|
"thursday" = "09:00-17:00"
|
||||||
|
"friday" = "09:00-17:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TimePeriod "never" {
|
||||||
|
display_name = "Icinga 2 never TimePeriod"
|
||||||
|
ranges = {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
31
roles/icinga2_server/templates/conf.d/users.conf.j2
Normal file
31
roles/icinga2_server/templates/conf.d/users.conf.j2
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* The example user 'icingaadmin' and the example
|
||||||
|
* group 'icingaadmins'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
object User "icingaadmin" {
|
||||||
|
import "generic-user"
|
||||||
|
|
||||||
|
display_name = "Icinga 2 Admin"
|
||||||
|
groups = [ "icingaadmins" ]
|
||||||
|
|
||||||
|
email = "root@localhost"
|
||||||
|
}
|
||||||
|
|
||||||
|
object UserGroup "icingaadmins" {
|
||||||
|
display_name = "Icinga 2 Admin Group"
|
||||||
|
}
|
||||||
|
|
||||||
|
object User "{{ icinga2_server_icingaweb2_main_user }}" {
|
||||||
|
import "generic-user"
|
||||||
|
|
||||||
|
display_name = "{{ icinga2_server_icingaweb2_main_user }}"
|
||||||
|
groups = [ "icingaadmins", "{{ icinga2_server_custom_hostgroup }}" ]
|
||||||
|
|
||||||
|
email = "{{ icinga2_server_icingaweb2_main_user_email }}"
|
||||||
|
}
|
||||||
|
|
||||||
|
object UserGroup "{{ icinga2_server_custom_hostgroup }}" {
|
||||||
|
display_name = "{{ icinga2_server_custom_hostgroup }}"
|
||||||
|
}
|
||||||
|
|
28
roles/icinga2_server/templates/constants.conf.j2
Normal file
28
roles/icinga2_server/templates/constants.conf.j2
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* This file defines global constants which can be used in
|
||||||
|
* the other configuration files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The directory which contains the plugins from the Monitoring Plugins project. */
|
||||||
|
const PluginDir = "/usr/lib/nagios/plugins"
|
||||||
|
|
||||||
|
/* The directory which contains the Manubulon plugins.
|
||||||
|
* Check the documentation, chapter "SNMP Manubulon Plugin Check Commands", for details.
|
||||||
|
*/
|
||||||
|
const ManubulonPluginDir = "/usr/lib/nagios/plugins"
|
||||||
|
|
||||||
|
/* The directory which you use to store additional plugins which ITL provides user contributed command definitions for.
|
||||||
|
* Check the documentation, chapter "Plugins Contribution", for details.
|
||||||
|
*/
|
||||||
|
const PluginContribDir = "/usr/lib/nagios/plugins"
|
||||||
|
|
||||||
|
/* Our local instance name. By default this is the server's hostname as returned by `hostname --fqdn`.
|
||||||
|
* This should be the common name from the API certificate.
|
||||||
|
*/
|
||||||
|
const NodeName = "{{ inventory_hostname }}"
|
||||||
|
|
||||||
|
/* Our local zone name. */
|
||||||
|
const ZoneName = "{{ inventory_hostname }}"
|
||||||
|
|
||||||
|
/* Secret key for remote node tickets */
|
||||||
|
const TicketSalt = "{{ icinga2_server_ticket_salt }}"
|
Loading…
Reference in a new issue