Add plugin that performs various checks on domain names.
This commit is contained in:
parent
de64c02488
commit
a37a8c33b1
BIN
check_mk-domains/domain_checks-0.1.0.mkp
Executable file
BIN
check_mk-domains/domain_checks-0.1.0.mkp
Executable file
Binary file not shown.
@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2025 Spearhead Systems SRL
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from cmk.base.plugins.agent_based.agent_based_api.v1 import register, Result, Service, State
|
||||||
|
|
||||||
|
|
||||||
|
# Incoming agent output takes the form:
|
||||||
|
#
|
||||||
|
# google.com:
|
||||||
|
# 2028-09-14
|
||||||
|
# yahoo.com:
|
||||||
|
# 2026-01-19
|
||||||
|
#
|
||||||
|
# The domains being queries end with a colon. The expiry response does not.
|
||||||
|
#
|
||||||
|
# Return a dictionary which uses domain as key, and returns an expiry as
|
||||||
|
# datetime.date.
|
||||||
|
def parse_domains_expiry(string_table):
|
||||||
|
expiries = {}
|
||||||
|
current_domain = ""
|
||||||
|
|
||||||
|
for line in string_table:
|
||||||
|
line = line[0]
|
||||||
|
|
||||||
|
domain = line[:-1]
|
||||||
|
ending = line[-1]
|
||||||
|
|
||||||
|
if ending == ":":
|
||||||
|
current_domain = domain
|
||||||
|
else:
|
||||||
|
date = datetime.datetime.strptime(line, '%Y-%m-%d').date()
|
||||||
|
expiries[current_domain] = date
|
||||||
|
|
||||||
|
return expiries
|
||||||
|
|
||||||
|
|
||||||
|
def discover_domains_expiry(section):
|
||||||
|
for domain, date in section.items():
|
||||||
|
yield Service(item=domain)
|
||||||
|
|
||||||
|
|
||||||
|
def check_domains_expiry(item, params, section):
|
||||||
|
expiry = section.get(item)
|
||||||
|
if not expiry:
|
||||||
|
yield Result(state=State.WARN, summary="Expiry not found in whois")
|
||||||
|
return
|
||||||
|
|
||||||
|
alert_delta = params.get("days_remaining")
|
||||||
|
if not alert_delta:
|
||||||
|
yield Result(state=State.WARN, summary="No expiry check rule configured")
|
||||||
|
return
|
||||||
|
|
||||||
|
valid_days_left = (expiry - datetime.date.today()).days
|
||||||
|
summary = "Domain expires in %s days" % valid_days_left
|
||||||
|
state = State.OK
|
||||||
|
|
||||||
|
if valid_days_left < alert_delta[1]:
|
||||||
|
state = State.CRIT
|
||||||
|
elif valid_days_left < alert_delta[0]:
|
||||||
|
state = State.WARN
|
||||||
|
|
||||||
|
yield Result(state=state, summary=summary)
|
||||||
|
|
||||||
|
|
||||||
|
register.agent_section(
|
||||||
|
name="domains_expiry",
|
||||||
|
parse_function=parse_domains_expiry
|
||||||
|
)
|
||||||
|
|
||||||
|
register.check_plugin(
|
||||||
|
name="domains_expiry",
|
||||||
|
service_name="Expiry for Domain '%s'",
|
||||||
|
|
||||||
|
discovery_function=discover_domains_expiry,
|
||||||
|
|
||||||
|
check_function=check_domains_expiry,
|
||||||
|
check_default_parameters={},
|
||||||
|
check_ruleset_name="domains_expiry",
|
||||||
|
)
|
@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2025 Spearhead Systems SRL
|
||||||
|
|
||||||
|
from cmk.base.plugins.agent_based.agent_based_api.v1 import register, Result, Service, State
|
||||||
|
|
||||||
|
|
||||||
|
# Incoming agent output takes the form:
|
||||||
|
#
|
||||||
|
# google.com:
|
||||||
|
# ns3.google.com.
|
||||||
|
# ns1.google.com.
|
||||||
|
# ns4.google.com.
|
||||||
|
# ns2.google.com.
|
||||||
|
# yahoo.com:
|
||||||
|
# ns2.yahoo.com.
|
||||||
|
# ns1.yahoo.com.
|
||||||
|
# ns3.yahoo.com.
|
||||||
|
# ns4.yahoo.com.
|
||||||
|
# ns5.yahoo.com.
|
||||||
|
#
|
||||||
|
# The domains being queries end with a colon. The nameserver responses end with
|
||||||
|
# a period. Nameservers follow the domain being queried.
|
||||||
|
#
|
||||||
|
# Return a dictionary which uses domain as key, and returns a list of associated
|
||||||
|
# nameservers for that key.
|
||||||
|
def parse_domains_nameservers(string_table):
|
||||||
|
nameservers = {}
|
||||||
|
current_domain = ""
|
||||||
|
|
||||||
|
for line in string_table:
|
||||||
|
domain = line[0][:-1]
|
||||||
|
ending = line[0][-1]
|
||||||
|
|
||||||
|
if ending == ":":
|
||||||
|
current_domain = domain
|
||||||
|
nameservers[current_domain] = []
|
||||||
|
elif ending == ".":
|
||||||
|
nameservers[current_domain].append(domain)
|
||||||
|
|
||||||
|
return nameservers
|
||||||
|
|
||||||
|
|
||||||
|
def discover_domains_nameservers(section):
|
||||||
|
for domain, nameservers in section.items():
|
||||||
|
yield Service(item=domain)
|
||||||
|
|
||||||
|
|
||||||
|
def check_domains_nameservers(item, params, section):
|
||||||
|
nameservers = section.get(item)
|
||||||
|
if not nameservers:
|
||||||
|
yield Result(state=State.WARN, summary="Nameservers missing")
|
||||||
|
return
|
||||||
|
|
||||||
|
configs = params.get("domain_nameservers")
|
||||||
|
if not configs:
|
||||||
|
yield Result(state=State.WARN, summary="No nameservers check rule configured")
|
||||||
|
return
|
||||||
|
|
||||||
|
alert_level = params["alert_level"]
|
||||||
|
|
||||||
|
nameservers.sort()
|
||||||
|
|
||||||
|
domain_found = False
|
||||||
|
|
||||||
|
for config in configs:
|
||||||
|
domains = config["domains"]
|
||||||
|
|
||||||
|
if item in domains:
|
||||||
|
domain_found = True
|
||||||
|
|
||||||
|
expected_nameservers = config["nameservers"]
|
||||||
|
expected_nameservers.sort()
|
||||||
|
|
||||||
|
if expected_nameservers == nameservers:
|
||||||
|
yield Result(state=State.OK, summary="Expected nameservers present")
|
||||||
|
else:
|
||||||
|
expected_str = ", ".join(expected_nameservers)
|
||||||
|
found_str = ", ".join(nameservers)
|
||||||
|
yield Result(state=State(alert_level), summary="Mismatch in nameservers. Expected: [%s], Found: [%s]" % (expected_str, found_str))
|
||||||
|
|
||||||
|
if not domain_found:
|
||||||
|
yield Result(state=State.WARN, summary="Domain not found in any nameserver check rule")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
register.agent_section(
|
||||||
|
name="domains_nameservers",
|
||||||
|
parse_function=parse_domains_nameservers
|
||||||
|
)
|
||||||
|
|
||||||
|
register.check_plugin(
|
||||||
|
name="domains_nameservers",
|
||||||
|
service_name="Nameservers for Domain '%s'",
|
||||||
|
|
||||||
|
discovery_function=discover_domains_nameservers,
|
||||||
|
|
||||||
|
check_function=check_domains_nameservers,
|
||||||
|
check_default_parameters={},
|
||||||
|
check_ruleset_name="domains_nameservers",
|
||||||
|
)
|
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Copyright (C) 2025 Spearhead Systems SRL
|
||||||
|
|
||||||
|
echo "<<<domains_expiry:sep(0)>>>"
|
||||||
|
for domain in "$@"; do
|
||||||
|
echo "$domain:"
|
||||||
|
whois "$domain" | grep 'Expir.*' | head -1 | grep -Eo '[0-9]{4}-[0-9]{2}-[0-9]{2}'
|
||||||
|
done
|
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Copyright (C) 2025 Spearhead Systems SRL
|
||||||
|
|
||||||
|
echo "<<<domains_nameservers:sep(0)>>>"
|
||||||
|
for domain in "$@"; do
|
||||||
|
echo "$domain:"
|
||||||
|
dig +short NS "$domain"
|
||||||
|
done
|
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2025 Spearhead Systems SRL
|
||||||
|
|
||||||
|
def agent_domains_expiry_args(params, hostname, ipaddress):
|
||||||
|
return params["domains"]
|
||||||
|
|
||||||
|
special_agent_info["domains_expiry"] = agent_domains_expiry_args
|
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2025 Spearhead Systems SRL
|
||||||
|
|
||||||
|
def agent_domains_nameservers_args(params, hostname, ipaddress):
|
||||||
|
return params["domains"]
|
||||||
|
|
||||||
|
special_agent_info["domains_nameservers"] = agent_domains_nameservers_args
|
@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2025 Spearhead Systems SRL
|
||||||
|
|
||||||
|
import copy
|
||||||
|
from cmk.base.plugins.agent_based.agent_based_api.v1 import State
|
||||||
|
from cmk.gui.i18n import _
|
||||||
|
from cmk.gui.plugins.wato.utils import (
|
||||||
|
rulespec_registry,
|
||||||
|
HostRulespec,
|
||||||
|
RulespecGroupCheckParametersNetworking,
|
||||||
|
)
|
||||||
|
from cmk.gui.watolib.rulespecs import Rulespec
|
||||||
|
from cmk.gui.valuespec import (
|
||||||
|
Dictionary,
|
||||||
|
Integer,
|
||||||
|
ListOfStrings,
|
||||||
|
Tuple,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _valuespec_special_agents_domains_expiry_query():
|
||||||
|
return Dictionary(
|
||||||
|
title=_("Domains Expiry Query"),
|
||||||
|
required_keys=["domains"],
|
||||||
|
elements=[
|
||||||
|
(
|
||||||
|
"domains",
|
||||||
|
ListOfStrings(
|
||||||
|
title=_("Domain names"),
|
||||||
|
help=_("List of domain names to check"),
|
||||||
|
allow_empty=False,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def _valuespec_special_agents_domains_expiry_checks():
|
||||||
|
return Dictionary(
|
||||||
|
title=_("Domains Expiry"),
|
||||||
|
required_keys=["days_remaining"],
|
||||||
|
elements=[
|
||||||
|
(
|
||||||
|
"days_remaining",
|
||||||
|
Tuple(
|
||||||
|
title=_("Days Remaining"),
|
||||||
|
help=_("If there are fewer days until one of the above domains expires, issue an alert"),
|
||||||
|
elements=[
|
||||||
|
Integer(
|
||||||
|
title=_("Warn if fewer days than"),
|
||||||
|
minvalue=0,
|
||||||
|
default_value=30
|
||||||
|
),
|
||||||
|
Integer(
|
||||||
|
title=_("Crit if fewer days than"),
|
||||||
|
minvalue=0,
|
||||||
|
default_value=7
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
rulespec_registry.register(
|
||||||
|
HostRulespec(
|
||||||
|
name="special_agents:domains_expiry",
|
||||||
|
group=RulespecGroupCheckParametersNetworking,
|
||||||
|
match_type='dict',
|
||||||
|
valuespec=_valuespec_special_agents_domains_expiry_query,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
rulespec_registry.register(
|
||||||
|
CheckParameterRulespecWithItem(
|
||||||
|
check_group_name="domains_expiry",
|
||||||
|
group=RulespecGroupCheckParametersNetworking,
|
||||||
|
match_type="dict",
|
||||||
|
parameter_valuespec=_valuespec_special_agents_domains_expiry_checks,
|
||||||
|
item_spec=lambda: TextInput(title=_("Expiry")),
|
||||||
|
title=lambda: _("Domains Expiry Checks"),
|
||||||
|
)
|
||||||
|
)
|
@ -0,0 +1,103 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2025 Spearhead Systems SRL
|
||||||
|
|
||||||
|
import copy
|
||||||
|
from cmk.base.plugins.agent_based.agent_based_api.v1 import State
|
||||||
|
from cmk.gui.i18n import _
|
||||||
|
from cmk.gui.plugins.wato.utils import (
|
||||||
|
rulespec_registry,
|
||||||
|
HostRulespec,
|
||||||
|
RulespecGroupCheckParametersNetworking,
|
||||||
|
)
|
||||||
|
from cmk.gui.watolib.rulespecs import Rulespec
|
||||||
|
from cmk.gui.valuespec import (
|
||||||
|
Dictionary,
|
||||||
|
Integer,
|
||||||
|
ListOfStrings,
|
||||||
|
DropdownChoice,
|
||||||
|
Tuple,
|
||||||
|
ListOf,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _valuespec_special_agents_domains_nameservers_query():
|
||||||
|
return Dictionary(
|
||||||
|
title=_("Domains Nameservers Query"),
|
||||||
|
required_keys=["domains"],
|
||||||
|
elements=[
|
||||||
|
(
|
||||||
|
"domains",
|
||||||
|
ListOfStrings(
|
||||||
|
title=_("Domain names"),
|
||||||
|
help=_("List of domain names to check"),
|
||||||
|
allow_empty=False,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def _valuespec_special_agents_domains_nameservers_checks():
|
||||||
|
return Dictionary(
|
||||||
|
title=_("Domains Nameservers Checks"),
|
||||||
|
required_keys=["domain_nameservers", "alert_level"],
|
||||||
|
elements=[
|
||||||
|
(
|
||||||
|
"domain_nameservers",
|
||||||
|
ListOf(
|
||||||
|
valuespec=Dictionary(
|
||||||
|
required_keys=["domains", "nameservers"],
|
||||||
|
elements=[
|
||||||
|
(
|
||||||
|
"domains",
|
||||||
|
ListOfStrings(
|
||||||
|
title=_("Domain names"),
|
||||||
|
help=_("List of domain names the below nameservers apply to"),
|
||||||
|
allow_empty=False,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"nameservers",
|
||||||
|
ListOfStrings(
|
||||||
|
title=_("Nameservers"),
|
||||||
|
help=_("List of nameservers that all of the above domain names should have"),
|
||||||
|
allow_empty=False,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"alert_level",
|
||||||
|
DropdownChoice(
|
||||||
|
title=_("Alert level used on mismatch"),
|
||||||
|
help=_("Alert level used when there is a mismatch in domain name servers for a domain"),
|
||||||
|
default_value=State.WARN.value,
|
||||||
|
choices=[
|
||||||
|
(State.CRIT.value, _(State.CRIT.name)),
|
||||||
|
(State.WARN.value, _(State.WARN.name)),
|
||||||
|
(State.OK.value, _(State.OK.name)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
rulespec_registry.register(
|
||||||
|
HostRulespec(
|
||||||
|
name="special_agents:domains_nameservers",
|
||||||
|
group=RulespecGroupCheckParametersNetworking,
|
||||||
|
match_type='dict',
|
||||||
|
valuespec=_valuespec_special_agents_domains_nameservers_query,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
rulespec_registry.register(
|
||||||
|
CheckParameterRulespecWithItem(
|
||||||
|
check_group_name="domains_nameservers",
|
||||||
|
group=RulespecGroupCheckParametersNetworking,
|
||||||
|
match_type="dict",
|
||||||
|
parameter_valuespec=_valuespec_special_agents_domains_nameservers_checks,
|
||||||
|
item_spec=lambda: TextInput(title=_("Nameserver")),
|
||||||
|
title=lambda: _("Domains Nameservers Checks"),
|
||||||
|
)
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user