diff --git a/azure-keyvault/local/lib/check_mk/base/plugins/agent_based/azure_keyvault.py b/azure-keyvault/2.2/local/lib/check_mk/base/plugins/agent_based/azure_keyvault.py similarity index 100% rename from azure-keyvault/local/lib/check_mk/base/plugins/agent_based/azure_keyvault.py rename to azure-keyvault/2.2/local/lib/check_mk/base/plugins/agent_based/azure_keyvault.py diff --git a/azure-keyvault/local/share/check_mk/agents/special/agent_azure_keyvault b/azure-keyvault/2.2/local/share/check_mk/agents/special/agent_azure_keyvault similarity index 100% rename from azure-keyvault/local/share/check_mk/agents/special/agent_azure_keyvault rename to azure-keyvault/2.2/local/share/check_mk/agents/special/agent_azure_keyvault diff --git a/azure-keyvault/local/share/check_mk/checks/agent_azure_keyvault b/azure-keyvault/2.2/local/share/check_mk/checks/agent_azure_keyvault similarity index 100% rename from azure-keyvault/local/share/check_mk/checks/agent_azure_keyvault rename to azure-keyvault/2.2/local/share/check_mk/checks/agent_azure_keyvault diff --git a/azure-keyvault/local/share/check_mk/web/plugins/wato/azure_keyvault.py b/azure-keyvault/2.2/local/share/check_mk/web/plugins/wato/azure_keyvault.py similarity index 100% rename from azure-keyvault/local/share/check_mk/web/plugins/wato/azure_keyvault.py rename to azure-keyvault/2.2/local/share/check_mk/web/plugins/wato/azure_keyvault.py diff --git a/azure-keyvault/2.3/azure_keyvault-0.4.0.mkp b/azure-keyvault/2.3/azure_keyvault-0.4.0.mkp new file mode 100755 index 0000000..2fcc3bc Binary files /dev/null and b/azure-keyvault/2.3/azure_keyvault-0.4.0.mkp differ diff --git a/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/agent_based/azure_keyvault.py b/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/agent_based/azure_keyvault.py new file mode 100644 index 0000000..5c7809c --- /dev/null +++ b/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/agent_based/azure_keyvault.py @@ -0,0 +1,71 @@ +#,!/usr/bin/env python3 +# Copyright (C) 2025 Spearhead Systems SRL - License: GNU General Public License v2 + +import json +from datetime import datetime, timezone +from cmk.agent_based.v2 import Result, Service, State, CheckPlugin, AgentSection + + +# Convert JSON entries into dictionaries indexed by certificate name. +def parse_keyvault(string_table): + raw_json = "" + cert_data = [] + + for row in string_table: + line = row[0] + raw_json += line + if line == "]": + cert_data.extend(json.loads(raw_json)) + raw_json = "" + + lookup = {} + for cert in cert_data: + lookup[cert["name"]] = cert + + return lookup + + +# Produce a list of certificates based on the parsed output. +def discover_keyvault(section): + for name, details in sorted(section.items()): + yield Service(item=name) + + +# Given a specific certificate, look it up in the parsed output, and produce +# results on that service based upon the certificate's expiry. +def check_keyvault(item, params, section): + warn_days = params.get("warn_days") + crit_days = params.get("crit_days") + + cert = section.get(item) + if cert is None: + return + + expires = datetime.fromisoformat(cert["attributes"]["expires"]) + now = datetime.now(timezone.utc) + remaining_days = (expires - now).days + + state = State.OK + if crit_days is not None and remaining_days < crit_days: + state = State.CRIT + elif warn_days is not None and remaining_days < warn_days: + state = State.WARN + + yield Result(state=state, summary="Expires in %d days" % remaining_days) + + +agent_section_azure_keyvault = AgentSection( + name="azure_keyvault", + parse_function=parse_keyvault, +) + +check_plugin_azure_keyvault = CheckPlugin( + name="azure_keyvault", + service_name="Azure Keyvault Certificate %s", + + check_function=check_keyvault, + check_default_parameters={}, + check_ruleset_name="azure_keyvault", + + discovery_function=discover_keyvault, +) diff --git a/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/libexec/agent_azure_keyvault b/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/libexec/agent_azure_keyvault new file mode 100755 index 0000000..c594dcd --- /dev/null +++ b/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/libexec/agent_azure_keyvault @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright (C) 2023 Spearhead Systems SRL - License: GNU General Public License v2 + +az=/usr/bin/az + +set -euo pipefail + +if [ "$#" -lt 4 ]; then + echo "Usage: $0 ... [vaultN]" >&2 + exit 1 +fi + +tenant="$1" +user="$2" +password="$3" +vaults="${@:4}" + +echo "<<>>" + +"$az" login --service-principal --tenant="$tenant" --user="$user" --password="$password" > /dev/null + +for vault in $vaults; do + "$az" keyvault certificate list --vault-name="$vault" +done + +"$az" logout diff --git a/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/rulesets/azure_keyvault.py b/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/rulesets/azure_keyvault.py new file mode 100644 index 0000000..edd5e67 --- /dev/null +++ b/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/rulesets/azure_keyvault.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# Copyright (C) 2025 Spearhead Systems SRL - License: GNU General Public License v2 + +from cmk.rulesets.v1 import Label +from cmk.rulesets.v1.form_specs import Dictionary, DictElement, String, Integer, Password, List, DefaultValue +from cmk.rulesets.v1.rule_specs import SpecialAgent, CheckParameters, HostCondition, Topic, Title, Help +from cmk.rulesets.v1.form_specs.validators import LengthInRange, NumberInRange + + +def _formspec_azure_keyvault_check(): + return Dictionary( + title = Title("Azure Key Vault Certificate Checks"), + elements = { + "warn_days": DictElement( + parameter_form = Integer( + title = Title("Certificate Days to Warn"), + help_text = Help("How many days to warn before a certificate in this key vault will expire"), + prefill = DefaultValue(30), + custom_validate = (NumberInRange(min_value=0),), + ), + ), + "crit_days": DictElement( + parameter_form = Integer( + title = Title("Certificate Days to Crit"), + help_text = Help("How many days to crit before a certificate in this key vault will expire"), + prefill = DefaultValue(3), + custom_validate = (NumberInRange(min_value=0),), + ), + ), + }, + ) + + +def _formspec_azure_keyvault_discovery(): + return Dictionary( + title = Title("Azure Key Vault Certificate Discovery"), + elements = { + "tenant": DictElement( + required = True, + parameter_form = String( + title = Title("Tenant ID / Directory ID"), + custom_validate = (LengthInRange(min_value=1),), + ), + ), + "client": DictElement( + required = True, + parameter_form = String( + title = Title("Client ID / Application ID"), + custom_validate = (LengthInRange(min_value=1),), + ), + ), + "secret": DictElement( + required = True, + parameter_form = Password( + title = Title("Client Secret"), + custom_validate = (LengthInRange(min_value=1),), + ), + ), + "vaults": DictElement( + required = True, + parameter_form = List( + title = Title("Keyvaults"), + add_element_label = Label("Add new keyvault"), + custom_validate = (LengthInRange(min_value=1),), + element_template = String(label=Label("Keyvault")), + ), + ), + }, + ) + + +rule_spec_agent_config_azure_keyvault = SpecialAgent( + topic = Topic.NETWORKING, + name = "azure_keyvault", + title = Title("Azure Keyvault"), + parameter_form = _formspec_azure_keyvault_discovery, +) + + +rule_spec_agent_config_azure_keyvault_check = CheckParameters( + topic = Topic.NETWORKING, + name = "azure_keyvault", + title = Title("Azure Keyvault Check"), + parameter_form = _formspec_azure_keyvault_check, + condition = HostCondition(), +) + +#check_plugin_juniper_trpz_cpu_util = CheckPlugin( +# name="juniper_trpz_cpu_util", +# service_name="CPU utilization", +# discovery_function=discovery_juniper_trpz_cpu_util, +# check_function=check_juniper_trpz_cpu_util, +# check_ruleset_name="cpu_utilization", +# check_default_parameters={"util": (80.0, 90.0)}, +#) diff --git a/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/server_side_calls/special_agent.py b/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/server_side_calls/special_agent.py new file mode 100644 index 0000000..bae5884 --- /dev/null +++ b/azure-keyvault/2.3/local/lib/python3/cmk_addons/plugins/azure_keyvault/server_side_calls/special_agent.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# Copyright (C) 2025 Spearhead Systems SRL - License: GNU General Public License v2 + +from cmk.server_side_calls.v1 import noop_parser, SpecialAgentConfig, SpecialAgentCommand + + +def agent_azure_keyvault(params, hostname): + tenant = params["tenant"] + client = params["client"] + secret = params["secret"] + + if type(secret) != str: + secret = secret.unsafe() + + args = [tenant, client, secret] + + for vault in params["vaults"]: + args.extend([vault.strip()]) + + yield SpecialAgentCommand(command_arguments=args) + + +special_agent_azure_keyvault = SpecialAgentConfig( + name = "azure_keyvault", + parameter_parser = noop_parser, + commands_function = agent_azure_keyvault, +)