Dotfiles/setup/modules/FreeipaAnsible/image/ansipa-infra-checkmk-instal...

213 lines
9.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# ansipa-infra-checkmk-install.sh — wire a Proxmox VE hypervisor or a Proxmox
# Backup Server into the ansipa CheckMK instance.
#
# Unlike regular ansipa clients (enrolled in FreeIPA, driven by the
# dev_mon_base host-group via ansipa-enforce-policies.sh), PVE/PBS hosts are
# infrastructure appliances that are not FreeIPA members — so this script
# does the same job (install agent, drop the local check, register with
# CheckMK) standalone, taking the CheckMK automation credentials directly
# instead of reading them from an IPA hostgroup description.
#
# Usage:
# ansipa-infra-checkmk-install.sh <CMK_URL> <CMK_SITE> <CMK_SECRET> [HOST_FQDN] [CMK_USER]
#
# CMK_URL e.g. http://mon.corp.example.com:8090 (client-routable — see
# CMK_ADVERTISED_URL in image/.env.example)
# CMK_SITE OMD site name, e.g. "cmk"
# CMK_SECRET automation user's secret (CheckMK → Users → automation → API secret)
# HOST_FQDN defaults to `hostname -f`
# CMK_USER defaults to "automation"
#
# Run as root on the PVE or PBS host itself. Re-run any time to pick up a new
# secret or to re-register after a host rename — it is idempotent.
set -euo pipefail
LOG_TAG="ansipa-infra-checkmk"
log() { echo "[$LOG_TAG] $*"; }
warn() { echo "[$LOG_TAG][WARN] $*" >&2; }
die() { echo "[$LOG_TAG][ERROR] $*" >&2; exit 1; }
[[ $EUID -eq 0 ]] || die "Run as root."
[[ $# -ge 3 ]] || die "Usage: $0 <CMK_URL> <CMK_SITE> <CMK_SECRET> [HOST_FQDN] [CMK_USER]"
CMK_URL="${1%/}"
CMK_SITE="$2"
CMK_SECRET="$3"
HOST_FQDN="${4:-$(hostname -f 2>/dev/null || hostname)}"
CMK_USER="${5:-automation}"
CMK_API="${CMK_URL}/${CMK_SITE}/check_mk/api/1.0"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOCAL_DIR="/usr/lib/check_mk_agent/local"
# ── Detect role ────────────────────────────────────────────────────────────
ROLE=""
if command -v pveversion &>/dev/null; then
ROLE="pve"
elif command -v proxmox-backup-manager &>/dev/null; then
ROLE="pbs"
else
die "Neither pveversion nor proxmox-backup-manager found — is this a PVE/PBS host?"
fi
MONITOR_SRC="$SCRIPT_DIR/ansipa-${ROLE}-monitor.sh"
[[ -f "$MONITOR_SRC" ]] || die "Companion script not found: $MONITOR_SRC"
log "Detected role: $ROLE (${HOST_FQDN})"
# ── Install CheckMK agent (Debian .deb — PVE/PBS are Debian-based) ──────────
_AGENT_INSTALLED=false
if dpkg -s check-mk-agent &>/dev/null || command -v check_mk_agent &>/dev/null; then
_AGENT_INSTALLED=true
log "CheckMK agent already installed"
else
log "Downloading CheckMK agent from ${CMK_URL}"
_DEB=$(curl -sf -u "${CMK_USER}:${CMK_SECRET}" \
"${CMK_URL}/${CMK_SITE}/check_mk/agents/" 2>/dev/null \
| grep -oE 'check-mk-agent_[^"]*_all\.deb' | head -1 || true)
if [[ -n "$_DEB" ]]; then
curl -sf -u "${CMK_USER}:${CMK_SECRET}" \
"${CMK_URL}/${CMK_SITE}/check_mk/agents/${_DEB}" \
-o /tmp/cmk-agent.deb 2>/dev/null \
&& (dpkg -i /tmp/cmk-agent.deb 2>/dev/null || apt-get install -y -f 2>/dev/null) \
&& dpkg -s check-mk-agent &>/dev/null \
&& _AGENT_INSTALLED=true \
|| warn "CheckMK .deb install failed"
rm -f /tmp/cmk-agent.deb
fi
if [[ "$_AGENT_INSTALLED" == false ]]; then
log "Falling back to the shell agent"
curl -sf -u "${CMK_USER}:${CMK_SECRET}" \
"${CMK_URL}/${CMK_SITE}/check_mk/agents/check_mk_agent.linux" \
-o /usr/local/bin/check_mk_agent 2>/dev/null \
&& chmod 755 /usr/local/bin/check_mk_agent \
&& _AGENT_INSTALLED=true \
|| die "Shell agent download failed — check CMK_URL/CMK_SITE/CMK_SECRET"
fi
fi
# ── Serve the agent: enable the package's own socket, or roll our own ───────
if systemctl list-unit-files 2>/dev/null | grep -q '^check-mk-agent\.socket'; then
systemctl enable --now check-mk-agent.socket 2>/dev/null \
&& log "check-mk-agent.socket enabled" \
|| warn "could not enable check-mk-agent.socket"
elif [[ ! -f /etc/systemd/system/check_mk.socket ]]; then
cat > /etc/systemd/system/check_mk.socket <<'UNIT'
[Unit]
Description=Check_MK agent socket (ansipa-managed)
[Socket]
ListenStream=6556
Accept=yes
[Install]
WantedBy=sockets.target
UNIT
cat > /etc/systemd/system/check_mk@.service <<'UNIT'
[Unit]
Description=Check_MK per-connection agent (ansipa-managed)
[Service]
ExecStart=/usr/local/bin/check_mk_agent
StandardInput=socket
StandardOutput=socket
StandardError=null
UNIT
systemctl daemon-reload
systemctl enable --now check_mk.socket 2>/dev/null \
&& log "check_mk.socket enabled (port 6556)" \
|| warn "could not enable check_mk.socket"
fi
# ── Drop in the local check ──────────────────────────────────────────────────
mkdir -p "$LOCAL_DIR"
install -m 755 "$MONITOR_SRC" "$LOCAL_DIR/ansipa_${ROLE}"
log "Installed local check: $LOCAL_DIR/ansipa_${ROLE}"
# ── cmk-agent-ctl: register for TLS/push transport (useful behind NAT) ──────
if command -v cmk-agent-ctl &>/dev/null; then
_RECV_HOST=$(echo "$CMK_URL" | sed 's|https\?://||;s|:.*||')
_ALREADY_CTL=$(cmk-agent-ctl status 2>/dev/null | grep -c "${_RECV_HOST}/${CMK_SITE}" || true)
if [[ "${_ALREADY_CTL:-0}" -eq 0 ]]; then
cmk-agent-ctl register \
--server "${_RECV_HOST}:8000" \
--site "${CMK_SITE}" \
--user "${CMK_USER}" \
--password "${CMK_SECRET}" \
--hostname "${HOST_FQDN}" \
--trust-cert &>/dev/null \
&& log "cmk-agent-ctl registered with ${_RECV_HOST}:8000" \
|| warn "cmk-agent-ctl registration failed (non-fatal — pull mode still works if reachable)"
fi
_CTL_MODE=$(cmk-agent-ctl status 2>/dev/null | awk '/Connection mode:/{print $NF; exit}')
if [[ "$_CTL_MODE" == "push-agent" ]]; then
cmk-agent-ctl push 2>/dev/null || true
if [[ ! -f /etc/systemd/system/cmk-agent-push.timer ]]; then
cat > /etc/systemd/system/cmk-agent-push.service <<'UNIT'
[Unit]
Description=CheckMK agent push (ansipa-managed)
[Service]
Type=oneshot
ExecStart=/usr/bin/cmk-agent-ctl push
UNIT
cat > /etc/systemd/system/cmk-agent-push.timer <<'UNIT'
[Unit]
Description=CheckMK agent push timer (ansipa-managed)
[Timer]
OnBootSec=30s
OnUnitActiveSec=60s
[Install]
WantedBy=timers.target
UNIT
systemctl daemon-reload
systemctl enable --now cmk-agent-push.timer 2>/dev/null \
&& log "cmk-agent-push.timer enabled (push every 60s)" \
|| warn "could not enable push timer"
fi
fi
fi
# ── Register the host in CheckMK (folder /ansipa/infra) ─────────────────────
_folder_result=$(curl -sf -o /dev/null -w '%{http_code}' \
-X POST "${CMK_API}/domain-types/folder_config/collections/all" \
-H "Authorization: Bearer ${CMK_USER} ${CMK_SECRET}" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"name":"infra","title":"Ansipa Infra (PVE/PBS)","parent":"/ansipa"}' \
2>/dev/null || echo "000")
[[ "$_folder_result" =~ ^2 || "$_folder_result" == "422" ]] \
|| warn "Unexpected response creating /ansipa/infra folder: HTTP $_folder_result"
_HOST_IP=$(hostname -I 2>/dev/null | awk '{print $1}' || echo "")
_ALREADY_REG=false
curl -sf -o /dev/null \
-H "Authorization: Bearer ${CMK_USER} ${CMK_SECRET}" \
"${CMK_API}/objects/host_config/${HOST_FQDN}" 2>/dev/null && _ALREADY_REG=true || true
if [[ "$_ALREADY_REG" == false ]]; then
_reg_body="{\"host_name\":\"${HOST_FQDN}\",\"folder\":\"/ansipa/infra\""
[[ -n "$_HOST_IP" ]] && _reg_body+=",\"attributes\":{\"ipaddress\":\"${_HOST_IP}\",\"tag_role\":\"${ROLE}\"}"
_reg_body+="}"
_reg_http=$(curl -sf -o /dev/null -w '%{http_code}' \
-X POST "${CMK_API}/domain-types/host_config/collections/all" \
-H "Authorization: Bearer ${CMK_USER} ${CMK_SECRET}" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d "$_reg_body" 2>/dev/null || echo "000")
if [[ "$_reg_http" =~ ^2 ]]; then
log "Registered ${HOST_FQDN} in CheckMK (/ansipa/infra)"
else
warn "Host registration failed (HTTP ${_reg_http}) — add it manually in the CheckMK UI"
fi
else
log "${HOST_FQDN} already registered in CheckMK"
fi
curl -sf -X POST "${CMK_API}/domain-types/service_discovery_run/actions/start/invoke" \
-H "Authorization: Bearer ${CMK_USER} ${CMK_SECRET}" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d "{\"host_name\":\"${HOST_FQDN}\",\"mode\":\"refresh\"}" >/dev/null 2>&1 || true
curl -sf -X POST "${CMK_API}/domain-types/activation_run/actions/activate-changes/invoke" \
-H "Authorization: Bearer ${CMK_USER} ${CMK_SECRET}" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"redirect":false,"sites":[],"force_foreign_changes":true}' >/dev/null 2>&1 || true
log "Done. ${HOST_FQDN} (${ROLE}) should appear under CheckMK folder /ansipa/infra within a minute."