213 lines
9.2 KiB
Bash
Executable File
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."
|