187 lines
8.3 KiB
Bash
187 lines
8.3 KiB
Bash
#!/bin/bash
|
|
# ansipa-checkmk-setup.sh — CheckMK CE integration for the IPA container.
|
|
#
|
|
# Phase 1 (one-time, guarded by /data/ansipa-checkmk.done):
|
|
# Creates /ansipa folder, IPA monitoring groups, stores CMK credentials.
|
|
#
|
|
# Phase 2 (runs every invocation after phase 1):
|
|
# Writes push-mode requests for all hosts in dev_mon_base to /cmk-creds/.
|
|
# The CheckMK container polls /cmk-creds/push-mode-*.req and updates hosts.mk.
|
|
# This lets clients in NAT environments push agent data without pull reachability.
|
|
#
|
|
# Credential format in IPA dev_mon_base description:
|
|
# cmk://<host>:<port>/<site>:automation:<secret>
|
|
|
|
set -euo pipefail
|
|
|
|
LOG_TAG="ansipa-checkmk-setup"
|
|
DONE_FLAG="/data/ansipa-checkmk.done"
|
|
CMK_CREDS_FILE="/cmk-creds/automation.secret"
|
|
|
|
log() { echo "[$LOG_TAG] $*"; }
|
|
warn() { echo "[$LOG_TAG][WARN] $*" >&2; }
|
|
|
|
# ── Phase 2: write push-mode requests for enrolled monitoring hosts ───────────
|
|
# Runs on EVERY invocation (not guarded by done flag). The CheckMK container
|
|
# polls /cmk-creds/push-mode-*.req and adds explicit_host_conf push-agent entries.
|
|
_write_push_requests() {
|
|
[[ -d /cmk-creds ]] || return 0
|
|
local _hosts _h
|
|
# `ipa hostgroup-show` prints members on the SAME line as the label
|
|
# (" Member hosts: a.example, b.example") and wraps long lists onto
|
|
# indented continuation lines. Capture the label line's own value AND any
|
|
# continuation lines, stopping at the next " Key:" field. (The previous
|
|
# awk did `next` on the label line, discarding the very line that holds the
|
|
# hostnames, so no host was ever extracted and no push request written.)
|
|
_hosts=$(ipa hostgroup-show dev_mon_base --all 2>/dev/null \
|
|
| awk '
|
|
/^ [A-Za-z][A-Za-z0-9 _-]*:/ {
|
|
if ($0 ~ /Member hosts:/) { sub(/.*Member hosts:[[:space:]]*/, ""); p=1; print; next }
|
|
else { p=0 }
|
|
}
|
|
p { print }
|
|
' \
|
|
| grep -oE '[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}' | sort -u || true)
|
|
[[ -z "$_hosts" ]] && return 0
|
|
while IFS= read -r _h; do
|
|
[[ -z "$_h" ]] && continue
|
|
_req="/cmk-creds/push-mode-${_h}.req"
|
|
[[ -f "$_req" ]] && continue
|
|
echo "$_h" > "$_req" && log "Push-mode request created for ${_h}"
|
|
done <<< "$_hosts"
|
|
}
|
|
|
|
# ── Resolve configuration ──────────────────────────────────────────────────────
|
|
# Must run BEFORE the DONE_FLAG early-exit: that path calls _write_push_requests,
|
|
# which needs IPA_REALM + IPA_ADMIN_PASS to kinit. Previously these were resolved
|
|
# only after the early exit, so every rerun kinit'd with an empty password, failed
|
|
# silently, and never wrote push-mode requests — leaving NAT'd clients stuck in
|
|
# pull mode (unreachable) forever.
|
|
# docker-env.service writes container env to /etc/container.env; source it.
|
|
[[ -f /etc/container.env ]] && source /etc/container.env || true
|
|
|
|
CMK_URL="${CMK_URL:-http://172.30.0.12:5000}"
|
|
CMK_SITE="${CMK_SITE_ID:-cmk}"
|
|
CMK_API="${CMK_URL}/${CMK_SITE}/check_mk/api/1.0"
|
|
IPA_REALM="${IPA_REALM:-}"
|
|
IPA_ADMIN_PASS="${IPA_ADMIN_PASSWORD:-}"
|
|
|
|
# Skip re-initialization but still run push-mode requests if already set up
|
|
if [[ -f "$DONE_FLAG" ]]; then
|
|
if [[ -f /etc/ipa/default.conf && -n "$IPA_ADMIN_PASS" && -n "$IPA_REALM" ]]; then
|
|
echo "$IPA_ADMIN_PASS" | kinit "admin@${IPA_REALM}" &>/dev/null \
|
|
&& _write_push_requests 2>/dev/null
|
|
kdestroy &>/dev/null || true
|
|
fi
|
|
log "Already configured (delete $DONE_FLAG to force re-initialization)"
|
|
exit 0
|
|
fi
|
|
|
|
if [[ -z "$IPA_REALM" || -z "$IPA_ADMIN_PASS" ]]; then
|
|
warn "IPA_REALM or IPA_ADMIN_PASSWORD not set — cannot configure IPA side"
|
|
exit 1
|
|
fi
|
|
|
|
# ── Wait for IPA to be fully configured ──────────────────────────────────────
|
|
if [[ ! -f /etc/ipa/default.conf ]]; then
|
|
warn "IPA not yet configured — waiting for ipa-first-boot to complete"
|
|
exit 1
|
|
fi
|
|
|
|
# ── Wait for CheckMK automation secret (written by checkmk container) ─────────
|
|
if [[ ! -f "$CMK_CREDS_FILE" ]]; then
|
|
warn "CheckMK automation secret not yet available at $CMK_CREDS_FILE"
|
|
warn " (CheckMK container writes it after site init — will retry)"
|
|
exit 1
|
|
fi
|
|
CMK_SECRET=$(tr -d '[:space:]' < "$CMK_CREDS_FILE")
|
|
if [[ -z "$CMK_SECRET" ]]; then
|
|
warn "CheckMK automation secret is empty — CheckMK not ready yet"
|
|
exit 1
|
|
fi
|
|
|
|
# ── Wait for CheckMK web API (use automation secret — no admin password needed) ──
|
|
log "Waiting for CheckMK API at ${CMK_API}..."
|
|
_wait=0
|
|
until curl -sf \
|
|
-H "Authorization: Bearer automation ${CMK_SECRET}" \
|
|
"${CMK_API}/version" >/dev/null 2>&1; do
|
|
_wait=$(( _wait + 15 ))
|
|
if [[ $_wait -ge 300 ]]; then
|
|
warn "CheckMK API not reachable after 5 minutes — will retry on next start"
|
|
exit 1
|
|
fi
|
|
sleep 15
|
|
done
|
|
log "CheckMK API is up"
|
|
|
|
# ── Create /ansipa folder in CheckMK ─────────────────────────────────────────
|
|
_folder_result=$(curl -sf -o /dev/null -w '%{http_code}' \
|
|
-X POST "${CMK_API}/domain-types/folder_config/collections/all" \
|
|
-H "Authorization: Bearer automation ${CMK_SECRET}" \
|
|
-H "Content-Type: application/json" \
|
|
-H "Accept: application/json" \
|
|
-d '{"name":"ansipa","title":"Ansipa Managed Hosts","parent":"/"}' \
|
|
2>/dev/null || echo "000")
|
|
if [[ "$_folder_result" =~ ^2 ]]; then
|
|
log "Created /ansipa folder in CheckMK"
|
|
elif [[ "$_folder_result" == "422" ]]; then
|
|
log "/ansipa folder already exists"
|
|
else
|
|
warn "Unexpected response creating /ansipa folder: HTTP $_folder_result"
|
|
fi
|
|
|
|
# ── Activate changes in CheckMK ───────────────────────────────────────────────
|
|
curl -sf \
|
|
-X POST "${CMK_API}/domain-types/activation_run/actions/activate-changes/invoke" \
|
|
-H "Authorization: Bearer automation ${CMK_SECRET}" \
|
|
-H "Content-Type: application/json" \
|
|
-H "Accept: application/json" \
|
|
-d '{"redirect":false,"sites":[],"force_foreign_changes":false}' \
|
|
>/dev/null 2>&1 && log "Changes activated" || warn "Activation failed (non-fatal)"
|
|
|
|
# ── Store CheckMK credentials in IPA host-group descriptions ─────────────────
|
|
# Format: cmk://<host>:<port>/<site>:automation:<secret>
|
|
# CMK_ADVERTISED_URL is what CLIENTS use to reach CheckMK. It must be a
|
|
# host-routable address (e.g. http://<docker-host>:8090), NOT the container's
|
|
# internal 172.30.0.x address — clients outside the docker network cannot
|
|
# reach that, and every dev_mon_* policy would silently fail to register.
|
|
# Falls back to CMK_URL for docker-network-internal test setups.
|
|
CMK_CLIENT_URL="${CMK_ADVERTISED_URL:-$CMK_URL}"
|
|
CMK_HOST=$(echo "$CMK_CLIENT_URL" | sed 's|http://||')
|
|
CMK_DESC="cmk://${CMK_HOST}/${CMK_SITE}:automation:${CMK_SECRET}"
|
|
|
|
echo "$IPA_ADMIN_PASS" | kinit "admin@${IPA_REALM}" &>/dev/null || {
|
|
warn "kinit admin failed"
|
|
exit 1
|
|
}
|
|
|
|
# dev_mon_base stores the credentials; clients parse them to register.
|
|
if ipa hostgroup-show dev_mon_base &>/dev/null 2>&1; then
|
|
ipa hostgroup-mod dev_mon_base --desc="$CMK_DESC" &>/dev/null \
|
|
&& log "Updated dev_mon_base description with CMK credentials"
|
|
else
|
|
ipa hostgroup-add dev_mon_base --desc="$CMK_DESC" &>/dev/null \
|
|
&& log "Created IPA hostgroup dev_mon_base with CMK credentials"
|
|
fi
|
|
|
|
# Create supplementary monitoring host-groups (no credentials needed in description).
|
|
for _hgrp in dev_mon_malware dev_mon_timeshift dev_mon_power; do
|
|
ipa hostgroup-show "$_hgrp" &>/dev/null 2>&1 || \
|
|
ipa hostgroup-add "$_hgrp" &>/dev/null || true
|
|
done
|
|
|
|
# usr_mon_logins is a USER group (monitoring follows the user, not the device).
|
|
ipa group-show usr_mon_logins &>/dev/null 2>&1 || \
|
|
ipa group-add usr_mon_logins \
|
|
--desc="Members: SSH login monitoring enabled on enrolled devices" &>/dev/null || true
|
|
|
|
kdestroy &>/dev/null || true
|
|
|
|
touch "$DONE_FLAG"
|
|
log "CheckMK setup complete."
|
|
log " Phase 2 (push-mode requests) will run on next invocation."
|
|
log " Web UI: ${CMK_URL}/${CMK_SITE}/"
|
|
log " Login: cmkadmin / (CMK_ADMIN_PASSWORD from .env)"
|
|
log " Clients: add to dev_mon_base hostgroup — agent self-registers via ansipa"
|