refactor(ansipa): dev_security-scan → dev_mon_clamscan, report to CheckMK; drop SMB scan pipeline
Rename the security-scan policy to dev_mon_clamscan (fits the XXX_mon_* naming for monitoring groups) and make it hand results to CheckMK natively instead of uploading logs to an SMB share. - dev_mon_clamscan.sh: runs the daily ClamAV/rkhunter/chkrootkit scan and writes its own CheckMK local check (ansipa_clamscan → service "Ansipa_ClamScan"); the agent from dev_mon_base collects it. Removes the SMB upload entirely. Discovery matches dev_mon_clamscan BEFORE the generic dev_mon_* catch-all so it sets WANT_CLAMSCAN rather than being treated as a dev_mon.sh check. mkdir -p the cron dir (minimal hosts lack /etc/cron.d until cron is installed). - Remove the now-redundant dev_mon_malware check from dev_mon.sh (subsumed). - Remove usr_scan-notify and the whole SMB scan-alert pipeline it fed: ansipa-fetch-alerts.sh, ansipa-scan-notify.sh, server ansipa-check-scans.sh, the ansipa-scans Samba share + scanupload account, /etc/ansipa-smb.creds, and the SMB_SCAN_PASSWORD/smb_scan_password variables (playbook, compose, run.sh, .env, Dockerfile). The ansipa-luks-keys and ansipa-policystore shares stay. Verified live on the Arch client: enrolling in dev_mon_clamscan writes the scan script, cron, and local check (which reports "Ansipa_ClamScan"); leaving the group removes all three. Docs updated (policy tables, architecture, SMB shares, scan-flow → CheckMK). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUhrcFU8J1Hnf7vNqNxZNifeat/astal-menu
parent
adea0f457d
commit
4f22a3b03f
|
|
@ -14,8 +14,8 @@ All relevant files live under `setup/modules/FreeipaAnsible/`.
|
|||
│ │
|
||||
│ • FreeIPA — user/host directory, Kerberos KDC, DNS (optional) │
|
||||
│ • Keycloak — OIDC provider federating FreeIPA via LDAP │
|
||||
│ • Samba — two SMB shares for scan results and LUKS backup keys │
|
||||
│ • cronie — hourly scan-result analyser (ansipa-check-scans) │
|
||||
│ • CheckMK — fleet monitoring (agent + local checks) │
|
||||
│ • Samba — SMB shares for the policy store and LUKS backup keys │
|
||||
└───────────┬─────────────────────────┬────────────────────────────────┘
|
||||
│ SSSD / Kerberos │ SMB (445)
|
||||
▼ ▼
|
||||
|
|
@ -24,9 +24,10 @@ All relevant files live under `setup/modules/FreeipaAnsible/`.
|
|||
│ │ │ │
|
||||
│ • sssd │ │ • deploy-ansipa-*.yml playbooks │
|
||||
│ • ipa CLI │ │ • collect-luks-keys.yml │
|
||||
│ • Ansible-deployed │ │ (uploads keys to ansipa-luks-keys │
|
||||
│ timers: │ │ share as luks-upload service acct) │
|
||||
│ ├── pkg installer │ └─────────────────────────────────────────┘
|
||||
│ • CheckMK agent │ │ (uploads keys to ansipa-luks-keys │
|
||||
│ • Ansible-deployed │ │ share as luks-upload service acct) │
|
||||
│ timers: │ └─────────────────────────────────────────┘
|
||||
│ ├── pkg installer │
|
||||
│ ├── module install│
|
||||
│ ├── Flatpak install
|
||||
│ ├── baseuser sync │
|
||||
|
|
@ -34,8 +35,7 @@ All relevant files live under `setup/modules/FreeipaAnsible/`.
|
|||
│ ├── binary blocking
|
||||
│ ├── daemon enable/disable
|
||||
│ ├── Timeshift backups
|
||||
│ ├── security scans + SMB upload
|
||||
│ └── alert fetch + desktop notify
|
||||
│ └── dev_mon_clamscan → CheckMK
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
|
|
@ -73,7 +73,6 @@ docker compose up -d freeipa
|
|||
| `IPA_SETUP_DNS` | — | `true` to enable integrated DNS (default `false`) |
|
||||
| `IPA_DNS_FORWARDER` | — | Upstream DNS when `IPA_SETUP_DNS=true` |
|
||||
| `IPA_SETUP_KRA` | — | `true` to enable the Key Recovery Authority |
|
||||
| `SMB_SCAN_PASSWORD` | yes | Password for the `scanupload` Samba service account |
|
||||
| `LUKS_KEY_UPLOAD_PASSWORD` | yes | Password for the `luks-upload` Samba service account |
|
||||
| `KC_HOSTNAME` | yes | Public hostname of Keycloak |
|
||||
| `KC_REALM` | — | Keycloak realm name (default `corp`) |
|
||||
|
|
@ -118,10 +117,8 @@ Data persisted to the `/data` volume:
|
|||
/data/
|
||||
├── samba/
|
||||
│ ├── passdb.tdb # Samba password database (survives restarts)
|
||||
│ └── ansipa-smb.env # Persisted SMB passwords (auto-written on first start)
|
||||
├── scan-results/
|
||||
│ ├── archive/<host>/ # Client scan logs (written by clients via SMB)
|
||||
│ └── alerts/<host>/ # Alert files generated by ansipa-check-scans (hourly)
|
||||
│ └── ansipa-smb.env # Persisted service passwords (auto-written on first start)
|
||||
├── policy-store/ # Policy files, edited live via the ansipa-policystore share
|
||||
└── luks-keys/ # LUKS backup keys (written by Ansible controller via SMB)
|
||||
```
|
||||
|
||||
|
|
@ -129,15 +126,12 @@ Data persisted to the `/data` volume:
|
|||
|
||||
## SMB Shares
|
||||
|
||||
The container exposes two Samba shares, both configured by `ansipa-smb-setup.sh`.
|
||||
The container exposes two Samba shares (`ansipa-luks-keys` and
|
||||
`ansipa-policystore`), configured by `ansipa-smb-setup.sh`.
|
||||
|
||||
### `ansipa-scans` — Scan Result Archive
|
||||
|
||||
- **Path:** `/data/scan-results`
|
||||
- **Authenticated user:** `scanupload` (write-only; no browse)
|
||||
- **Purpose:** Clients enrolled in `policy-security-scan` upload their daily ClamAV / rkhunter / chkrootkit logs here after each scan run.
|
||||
- **Analysis:** `ansipa-check-scans.sh` runs hourly via cronie; it reads each host's archive logs and writes `*.alert` files to the `alerts/` subdirectory when concerning patterns are found.
|
||||
- **Credentials file on clients:** `/etc/ansipa-smb.creds` (deployed by `deploy-ansipa-policies.yml`)
|
||||
> ClamAV scan results are **no longer** delivered over SMB. The `dev_mon_clamscan`
|
||||
> policy now reports them to CheckMK via a local check (`Ansipa_ClamScan`), so
|
||||
> there is no `ansipa-scans` share or `scanupload` account any more.
|
||||
|
||||
### `ansipa-luks-keys` — LUKS Backup Key Store
|
||||
|
||||
|
|
@ -150,7 +144,7 @@ The container exposes two Samba shares, both configured by `ansipa-smb-setup.sh`
|
|||
useradd -r -G KeyAdmin <username>
|
||||
smbpasswd -a <username>
|
||||
```
|
||||
The `KeyAdmin` group and the `luks-upload` / `scanupload` service accounts are created by `ansipa-smb-setup.sh` on every container start.
|
||||
The `KeyAdmin` group and the `luks-upload` service account are created by `ansipa-smb-setup.sh` on every container start.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -247,11 +241,10 @@ Deploys a `systemd.path` unit that triggers on login. Users who are members of t
|
|||
### Deploy Policy Enforcer
|
||||
|
||||
```bash
|
||||
ansible-playbook -i inventory deploy-ansipa-policies.yml \
|
||||
-e smb_scan_password=<SMB_SCAN_PASSWORD>
|
||||
ansible-playbook -i inventory deploy-ansipa-policies.yml
|
||||
```
|
||||
|
||||
Deploys `ansipa-enforce-policies.sh`, `ansipa-fetch-alerts.sh`, `ansipa-scan-notify.sh`, a systemd timer (every 30 min), and `/etc/ansipa-smb.creds`. Use `ansible-vault` for the password in production.
|
||||
Deploys the shared policy library, all `policies.d/` modules, `ansipa-enforce-policies.sh`, and a systemd timer that runs the enforcer every 30 min.
|
||||
|
||||
### Collect LUKS Backup Keys
|
||||
|
||||
|
|
@ -292,17 +285,16 @@ Keys on the SMB share are accessible only to `KeyAdmin` group members (see [SMB
|
|||
| `BaseUser` | `auto-add-baseuser.sh` | Add user to local `baseusers` group |
|
||||
| `policy-daemon-enable-<unit>` | `ansipa-enforce-policies.sh` | `systemctl enable --now <unit>`; reverted on leave |
|
||||
| `policy-daemon-disable-<unit>` | `ansipa-enforce-policies.sh` | `systemctl disable --now <unit>`; reverted on leave |
|
||||
| `policy-timeshift-backup` | `ansipa-enforce-policies.sh` | Daily Timeshift snapshot at 03:00 |
|
||||
| `policy-security-scan` | `ansipa-enforce-policies.sh` | Daily ClamAV + rkhunter + chkrootkit scan + SMB upload |
|
||||
| `no_local_users` | `ansipa-enforce-policies.sh` | Lock passwords for root and all local users (UID ≥ 1000); reverted on leave |
|
||||
| `dev_timeshift-backup` | `ansipa-enforce-policies.sh` | Daily Timeshift snapshot at 03:00 |
|
||||
| `dev_mon_clamscan` | `ansipa-enforce-policies.sh` | Daily ClamAV + rkhunter + chkrootkit scan at 02:00; result reported to CheckMK (`Ansipa_ClamScan` local check) |
|
||||
| `dev_no-local-users` | `ansipa-enforce-policies.sh` | Lock passwords for root and all local users (UID ≥ 1000); reverted on leave |
|
||||
| `local_sudo_<username>` | `ansipa-enforce-policies.sh` | Grant `<username>` full sudo on this specific device; reverted on leave |
|
||||
|
||||
### User policies (user groups — follow the user across all enrolled devices)
|
||||
|
||||
| Group prefix | Handled by | Effect |
|
||||
|--------------|-----------|--------|
|
||||
| `policy-block-binary-<name>` | `ansipa-enforce-policies.sh` | Prevent group members from running `<name>` on any enrolled host; use `__` for `.` in Flatpak app IDs |
|
||||
| `policy-scan-notify` | `ansipa-enforce-policies.sh` | Fetch server alerts and notify group members every 10 min until acknowledged; follows the user across all enrolled devices |
|
||||
| `usr_block-binary-<name>` | `ansipa-enforce-policies.sh` | Prevent group members from running `<name>` on any enrolled host; use `__` for `.` in Flatpak app IDs |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -322,14 +314,6 @@ The enforcer queries all `policy-block-binary-*` user groups from FreeIPA on eve
|
|||
|
||||
Deleting the IPA user group causes the wrapper to be removed on the next enforcer run. State is tracked in `/var/lib/ansipa-policies/blocked-binaries`.
|
||||
|
||||
### Scan Notifications (per user)
|
||||
|
||||
`policy-scan-notify` is a FreeIPA **user group**, not a host group. Membership follows the user to every enrolled machine: group members receive scan alert notifications regardless of which device they log into.
|
||||
|
||||
The enforcer checks whether the `policy-scan-notify` group exists in FreeIPA on every run. If it does, it installs the `ansipa-fetch-alerts` systemd timer fleet-wide (root service, fires every 10 min) and a `/etc/profile.d/ansipa-notify.sh` snippet. The profile.d snippet checks group membership at login via `id(1)` / SSSD and starts `ansipa-scan-notify.sh` as a background user daemon only for members. Non-members log in unaffected.
|
||||
|
||||
Deleting the `policy-scan-notify` IPA user group causes the timer and profile.d snippet to be removed on the next enforcer run.
|
||||
|
||||
### Daemon Enable / Disable
|
||||
|
||||
| Group | Effect on join | Effect on leave |
|
||||
|
|
@ -341,30 +325,28 @@ The `.service` suffix is optional — it is appended automatically when the unit
|
|||
|
||||
State is tracked in `/var/lib/ansipa-policies/daemon-enabled` and `daemon-disabled` so revert actions are applied correctly when a host leaves a group.
|
||||
|
||||
### Security Scans & Alert Pipeline
|
||||
### ClamAV Scan → CheckMK (`dev_mon_clamscan`)
|
||||
|
||||
The scan results go straight to CheckMK — there is no SMB share or desktop-notification pipeline.
|
||||
|
||||
```
|
||||
Client (policy-security-scan)
|
||||
└── daily 02:00: clamscan + rkhunter + chkrootkit
|
||||
└── smbclient → //ipa-server/ansipa-scans/archive/<host>/<date>.log
|
||||
Client (dev_mon_clamscan)
|
||||
└── cron 02:00: /usr/local/bin/ansipa-clamscan.sh
|
||||
├── clamscan + rkhunter + chkrootkit → /var/log/ansipa-clamscan.log
|
||||
└── writes CheckMK local check /usr/lib/check_mk_agent/local/ansipa_clamscan
|
||||
|
||||
IPA container (hourly cron)
|
||||
└── ansipa-check-scans.sh
|
||||
└── grep for FOUND / Warning / Possible rootkit / etc.
|
||||
└── writes /data/scan-results/alerts/<host>/<date>.alert
|
||||
|
||||
Client (policy-scan-notify, every 10 min via systemd timer)
|
||||
└── ansipa-fetch-alerts.sh (root)
|
||||
└── downloads *.alert files → ~/administration/<host>/ per active user
|
||||
└── ansipa-scan-notify.sh (user daemon, started on login via profile.d)
|
||||
└── notify-send every 10 min while *.alert files remain
|
||||
└── delete file to acknowledge → removed from server on next fetch
|
||||
CheckMK agent (installed by dev_mon_base)
|
||||
└── collects the ansipa_clamscan local check on each poll
|
||||
└── surfaces the "Ansipa_ClamScan" service:
|
||||
OK = clean · WARN = stale DB / rkhunter warnings · CRIT = infected
|
||||
```
|
||||
|
||||
**Prerequisites for scan policies:**
|
||||
- Add host to `ansipa-module-anti-malware` before `policy-security-scan` (installs ClamAV, rkhunter, chkrootkit).
|
||||
- `samba-client` is installed automatically by `deploy-ansipa-policies.yml`.
|
||||
- SMB credentials are written to `/etc/ansipa-smb.creds` (root-only, `0600`).
|
||||
**Prerequisites:**
|
||||
- Add the host to `dev_mod_anti-malware` (installs ClamAV, rkhunter, chkrootkit).
|
||||
- Add the host to `dev_mon_base` (installs the CheckMK agent that collects the check).
|
||||
- Add the host to `dev_mon_clamscan` (runs the scan + emits the check).
|
||||
|
||||
Leaving `dev_mon_clamscan` removes the cron, scan script, log, and local check on the next enforcer run.
|
||||
|
||||
### Local User Lockdown
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
# <unit> may omit the .service suffix; all systemd unit types work.
|
||||
# If a unit appears in both enable and disable groups it is skipped.
|
||||
# dev_timeshift-backup Enforce a daily Timeshift snapshot (requires timeshift installed)
|
||||
# dev_security-scan Enforce daily ClamAV + rkhunter + chkrootkit scans
|
||||
# dev_no-local-users Lock passwords for root and all local users (UID >= 1000) so
|
||||
# that only FreeIPA domain accounts with centrally-managed sudo
|
||||
# rules can authenticate and gain elevated privileges.
|
||||
|
|
@ -37,9 +36,10 @@
|
|||
# Credentials are auto-discovered from the IPA dev_mon_base
|
||||
# description (populated by ansipa-checkmk-setup.sh on the server).
|
||||
# Leaving the group deregisters the host and disables the agent.
|
||||
# dev_mon_malware Local check reporting ClamAV scan results from the
|
||||
# dev_security-scan log. Requires dev_security-scan to run first;
|
||||
# both groups can coexist independently.
|
||||
# dev_mon_clamscan Run a daily ClamAV + rkhunter + chkrootkit scan (02:00) and report
|
||||
# the result to CheckMK via a local check (Ansipa_ClamScan). Requires
|
||||
# dev_mod_anti-malware (tools) and dev_mon_base (agent that collects
|
||||
# the check). Leaving the group removes the scan + check.
|
||||
# dev_mon_timeshift Local check for most-recent Timeshift snapshot age.
|
||||
# WARN if >5 days, CRIT if >10 days; CRIT if no snapshots found.
|
||||
# dev_mon_power Local check for CPU package power via Intel RAPL (preferred)
|
||||
|
|
@ -65,12 +65,6 @@
|
|||
# or all members leave, the printer is removed from CUPS on that
|
||||
# host. A profile.d snippet + NOPASSWD sudo rule trigger the
|
||||
# enforcer at login for immediate setup.
|
||||
# usr_scan-notify Members receive scan alert notifications on every enrolled device
|
||||
# they log into. The fetch-alerts timer is installed fleet-wide
|
||||
# when the group exists; the notification daemon starts on login
|
||||
# only for group members (checked via id(1) / SSSD).
|
||||
# Deleting the IPA user group removes the timer and profile.d
|
||||
# snippet on the next enforcer run.
|
||||
# usr_smb_r_<name> Mount a read-only Samba share as ~/‹name› for members on any
|
||||
# usr_smb_rw_<name> enrolled host where they are logged in. rw membership takes
|
||||
# precedence over r when both exist for the same share name.
|
||||
|
|
|
|||
|
|
@ -1,157 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# ansipa-fetch-alerts.sh — fetch security alerts from the server SMB share.
|
||||
# Runs as root every 10 minutes via ansipa-fetch-alerts.timer (usr_scan-notify).
|
||||
#
|
||||
# For each alert on the server that hasn't been acknowledged yet:
|
||||
# - Downloads it to ~/administration/<hostname>/ for every active login session.
|
||||
# - A local file that has been deleted counts as acknowledged and is removed
|
||||
# from the server alerts directory on the next run.
|
||||
#
|
||||
# Prerequisites:
|
||||
# /etc/ansipa-smb.creds — Samba credentials file (deployed by deploy-ansipa-policies.yml)
|
||||
# /etc/ipa/default.conf — FreeIPA client config (provides server hostname)
|
||||
# smbclient — from the samba-client package
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
LOG_TAG="ansipa-fetch-alerts"
|
||||
ADMIN_SUBDIR="administration"
|
||||
CREDS_FILE="/etc/ansipa-smb.creds"
|
||||
SMB_SHARE="ansipa-scans"
|
||||
STATE_DIR="/var/lib/ansipa-policies"
|
||||
FETCHED_STATE="$STATE_DIR/fetched-alerts"
|
||||
|
||||
log() { echo "[$LOG_TAG] $*"; logger -t "$LOG_TAG" "$*" 2>/dev/null || true; }
|
||||
warn() { echo "[$LOG_TAG][WARN] $*" >&2; logger -t "$LOG_TAG" "WARN: $*" 2>/dev/null || true; }
|
||||
|
||||
# ── Prerequisites ─────────────────────────────────────────────────────────────
|
||||
if [[ ! -f "$CREDS_FILE" ]]; then
|
||||
warn "Credentials file $CREDS_FILE not found — run deploy-ansipa-policies.yml first."
|
||||
exit 0
|
||||
fi
|
||||
if ! command -v smbclient &>/dev/null; then
|
||||
warn "smbclient not installed — install samba-client."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
IPA_SERVER=$(awk '/^server[[:space:]]*=/{print $3}' /etc/ipa/default.conf 2>/dev/null || echo "")
|
||||
if [[ -z "$IPA_SERVER" ]]; then
|
||||
warn "Cannot read IPA server from /etc/ipa/default.conf — host enrolled?"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
HOSTNAME=$(hostname -f 2>/dev/null || hostname)
|
||||
mkdir -p "$STATE_DIR"
|
||||
touch "$FETCHED_STATE"
|
||||
|
||||
smb() { smbclient "//$IPA_SERVER/$SMB_SHARE" -A "$CREDS_FILE" "$@" 2>/dev/null; }
|
||||
|
||||
# ── List active login sessions (usr_scan-notify members only) ─────────────────
|
||||
# loginctl list-sessions --no-legend: SESSION UID USER SEAT TTY → $3 = USER
|
||||
# who: USER TTY DATE TIME (HOST) → $1 = USER
|
||||
# Only deliver to members of the usr_scan-notify FreeIPA user group.
|
||||
ACTIVE_USERS=()
|
||||
_parse_session_user() {
|
||||
local line="$1" src="$2"
|
||||
local user
|
||||
if [[ "$src" == "loginctl" ]]; then
|
||||
user=$(awk '{print $3}' <<< "$line")
|
||||
else
|
||||
user=$(awk '{print $1}' <<< "$line")
|
||||
fi
|
||||
[[ -z "$user" || "$user" == "root" || "$user" == "USER" ]] && return
|
||||
# Only deliver to members of usr_scan-notify.
|
||||
id -nG "$user" 2>/dev/null | tr ' ' '\n' | grep -qxF "usr_scan-notify" || return
|
||||
local home
|
||||
home=$(getent passwd "$user" | cut -d: -f6 2>/dev/null) || return
|
||||
[[ -d "$home" ]] && ACTIVE_USERS+=("$user:$home")
|
||||
}
|
||||
|
||||
if loginctl list-sessions --no-legend &>/dev/null; then
|
||||
while IFS= read -r LINE; do
|
||||
_parse_session_user "$LINE" "loginctl"
|
||||
done < <(loginctl list-sessions --no-legend 2>/dev/null)
|
||||
else
|
||||
while IFS= read -r LINE; do
|
||||
_parse_session_user "$LINE" "who"
|
||||
done < <(who 2>/dev/null)
|
||||
fi
|
||||
# Deduplicate by user.
|
||||
mapfile -t ACTIVE_USERS < <(printf '%s\n' "${ACTIVE_USERS[@]+"${ACTIVE_USERS[@]}"}" | sort -u)
|
||||
|
||||
# ── List alerts on server for this host ───────────────────────────────────────
|
||||
# smbclient `ls path\` treats the argument as a pattern, not a cd target;
|
||||
# use `cd path; ls` to list directory contents instead.
|
||||
SERVER_ALERTS=()
|
||||
while IFS= read -r LINE; do
|
||||
# smbclient ls output: " filename.alert A 1234 date"
|
||||
FILE=$(awk '{print $1}' <<< "$LINE")
|
||||
[[ "$FILE" == *.alert ]] && SERVER_ALERTS+=("$FILE")
|
||||
done < <(smb -c "cd alerts\\$HOSTNAME; ls" 2>/dev/null || true)
|
||||
|
||||
# ── Check for locally deleted alerts (acknowledged) ───────────────────────────
|
||||
ACKNOWLEDGED=()
|
||||
while IFS= read -r ALERT_NAME; do
|
||||
[[ -z "$ALERT_NAME" ]] && continue
|
||||
# If none of the active users still have this alert file, it was acknowledged.
|
||||
ALL_DELETED=true
|
||||
for USER_INFO in "${ACTIVE_USERS[@]}"; do
|
||||
HOME_DIR="${USER_INFO#*:}"
|
||||
USER="${USER_INFO%%:*}"
|
||||
LOCAL_FILE="$HOME_DIR/$ADMIN_SUBDIR/$HOSTNAME/$ALERT_NAME"
|
||||
if [[ -f "$LOCAL_FILE" ]]; then
|
||||
ALL_DELETED=false
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$ALL_DELETED" == true ]] && [[ ${#ACTIVE_USERS[@]} -gt 0 ]]; then
|
||||
log "Alert acknowledged (deleted locally): $ALERT_NAME — removing from server"
|
||||
smb -c "del alerts\\$HOSTNAME\\$ALERT_NAME" 2>/dev/null || true
|
||||
# Remove from state file and skip re-download in this run.
|
||||
sed -i "/^$ALERT_NAME\$/d" "$FETCHED_STATE" 2>/dev/null || true
|
||||
ACKNOWLEDGED+=("$ALERT_NAME")
|
||||
fi
|
||||
done < "$FETCHED_STATE"
|
||||
|
||||
# ── Download new/pending alerts to user home dirs ─────────────────────────────
|
||||
TMP_DIR=$(mktemp -d /tmp/ansipa-alerts.XXXXXX)
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
|
||||
for ALERT_NAME in "${SERVER_ALERTS[@]}"; do
|
||||
# Skip alerts already acknowledged (and deleted from server) in this run.
|
||||
[[ " ${ACKNOWLEDGED[*]+"${ACKNOWLEDGED[*]}"} " == *" $ALERT_NAME "* ]] && continue
|
||||
|
||||
TMP_FILE="$TMP_DIR/$ALERT_NAME"
|
||||
|
||||
# Download alert content from server.
|
||||
smb -c "get alerts\\$HOSTNAME\\$ALERT_NAME $TMP_FILE" 2>/dev/null || {
|
||||
warn "Failed to download alert: $ALERT_NAME"
|
||||
continue
|
||||
}
|
||||
|
||||
NEW=false
|
||||
for USER_INFO in "${ACTIVE_USERS[@]}"; do
|
||||
HOME_DIR="${USER_INFO#*:}"
|
||||
USER="${USER_INFO%%:*}"
|
||||
LOCAL_DIR="$HOME_DIR/$ADMIN_SUBDIR/$HOSTNAME"
|
||||
LOCAL_FILE="$LOCAL_DIR/$ALERT_NAME"
|
||||
mkdir -p "$LOCAL_DIR"
|
||||
chown "$USER" "$LOCAL_DIR" 2>/dev/null || true
|
||||
|
||||
if [[ ! -f "$LOCAL_FILE" ]]; then
|
||||
cp "$TMP_FILE" "$LOCAL_FILE"
|
||||
chown "$USER" "$LOCAL_FILE"
|
||||
chmod 644 "$LOCAL_FILE"
|
||||
NEW=true
|
||||
fi
|
||||
done
|
||||
|
||||
# Track fetched alerts so we can detect acknowledgment on the next run.
|
||||
if ! grep -qx "$ALERT_NAME" "$FETCHED_STATE" 2>/dev/null; then
|
||||
echo "$ALERT_NAME" >> "$FETCHED_STATE"
|
||||
fi
|
||||
|
||||
[[ "$NEW" == true ]] && log "New alert delivered: $ALERT_NAME"
|
||||
done
|
||||
|
||||
log "Done. ${#SERVER_ALERTS[@]} server alert(s) for $HOSTNAME."
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# ansipa-scan-notify.sh — user-session scan alert notification daemon.
|
||||
# Started automatically on login via /etc/profile.d/ansipa-notify.sh.
|
||||
#
|
||||
# Behaviour:
|
||||
# - Checks ~/administration/ for *.alert files every 10 minutes.
|
||||
# - Sends a desktop notification (notify-send) for any unacknowledged alerts.
|
||||
# - Re-notifies every 10 minutes as long as alert files remain.
|
||||
# - Deleting an alert file counts as acknowledgment — notifications stop.
|
||||
# - Exits when no alert files remain AND none have been seen this session,
|
||||
# but keeps running once any alert is ever found (to catch future ones).
|
||||
|
||||
ADMIN_DIR="$HOME/administration"
|
||||
NOTIFY_INTERVAL=600 # 10 minutes
|
||||
ICON="security-high" # freedesktop icon name
|
||||
|
||||
notified_once=false
|
||||
|
||||
notify_alerts() {
|
||||
local alerts=() file count=0
|
||||
|
||||
mapfile -t alerts < <(find "$ADMIN_DIR" -name "*.alert" 2>/dev/null | sort)
|
||||
count=${#alerts[@]}
|
||||
|
||||
[[ $count -eq 0 ]] && return 0
|
||||
|
||||
local title body
|
||||
if [[ $count -eq 1 ]]; then
|
||||
local name
|
||||
name=$(basename "${alerts[0]}" .alert)
|
||||
title="Security alert: $name"
|
||||
body="Check $ADMIN_DIR\nDelete the file to acknowledge."
|
||||
else
|
||||
title="$count unacknowledged security alerts"
|
||||
body="Check $ADMIN_DIR\nDelete files to acknowledge."
|
||||
fi
|
||||
|
||||
notify-send -u critical -i "$ICON" -t 0 "$title" "$body" 2>/dev/null \
|
||||
|| notify-send -u critical "$title" "$body" 2>/dev/null \
|
||||
|| echo "[ansipa-notify] ALERT: $title — $body" >&2
|
||||
|
||||
notified_once=true
|
||||
}
|
||||
|
||||
mkdir -p "$ADMIN_DIR"
|
||||
|
||||
while true; do
|
||||
notify_alerts
|
||||
sleep "$NOTIFY_INTERVAL"
|
||||
done
|
||||
|
|
@ -10,7 +10,6 @@
|
|||
# dev_daemon-enable-<unit> Ensure <unit> is enabled and running; reverted when host leaves group
|
||||
# dev_daemon-disable-<unit> Ensure <unit> is disabled and stopped; reverted when host leaves group
|
||||
# dev_timeshift-backup Enforce daily Timeshift snapshots (03:00)
|
||||
# dev_security-scan Enforce daily ClamAV + rkhunter + chkrootkit scans + SMB upload (02:00)
|
||||
# dev_no-local-users Lock local account passwords; only FreeIPA accounts can auth
|
||||
# dev_local-sudo-<username> Grant <username> local sudo on this device; reverted when host leaves
|
||||
# dev_ssh_<userid> Distribute <userid>'s SSH public keys from IPA to authorized_keys
|
||||
|
|
@ -22,7 +21,6 @@
|
|||
# usr_admin Grant full sudo on every enrolled host (sudoers drop-in, SSSD-resolved)
|
||||
# usr_block-binary-<name> Block execution of <name> via a PATH-priority wrapper
|
||||
# usr_prt_<printer> Auto-add printer at login (per-user); URI in IPA group description
|
||||
# usr_scan-notify Fetch alerts from server, notify user every 10 min until acknowledged
|
||||
# usr_smb_r_<name> Mount read-only Samba share ~/‹name› for members; credentials in IPA group description
|
||||
# usr_smb_rw_<name> Mount read-write Samba share ~/‹name› for members (rw beats r if both)
|
||||
# usr_smb_adm_policystore Mount the policy store at ~/policystore (rw) for admin members;
|
||||
|
|
@ -33,8 +31,10 @@
|
|||
# Credentials auto-discovered from IPA dev_mon_base description (set by
|
||||
# ansipa-checkmk-setup.sh on the FreeIPA container).
|
||||
# CPU/RAM/disk/uptime reported by built-in agent sections.
|
||||
# dev_mon_malware Local check reporting ClamAV scan results from dev_security-scan log.
|
||||
# Complement — does not replace dev_security-scan; both can coexist.
|
||||
# dev_mon_clamscan Run daily ClamAV + rkhunter + chkrootkit scan (02:00) and report the
|
||||
# result to CheckMK via a local check (Ansipa_ClamScan). Also add the
|
||||
# host to dev_mod_anti-malware (installs the tools) and dev_mon_base
|
||||
# (installs the agent that collects the check).
|
||||
# dev_mon_timeshift Local check for most recent Timeshift snapshot age.
|
||||
# WARN if >5 days, CRIT if >10 days, CRIT if no snapshots found.
|
||||
# dev_mon_power Local check for CPU package TDP/power via Intel RAPL or lm-sensors.
|
||||
|
|
@ -43,9 +43,7 @@
|
|||
#
|
||||
# Prerequisites:
|
||||
# - Host enrolled in FreeIPA (sssd + ipa CLI available)
|
||||
# - For dev_security-scan / usr_scan-notify: samba-client installed (handled below)
|
||||
# - For dev_security-scan / usr_scan-notify: smb_scan_password set (use ansible-vault in production)
|
||||
# - For security-scan tools: also add host to dev_mod_anti-malware group
|
||||
# - For dev_mon_clamscan tools: also add host to dev_mod_anti-malware group
|
||||
# - For timeshift-backup: also add host to dev_mod_timeshift group
|
||||
# - For dev_mon_*: CheckMK CE must be up; run ansipa-checkmk-setup.sh on the FreeIPA
|
||||
# container first (seeds credentials + groups in IPA)
|
||||
|
|
@ -53,21 +51,17 @@
|
|||
# Samba service running on the IPA container (ansipa-smb.service auto-starts)
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory deploy-ansipa-policies.yml \
|
||||
# -e smb_scan_password=<password> # or use --vault-password-file
|
||||
# ansible-playbook -i inventory deploy-ansipa-policies.yml
|
||||
#
|
||||
# To seed the policystore on the FreeIPA container for the first time (bootstrap only;
|
||||
# thereafter edit files directly via the SMB share at ~/policystore):
|
||||
# ansible-playbook -i inventory deploy-ansipa-policies.yml \
|
||||
# -e smb_scan_password=<password> -e seed_policystore=true -e ipa_server_host=<ipa-host>
|
||||
# -e seed_policystore=true -e ipa_server_host=<ipa-host>
|
||||
|
||||
- name: Deploy FreeIPA policy enforcer
|
||||
hosts: all
|
||||
become: yes
|
||||
|
||||
vars:
|
||||
smb_scan_password: "{{ smb_scan_password | mandatory('smb_scan_password is required — use -e smb_scan_password=... or ansible-vault') }}"
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Create ansipa library and policy directories
|
||||
|
|
@ -104,35 +98,12 @@
|
|||
- lm_sensors # needed for dev_mon_power fallback (Intel RAPL preferred)
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Deploy SMB credentials file
|
||||
copy:
|
||||
dest: /etc/ansipa-smb.creds
|
||||
mode: '0600'
|
||||
owner: root
|
||||
group: root
|
||||
content: |
|
||||
username = scanupload
|
||||
password = {{ smb_scan_password }}
|
||||
domain = WORKGROUP
|
||||
|
||||
- name: Deploy policy enforcer script
|
||||
copy:
|
||||
src: ansipa-enforce-policies.sh
|
||||
dest: /usr/local/bin/ansipa-enforce-policies.sh
|
||||
mode: '0755'
|
||||
|
||||
- name: Deploy alert fetch script
|
||||
copy:
|
||||
src: ansipa-fetch-alerts.sh
|
||||
dest: /usr/local/bin/ansipa-fetch-alerts.sh
|
||||
mode: '0755'
|
||||
|
||||
- name: Deploy user notification daemon
|
||||
copy:
|
||||
src: ansipa-scan-notify.sh
|
||||
dest: /usr/local/bin/ansipa-scan-notify.sh
|
||||
mode: '0755'
|
||||
|
||||
- name: Create policy state directory
|
||||
file:
|
||||
path: /var/lib/ansipa-policies
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
# RAW_GROUPS (comma-sep host-group string from ipa host-show)
|
||||
# _ALL_USER_GROUPS (newline-sep full list from one ipa group-find call)
|
||||
# ACTIVE_DAEMON_ENABLE ACTIVE_DAEMON_DISABLE (arrays, unit name suffixes)
|
||||
# WANT_TIMESHIFT_BACKUP WANT_SECURITY_SCAN WANT_NO_LOCAL_USERS (booleans)
|
||||
# WANT_TIMESHIFT_BACKUP WANT_CLAMSCAN WANT_NO_LOCAL_USERS (booleans)
|
||||
# ACTIVE_LOCAL_SUDO_USERS ACTIVE_SSH_USERS ACTIVE_MON_DEV (arrays)
|
||||
# WANT_USR_ADMIN WANT_SCAN_NOTIFY (booleans)
|
||||
# WANT_USR_ADMIN (boolean)
|
||||
# ACTIVE_BLOCK_BINARIES ACTIVE_BLOCK_IPA_GROUPS (parallel arrays)
|
||||
# ACTIVE_PRT_GROUPS ACTIVE_PRT_PRINTERS (parallel arrays)
|
||||
# ACTIVE_MON_USR (array, usr_mon_* suffixes)
|
||||
|
|
@ -63,7 +63,7 @@ _ansipa_discover() {
|
|||
ACTIVE_SSH_USERS=()
|
||||
ACTIVE_MON_DEV=()
|
||||
WANT_TIMESHIFT_BACKUP=false
|
||||
WANT_SECURITY_SCAN=false
|
||||
WANT_CLAMSCAN=false
|
||||
WANT_NO_LOCAL_USERS=false
|
||||
|
||||
if [[ -n "$RAW_GROUPS" ]]; then
|
||||
|
|
@ -74,10 +74,13 @@ _ansipa_discover() {
|
|||
dev_daemon-enable-*) ACTIVE_DAEMON_ENABLE+=("${g#dev_daemon-enable-}") ;;
|
||||
dev_daemon-disable-*) ACTIVE_DAEMON_DISABLE+=("${g#dev_daemon-disable-}") ;;
|
||||
dev_timeshift-backup) WANT_TIMESHIFT_BACKUP=true ;;
|
||||
dev_security-scan) WANT_SECURITY_SCAN=true ;;
|
||||
dev_no-local-users) WANT_NO_LOCAL_USERS=true ;;
|
||||
dev_local-sudo-*) ACTIVE_LOCAL_SUDO_USERS+=("${g#dev_local-sudo-}") ;;
|
||||
dev_ssh_*) ACTIVE_SSH_USERS+=("${g#dev_ssh_}") ;;
|
||||
# dev_mon_clamscan runs the scan + emits its own CheckMK check;
|
||||
# match it BEFORE the generic dev_mon_* catch-all so it sets
|
||||
# WANT_CLAMSCAN instead of being treated as a dev_mon.sh check.
|
||||
dev_mon_clamscan) WANT_CLAMSCAN=true ;;
|
||||
dev_mon_*) ACTIVE_MON_DEV+=("${g#dev_mon_}") ;;
|
||||
esac
|
||||
done
|
||||
|
|
@ -89,7 +92,6 @@ _ansipa_discover() {
|
|||
| awk '/Group name:/ {print $NF}' | sort -u || true)
|
||||
|
||||
WANT_USR_ADMIN=false
|
||||
WANT_SCAN_NOTIFY=false
|
||||
ACTIVE_BLOCK_BINARIES=()
|
||||
ACTIVE_BLOCK_IPA_GROUPS=()
|
||||
ACTIVE_PRT_GROUPS=()
|
||||
|
|
@ -100,7 +102,6 @@ _ansipa_discover() {
|
|||
[[ -z "$_grp" ]] && continue
|
||||
case "$_grp" in
|
||||
usr_admin) WANT_USR_ADMIN=true ;;
|
||||
usr_scan-notify) WANT_SCAN_NOTIFY=true ;;
|
||||
usr_block-binary-*)
|
||||
local _raw="${_grp#usr_block-binary-}"
|
||||
ACTIVE_BLOCK_BINARIES+=("${_raw//__/.}")
|
||||
|
|
@ -116,13 +117,13 @@ _ansipa_discover() {
|
|||
|
||||
log "Device policies — daemon-enable: ${ACTIVE_DAEMON_ENABLE[*]:-none}" \
|
||||
"| daemon-disable: ${ACTIVE_DAEMON_DISABLE[*]:-none}" \
|
||||
"| timeshift-backup: $WANT_TIMESHIFT_BACKUP | security-scan: $WANT_SECURITY_SCAN" \
|
||||
"| timeshift-backup: $WANT_TIMESHIFT_BACKUP | clamscan: $WANT_CLAMSCAN" \
|
||||
"| no-local-users: $WANT_NO_LOCAL_USERS | local-sudo: ${ACTIVE_LOCAL_SUDO_USERS[*]:-none}" \
|
||||
"| ssh-keys: ${ACTIVE_SSH_USERS[*]:-none} | mon-dev: ${ACTIVE_MON_DEV[*]:-none}"
|
||||
log "User policies — admin: $WANT_USR_ADMIN" \
|
||||
"| block-binary: ${ACTIVE_BLOCK_BINARIES[*]:-none}" \
|
||||
"| printers: ${ACTIVE_PRT_PRINTERS[*]:-none}" \
|
||||
"| scan-notify: $WANT_SCAN_NOTIFY | mon-usr: ${ACTIVE_MON_USR[*]:-none}"
|
||||
"| mon-usr: ${ACTIVE_MON_USR[*]:-none}"
|
||||
}
|
||||
|
||||
# ── SMB credential parser ─────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
# policy: dev_mon — CheckMK monitoring agent + local checks.
|
||||
# dev_mon_base install agent, register host, installed-packages check
|
||||
# dev_mon_malware ClamAV scan result check
|
||||
# dev_mon_timeshift Timeshift snapshot age check
|
||||
# dev_mon_power CPU package power via RAPL / lm-sensors
|
||||
# usr_mon_logins SSH login audit check (user group, but requires dev_mon_base)
|
||||
# (ClamAV scan reporting lives in its own policy, dev_mon_clamscan, which runs
|
||||
# the scan and writes the Ansipa_ClamScan local check the agent here collects.)
|
||||
# Revert: deregisters the host and removes the agent socket when dev_mon_base leaves.
|
||||
|
||||
MON_LOCAL_DIR="/usr/lib/check_mk_agent/local"
|
||||
|
|
@ -218,34 +219,12 @@ elif command -v pacman &>/dev/null; then
|
|||
fi
|
||||
echo "0 Ansipa_Packages packages=${PKG_COUNT} ${PKG_COUNT} packages installed. Recent: ${RECENT}"'
|
||||
|
||||
# ── dev_mon_malware: ClamAV scan result check ─────────────────────────
|
||||
if _mon_dev_active "malware"; then
|
||||
_cmk_write_check "ansipa_clamav" '#!/bin/bash
|
||||
LOG=/var/log/ansipa-security-scan.log
|
||||
CLAMDB=/var/lib/clamav/main.cvd
|
||||
[[ -f /var/lib/clamav/main.cld ]] && CLAMDB=/var/lib/clamav/main.cld
|
||||
if [[ ! -f "$LOG" ]]; then
|
||||
echo "3 Ansipa_ClamAV - No scan log found. Add host to dev_security-scan first."
|
||||
exit 0
|
||||
fi
|
||||
LAST_DATE=$(grep "^=== ansipa-security-scan:" "$LOG" 2>/dev/null | tail -1 \
|
||||
| grep -oE "[0-9]{4}-[0-9]{2}-[0-9]{2}" || echo "")
|
||||
INFECTED=$(grep -c "FOUND$" "$LOG" 2>/dev/null) || INFECTED=0
|
||||
DB_DAYS=999
|
||||
if [[ -f "$CLAMDB" ]]; then
|
||||
DB_DAYS=$(( ( $(date +%s) - $(stat -c %Y "$CLAMDB" 2>/dev/null || echo 0) ) / 86400 ))
|
||||
fi
|
||||
PERF="infected=${INFECTED};0;0 db_age_days=${DB_DAYS};7;30"
|
||||
if [[ -z "$LAST_DATE" ]]; then
|
||||
echo "1 Ansipa_ClamAV ${PERF} No scan found yet"
|
||||
elif [[ "$INFECTED" -gt 0 ]]; then
|
||||
echo "2 Ansipa_ClamAV ${PERF} INFECTED: ${INFECTED} threat(s) found — last scan: ${LAST_DATE}"
|
||||
elif [[ "$DB_DAYS" -gt 7 ]]; then
|
||||
echo "1 Ansipa_ClamAV ${PERF} DB stale (${DB_DAYS}d). Last scan: ${LAST_DATE}"
|
||||
else
|
||||
echo "0 Ansipa_ClamAV ${PERF} Clean — last scan: ${LAST_DATE}, DB age: ${DB_DAYS}d"
|
||||
fi'
|
||||
fi
|
||||
# NOTE: ClamAV scan reporting is handled by the dev_mon_clamscan policy,
|
||||
# which runs the scan and writes its own CheckMK local check
|
||||
# (ansipa_clamscan) directly — so the old dev_mon_malware group and its
|
||||
# ansipa_clamav check are gone. The stale ansipa_clamav file is cleaned
|
||||
# up automatically by the local-check cleanup below (it is no longer in
|
||||
# _WANT_CHECKS).
|
||||
|
||||
# ── dev_mon_timeshift: snapshot age check ─────────────────────────────
|
||||
if _mon_dev_active "timeshift"; then
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
#!/usr/bin/env bash
|
||||
# policy: dev_mon_clamscan — daily ClamAV + rkhunter + chkrootkit scan at 02:00,
|
||||
# with results reported natively to CheckMK.
|
||||
# Applied when the host is a member of the dev_mon_clamscan host-group.
|
||||
#
|
||||
# Results are handed to CheckMK via a local check (ansipa_clamscan) rather than
|
||||
# uploaded to an SMB share: the CheckMK agent (installed by dev_mon_base) picks
|
||||
# up the local check and surfaces the scan status as a monitored service. Add a
|
||||
# host to BOTH dev_mon_clamscan (to run the scan + emit the check) and dev_mon_base
|
||||
# (to install the agent that collects it) to see results in CheckMK.
|
||||
|
||||
SCAN_CRON="$CRON_DIR/ansipa-clamscan"
|
||||
SCAN_SCRIPT="/usr/local/bin/ansipa-clamscan.sh"
|
||||
SCAN_LOG="/var/log/ansipa-clamscan.log"
|
||||
CMK_LOCAL_DIR="/usr/lib/check_mk_agent/local"
|
||||
CMK_CHECK="$CMK_LOCAL_DIR/ansipa_clamscan"
|
||||
|
||||
if [[ "$WANT_CLAMSCAN" == true ]]; then
|
||||
# (Re-)write the scan script so it stays current with this version of the enforcer.
|
||||
cat > "$SCAN_SCRIPT" <<'SCAN'
|
||||
#!/bin/bash
|
||||
# ansipa-clamscan — daily ClamAV / rkhunter / chkrootkit run.
|
||||
# Managed by ansipa-enforce-policies — do not edit manually.
|
||||
# Results are read by the ansipa_clamscan CheckMK local check; no SMB upload.
|
||||
LOG=/var/log/ansipa-clamscan.log
|
||||
# `hostname` (inetutils) may be absent on minimal Arch; resolve without it.
|
||||
HOSTNAME=$( { command -v hostname >/dev/null 2>&1 && hostname -f 2>/dev/null; } \
|
||||
|| hostnamectl --static 2>/dev/null || cat /etc/hostname 2>/dev/null \
|
||||
|| cat /proc/sys/kernel/hostname 2>/dev/null )
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
{
|
||||
echo "=== ansipa-clamscan: $DATE $HOSTNAME ==="
|
||||
|
||||
if command -v freshclam &>/dev/null; then
|
||||
freshclam --quiet 2>/dev/null || true
|
||||
fi
|
||||
if command -v clamscan &>/dev/null; then
|
||||
clamscan -r --infected --quiet /home /etc /tmp /var/tmp 2>/dev/null || true
|
||||
fi
|
||||
if command -v rkhunter &>/dev/null; then
|
||||
rkhunter --update --quiet 2>/dev/null || true
|
||||
rkhunter --check --skip-keypress --quiet 2>/dev/null || true
|
||||
fi
|
||||
if command -v chkrootkit &>/dev/null; then
|
||||
chkrootkit 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "=== scan complete ==="
|
||||
} >> "$LOG" 2>&1
|
||||
SCAN
|
||||
chmod 755 "$SCAN_SCRIPT"
|
||||
|
||||
# ── CheckMK local check: report scan results to CheckMK ───────────────────
|
||||
# Emitted regardless of whether the CheckMK agent is present yet; once
|
||||
# dev_mon_base installs the agent, it collects this check automatically.
|
||||
mkdir -p "$CMK_LOCAL_DIR"
|
||||
cat > "$CMK_CHECK" <<'CHECK'
|
||||
#!/bin/bash
|
||||
# ansipa_clamscan — CheckMK local check reporting the ansipa-clamscan result.
|
||||
# Managed by ansipa-enforce-policies (dev_mon_clamscan) — do not edit manually.
|
||||
LOG=/var/log/ansipa-clamscan.log
|
||||
CLAMDB=/var/lib/clamav/main.cvd
|
||||
[[ -f /var/lib/clamav/main.cld ]] && CLAMDB=/var/lib/clamav/main.cld
|
||||
if [[ ! -f "$LOG" ]]; then
|
||||
echo "1 Ansipa_ClamScan - No scan has run yet (scans run daily at 02:00)."
|
||||
exit 0
|
||||
fi
|
||||
LAST_DATE=$(grep "^=== ansipa-clamscan:" "$LOG" 2>/dev/null | tail -1 \
|
||||
| grep -oE "[0-9]{4}-[0-9]{2}-[0-9]{2}" || echo "")
|
||||
INFECTED=$(grep -c "FOUND$" "$LOG" 2>/dev/null) || INFECTED=0
|
||||
RKWARN=$(grep -c "Warning:" "$LOG" 2>/dev/null) || RKWARN=0
|
||||
DB_DAYS=999
|
||||
if [[ -f "$CLAMDB" ]]; then
|
||||
DB_DAYS=$(( ( $(date +%s) - $(stat -c %Y "$CLAMDB" 2>/dev/null || echo 0) ) / 86400 ))
|
||||
fi
|
||||
PERF="infected=${INFECTED};1;1 rkhunter_warnings=${RKWARN} db_age_days=${DB_DAYS};7;30"
|
||||
if [[ -z "$LAST_DATE" ]]; then
|
||||
echo "1 Ansipa_ClamScan ${PERF} No completed scan found yet"
|
||||
elif [[ "$INFECTED" -gt 0 ]]; then
|
||||
echo "2 Ansipa_ClamScan ${PERF} INFECTED: ${INFECTED} threat(s) — last scan: ${LAST_DATE}"
|
||||
elif [[ "$DB_DAYS" -gt 7 ]]; then
|
||||
echo "1 Ansipa_ClamScan ${PERF} ClamAV DB stale (${DB_DAYS}d). Last scan: ${LAST_DATE}"
|
||||
elif [[ "$RKWARN" -gt 0 ]]; then
|
||||
echo "1 Ansipa_ClamScan ${PERF} Clean, but ${RKWARN} rkhunter warning(s) — last scan: ${LAST_DATE}"
|
||||
else
|
||||
echo "0 Ansipa_ClamScan ${PERF} Clean — last scan: ${LAST_DATE}, DB age: ${DB_DAYS}d"
|
||||
fi
|
||||
CHECK
|
||||
chmod 755 "$CMK_CHECK"
|
||||
|
||||
if [[ ! -f "$SCAN_CRON" ]]; then
|
||||
log "Enabling daily ClamAV scan (dev_mon_clamscan) with CheckMK reporting"
|
||||
# /etc/cron.d may not exist yet if cron isn't installed — create it so the
|
||||
# drop-in lands (cronie/anti-malware tooling comes via dev_mod_anti-malware).
|
||||
mkdir -p "$CRON_DIR"
|
||||
cat > "$SCAN_CRON" <<'CRON'
|
||||
# ansipa-dev_mon_clamscan: managed by ansipa-enforce-policies — do not edit manually.
|
||||
# Install scan tools by adding the host to the dev_mod_anti-malware group.
|
||||
# Results appear in CheckMK (Ansipa_ClamScan) when the host is also in dev_mon_base.
|
||||
0 2 * * * root /usr/local/bin/ansipa-clamscan.sh
|
||||
CRON
|
||||
chmod 644 "$SCAN_CRON"
|
||||
fi
|
||||
else
|
||||
if [[ -f "$SCAN_CRON" || -f "$SCAN_SCRIPT" || -f "$CMK_CHECK" ]]; then
|
||||
rm -f "$SCAN_CRON" "$SCAN_SCRIPT" "$CMK_CHECK" "$SCAN_LOG"
|
||||
log "Removed dev_mon_clamscan policy (host left dev_mon_clamscan group)"
|
||||
fi
|
||||
fi
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# policy: dev_security-scan — daily ClamAV + rkhunter + chkrootkit scans + SMB upload at 02:00.
|
||||
# Applied when host is member of dev_security-scan host-group.
|
||||
|
||||
SCAN_CRON="$CRON_DIR/ansipa-security-scan"
|
||||
SCAN_SCRIPT="/usr/local/bin/ansipa-security-scan.sh"
|
||||
|
||||
if [[ "$WANT_SECURITY_SCAN" == true ]]; then
|
||||
# (Re-)write the scan script so it stays current with this version of the enforcer.
|
||||
cat > "$SCAN_SCRIPT" <<'SCAN'
|
||||
#!/bin/bash
|
||||
# ansipa-security-scan — daily ClamAV / rkhunter / chkrootkit run + SMB upload.
|
||||
# Managed by ansipa-enforce-policies — do not edit manually.
|
||||
LOG=/var/log/ansipa-security-scan.log
|
||||
# `hostname` (inetutils) may be absent on minimal Arch; resolve without it.
|
||||
HOSTNAME=$( { command -v hostname >/dev/null 2>&1 && hostname -f 2>/dev/null; } \
|
||||
|| hostnamectl --static 2>/dev/null || cat /etc/hostname 2>/dev/null \
|
||||
|| cat /proc/sys/kernel/hostname 2>/dev/null )
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
{
|
||||
echo "=== ansipa-security-scan: $DATE $HOSTNAME ==="
|
||||
|
||||
if command -v freshclam &>/dev/null; then
|
||||
freshclam --quiet 2>/dev/null || true
|
||||
fi
|
||||
if command -v clamscan &>/dev/null; then
|
||||
clamscan -r --infected --quiet /home /etc /tmp /var/tmp 2>/dev/null || true
|
||||
fi
|
||||
if command -v rkhunter &>/dev/null; then
|
||||
rkhunter --update --quiet 2>/dev/null || true
|
||||
rkhunter --check --skip-keypress --quiet 2>/dev/null || true
|
||||
fi
|
||||
if command -v chkrootkit &>/dev/null; then
|
||||
chkrootkit 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "=== scan complete ==="
|
||||
} >> "$LOG" 2>&1
|
||||
|
||||
# ── Upload to server SMB share ────────────────────────────────────────────────
|
||||
IPA_SERVER=$(awk '/^server[[:space:]]*=/{print $3}' /etc/ipa/default.conf 2>/dev/null || echo "")
|
||||
if [[ -n "$IPA_SERVER" ]] && [[ -f /etc/ansipa-smb.creds ]] && command -v smbclient &>/dev/null; then
|
||||
# Create host archive dir (mkdir is idempotent; errors suppressed).
|
||||
smbclient "//$IPA_SERVER/ansipa-scans" -A /etc/ansipa-smb.creds \
|
||||
-c "mkdir archive; mkdir archive\\$HOSTNAME; put $LOG archive\\$HOSTNAME\\$DATE.log" \
|
||||
>> "$LOG" 2>&1 \
|
||||
&& echo "[ansipa] Scan results uploaded to $IPA_SERVER/ansipa-scans/archive/$HOSTNAME/$DATE.log" >> "$LOG" \
|
||||
|| echo "[ansipa][WARN] SMB upload failed — results remain local at $LOG" >> "$LOG"
|
||||
else
|
||||
echo "[ansipa] SMB upload skipped (no credentials or smbclient not found)." >> "$LOG"
|
||||
fi
|
||||
SCAN
|
||||
chmod 755 "$SCAN_SCRIPT"
|
||||
|
||||
if [[ ! -f "$SCAN_CRON" ]]; then
|
||||
log "Enabling daily security scans (ClamAV / rkhunter / chkrootkit)"
|
||||
cat > "$SCAN_CRON" <<'CRON'
|
||||
# ansipa-dev_security-scan: managed by ansipa-enforce-policies — do not edit manually.
|
||||
# Install scan tools by adding the host to the dev_mod_anti-malware group.
|
||||
0 2 * * * root /usr/local/bin/ansipa-security-scan.sh
|
||||
CRON
|
||||
chmod 644 "$SCAN_CRON"
|
||||
fi
|
||||
else
|
||||
if [[ -f "$SCAN_CRON" ]]; then
|
||||
rm -f "$SCAN_CRON"
|
||||
rm -f "$SCAN_SCRIPT"
|
||||
log "Removed security scan policy (host left dev_security-scan group)"
|
||||
fi
|
||||
fi
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# policy: usr_scan-notify — scan alert notification daemon for IPA group members.
|
||||
# When the usr_scan-notify user group exists: installs a systemd fetch-alerts timer
|
||||
# (fleet-wide) and a profile.d snippet that starts the notification daemon on login
|
||||
# for group members (checked at login time via id/SSSD).
|
||||
|
||||
FETCH_SVC="/etc/systemd/system/ansipa-fetch-alerts.service"
|
||||
FETCH_TIMER="/etc/systemd/system/ansipa-fetch-alerts.timer"
|
||||
NOTIFY_PROFILED="/etc/profile.d/ansipa-notify.sh"
|
||||
|
||||
if [[ "$WANT_SCAN_NOTIFY" == true ]]; then
|
||||
if [[ ! -x /usr/local/bin/ansipa-fetch-alerts.sh ]]; then
|
||||
warn "ansipa-fetch-alerts.sh not found — run deploy-ansipa-policies.yml first."
|
||||
fi
|
||||
|
||||
if [[ ! -f "$FETCH_SVC" ]]; then
|
||||
log "Installing ansipa-fetch-alerts systemd service + timer"
|
||||
cat > "$FETCH_SVC" <<'UNIT'
|
||||
[Unit]
|
||||
Description=Fetch Ansipa security alerts from the server SMB share
|
||||
After=network-online.target sssd.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/ansipa-fetch-alerts.sh
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
UNIT
|
||||
|
||||
cat > "$FETCH_TIMER" <<'UNIT'
|
||||
[Unit]
|
||||
Description=Periodic ansipa security alert fetch
|
||||
|
||||
[Timer]
|
||||
OnBootSec=2min
|
||||
OnUnitActiveSec=10min
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
UNIT
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now ansipa-fetch-alerts.timer
|
||||
log "ansipa-fetch-alerts.timer enabled"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$NOTIFY_PROFILED" ]]; then
|
||||
log "Installing /etc/profile.d/ansipa-notify.sh"
|
||||
cat > "$NOTIFY_PROFILED" <<'PROFILED'
|
||||
# ansipa-notify: launch the scan alert notification daemon on login for
|
||||
# members of the usr_scan-notify FreeIPA user group.
|
||||
# Managed by ansipa-enforce-policies — do not edit manually.
|
||||
_NOTIFY_DAEMON=/usr/local/bin/ansipa-scan-notify.sh
|
||||
if [[ -x "$_NOTIFY_DAEMON" ]] && \
|
||||
id -nG 2>/dev/null | grep -qw "usr_scan-notify" && \
|
||||
! pgrep -u "$(id -u)" -f "ansipa-scan-notify" >/dev/null 2>&1; then
|
||||
"$_NOTIFY_DAEMON" &
|
||||
disown
|
||||
fi
|
||||
unset _NOTIFY_DAEMON
|
||||
PROFILED
|
||||
chmod 644 "$NOTIFY_PROFILED"
|
||||
fi
|
||||
else
|
||||
if [[ -f "$FETCH_TIMER" ]]; then
|
||||
systemctl disable --now ansipa-fetch-alerts.timer 2>/dev/null || true
|
||||
rm -f "$FETCH_SVC" "$FETCH_TIMER"
|
||||
systemctl daemon-reload
|
||||
log "Removed ansipa-fetch-alerts timer (usr_scan-notify user group no longer exists)"
|
||||
fi
|
||||
if [[ -f "$NOTIFY_PROFILED" ]]; then
|
||||
rm -f "$NOTIFY_PROFILED"
|
||||
log "Removed /etc/profile.d/ansipa-notify.sh"
|
||||
fi
|
||||
fi
|
||||
|
|
@ -9,15 +9,14 @@ IPA_DNS_FORWARDER=
|
|||
IPA_SETUP_KRA=false
|
||||
|
||||
# ── Ansipa SMB shares ─────────────────────────────────────────────────────────
|
||||
# SMB_SCAN_PASSWORD — password for 'scanupload'; deploy to clients via Ansible
|
||||
# with smb_scan_password=<this value> (use ansible-vault).
|
||||
# LUKS_KEY_UPLOAD_PASSWORD — password for the 'luks-upload' service account used
|
||||
# by the Ansible controller to write LUKS backup keys to
|
||||
# the ansipa-luks-keys share. Pass to collect-luks-keys.yml
|
||||
# with -e luks_upload_password=<this value>.
|
||||
# To grant read access, add a Samba user to KeyAdmin on the
|
||||
# container: useradd -r -G KeyAdmin <user> && smbpasswd -a <user>
|
||||
SMB_SCAN_PASSWORD=ChangeMe_ScanPass!
|
||||
# (ClamAV scan results now go to CheckMK via the dev_mon_clamscan local check —
|
||||
# there is no longer an ansipa-scans SMB share or scanupload account.)
|
||||
LUKS_KEY_UPLOAD_PASSWORD=ChangeMe_LuksUpload!
|
||||
|
||||
# ── CheckMK CE monitoring ─────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
# -e IPA_DOMAIN=example.com \
|
||||
# -e IPA_ADMIN_PASSWORD=Secret123 \
|
||||
# -e IPA_DM_PASSWORD=Secret456 \
|
||||
# -e SMB_SCAN_PASSWORD=Secret789 \
|
||||
# -p 443:443 -p 389:389 -p 636:636 -p 88:88 -p 445:445 \
|
||||
# freeipa-server
|
||||
#
|
||||
|
|
@ -64,12 +63,10 @@ COPY ipa-first-boot.sh /usr/local/sbin/ipa-first-boot.sh
|
|||
COPY ipa-first-boot.service /etc/systemd/system/ipa-first-boot.service
|
||||
COPY ansipa-smb-setup.sh /usr/local/sbin/ansipa-smb-setup.sh
|
||||
COPY ansipa-smb.service /etc/systemd/system/ansipa-smb.service
|
||||
COPY ansipa-check-scans.sh /usr/local/sbin/ansipa-check-scans.sh
|
||||
COPY ansipa-checkmk-setup.sh /usr/local/sbin/ansipa-checkmk-setup.sh
|
||||
COPY ansipa-checkmk.service /etc/systemd/system/ansipa-checkmk.service
|
||||
RUN chmod +x /usr/local/sbin/ipa-first-boot.sh \
|
||||
&& chmod +x /usr/local/sbin/ansipa-smb-setup.sh \
|
||||
&& chmod +x /usr/local/sbin/ansipa-check-scans.sh \
|
||||
&& chmod +x /usr/local/sbin/ansipa-checkmk-setup.sh \
|
||||
&& systemctl enable docker-env.service \
|
||||
&& systemctl enable ipa-first-boot.service \
|
||||
|
|
|
|||
|
|
@ -1,71 +0,0 @@
|
|||
#!/bin/bash
|
||||
# ansipa-check-scans.sh — analyse client scan logs and create alert files.
|
||||
# Runs hourly via /etc/cron.d/ansipa-check-scans (installed by ansipa-smb-setup.sh).
|
||||
#
|
||||
# Input: /data/scan-results/archive/<hostname>/<YYYY-MM-DD>.log
|
||||
# Output: /data/scan-results/alerts/<hostname>/<YYYY-MM-DD>.alert
|
||||
# (created only when concerning patterns are found; client deletes to acknowledge)
|
||||
|
||||
SCAN_BASE="/data/scan-results"
|
||||
ARCHIVE_DIR="$SCAN_BASE/archive"
|
||||
ALERT_DIR="$SCAN_BASE/alerts"
|
||||
LOG=/var/log/ansipa-check-scans.log
|
||||
|
||||
log() { printf '[%s] [ansipa-check-scans] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG"; }
|
||||
|
||||
# Patterns that indicate a concerning scan result (case-insensitive).
|
||||
CONCERN_PATTERNS=(
|
||||
"FOUND" # ClamAV: virus or trojan found
|
||||
"Infected files: [^0]" # ClamAV summary with non-zero count
|
||||
"Warning:" # rkhunter warning
|
||||
"Possible rootkit" # rkhunter
|
||||
"INFECTED" # generic
|
||||
"Suspicious file" # chkrootkit
|
||||
"INFECTED SOURCE" # chkrootkit
|
||||
)
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
for HOST_DIR in "$ARCHIVE_DIR"/*/; do
|
||||
[[ -d "$HOST_DIR" ]] || continue
|
||||
HOSTNAME=$(basename "$HOST_DIR")
|
||||
mkdir -p "$ALERT_DIR/$HOSTNAME"
|
||||
|
||||
for SCAN_LOG in "$HOST_DIR"*.log; do
|
||||
[[ -f "$SCAN_LOG" ]] || continue
|
||||
LOG_DATE=$(basename "$SCAN_LOG" .log)
|
||||
ALERT_FILE="$ALERT_DIR/$HOSTNAME/$LOG_DATE.alert"
|
||||
|
||||
# Skip if we already generated an alert for this log.
|
||||
[[ -f "$ALERT_FILE" ]] && continue
|
||||
|
||||
FINDINGS=()
|
||||
for PATTERN in "${CONCERN_PATTERNS[@]}"; do
|
||||
while IFS= read -r LINE; do
|
||||
FINDINGS+=("$LINE")
|
||||
done < <(grep -iE "$PATTERN" "$SCAN_LOG" 2>/dev/null || true)
|
||||
done
|
||||
|
||||
# Deduplicate.
|
||||
mapfile -t FINDINGS < <(printf '%s\n' "${FINDINGS[@]}" | sort -u)
|
||||
|
||||
if [[ ${#FINDINGS[@]} -gt 0 ]]; then
|
||||
log "ALERT: $HOSTNAME / $LOG_DATE — ${#FINDINGS[@]} finding(s)"
|
||||
{
|
||||
printf '=== Ansipa Security Alert ===\n'
|
||||
printf 'Host: %s\n' "$HOSTNAME"
|
||||
printf 'Scan: %s\n' "$LOG_DATE"
|
||||
printf 'Findings: %d\n' "${#FINDINGS[@]}"
|
||||
printf '\nConcerning lines:\n'
|
||||
printf ' %s\n' "${FINDINGS[@]}"
|
||||
printf '\nFull log: %s\n' "$SCAN_LOG"
|
||||
printf '\nTo acknowledge: delete this file on the client.\n'
|
||||
printf '=== Generated: %s ===\n' "$(date)"
|
||||
} > "$ALERT_FILE"
|
||||
else
|
||||
log "OK: $HOSTNAME / $LOG_DATE — clean"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
log "Check complete."
|
||||
|
|
@ -166,7 +166,7 @@ else
|
|||
fi
|
||||
|
||||
# Create supplementary monitoring host-groups (no credentials needed in description).
|
||||
for _hgrp in dev_mon_malware dev_mon_timeshift dev_mon_power; do
|
||||
for _hgrp in dev_mon_clamscan dev_mon_timeshift dev_mon_power; do
|
||||
ipa hostgroup-show "$_hgrp" &>/dev/null 2>&1 || \
|
||||
ipa hostgroup-add "$_hgrp" &>/dev/null || true
|
||||
done
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
# 2. /data/samba/ansipa-smb.env (persisted from first boot)
|
||||
#
|
||||
# Shares:
|
||||
# ansipa-scans — write-only for 'scanupload'; clients push scan results here.
|
||||
# ansipa-luks-keys — write-only for 'luks-upload' (Ansible controller);
|
||||
# read for members of the 'KeyAdmin' Linux group.
|
||||
# Add a Samba user to KeyAdmin to grant key-read access:
|
||||
|
|
@ -24,12 +23,10 @@
|
|||
set -euo pipefail
|
||||
|
||||
LOG_TAG="ansipa-smb-setup"
|
||||
SCAN_BASE="/data/scan-results"
|
||||
LUKS_BASE="/data/luks-keys"
|
||||
SHARES_BASE="/data/smb-shares"
|
||||
POLICY_STORE_BASE="/data/policy-store"
|
||||
SMB_CONF="/etc/samba/smb.conf"
|
||||
SMB_USER="scanupload"
|
||||
LUKS_UPLOAD_USER="luks-upload"
|
||||
POLICY_STORE_USER="smb-policystore"
|
||||
KEYADMIN_GROUP="KeyAdmin"
|
||||
|
|
@ -40,32 +37,27 @@ warn() { echo "[$LOG_TAG][WARN] $*" >&2; }
|
|||
die() { echo "[$LOG_TAG][ERROR] $*" >&2; exit 1; }
|
||||
|
||||
# ── Resolve passwords ─────────────────────────────────────────────────────────
|
||||
SMB_PASS="${SMB_SCAN_PASSWORD:-}"
|
||||
LUKS_PASS="${LUKS_KEY_UPLOAD_PASSWORD:-}"
|
||||
IPA_ADMIN_PASS="${IPA_ADMIN_PASSWORD:-}"
|
||||
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$ENV_FILE"
|
||||
SMB_PASS="${SMB_SCAN_PASSWORD:-$SMB_PASS}"
|
||||
LUKS_PASS="${LUKS_KEY_UPLOAD_PASSWORD:-$LUKS_PASS}"
|
||||
IPA_ADMIN_PASS="${IPA_ADMIN_PASSWORD:-$IPA_ADMIN_PASS}"
|
||||
fi
|
||||
|
||||
[[ -z "$SMB_PASS" ]] && die "SMB_SCAN_PASSWORD not set and $ENV_FILE not present. Set it in .env."
|
||||
[[ -z "$LUKS_PASS" ]] && die "LUKS_KEY_UPLOAD_PASSWORD not set and $ENV_FILE not present. Set it in .env."
|
||||
|
||||
# ── Persist for subsequent restarts ──────────────────────────────────────────
|
||||
mkdir -p "$(dirname "$ENV_FILE")"
|
||||
{
|
||||
printf 'SMB_SCAN_PASSWORD=%q\n' "$SMB_PASS"
|
||||
printf 'LUKS_KEY_UPLOAD_PASSWORD=%q\n' "$LUKS_PASS"
|
||||
[[ -n "$IPA_ADMIN_PASS" ]] && printf 'IPA_ADMIN_PASSWORD=%q\n' "$IPA_ADMIN_PASS" || true
|
||||
} > "$ENV_FILE"
|
||||
chmod 600 "$ENV_FILE"
|
||||
|
||||
# ── Directory structure (idempotent) ──────────────────────────────────────────
|
||||
mkdir -p "$SCAN_BASE/archive" "$SCAN_BASE/alerts"
|
||||
mkdir -p "$LUKS_BASE"
|
||||
mkdir -p "$SHARES_BASE"
|
||||
mkdir -p "$POLICY_STORE_BASE/policies.d"
|
||||
|
|
@ -77,11 +69,6 @@ if ! getent group "$KEYADMIN_GROUP" &>/dev/null; then
|
|||
fi
|
||||
|
||||
# ── System users ──────────────────────────────────────────────────────────────
|
||||
if ! id "$SMB_USER" &>/dev/null; then
|
||||
useradd -r -s /sbin/nologin -d "$SCAN_BASE" -M "$SMB_USER"
|
||||
log "Created system user: $SMB_USER"
|
||||
fi
|
||||
|
||||
if ! id "$POLICY_STORE_USER" &>/dev/null; then
|
||||
useradd -r -s /sbin/nologin -d "$POLICY_STORE_BASE" -M "$POLICY_STORE_USER"
|
||||
log "Created system user: $POLICY_STORE_USER"
|
||||
|
|
@ -95,7 +82,6 @@ else
|
|||
usermod -aG "$KEYADMIN_GROUP" "$LUKS_UPLOAD_USER"
|
||||
fi
|
||||
|
||||
chown -R "$SMB_USER:$SMB_USER" "$SCAN_BASE"
|
||||
chown -R "root:$KEYADMIN_GROUP" "$LUKS_BASE"
|
||||
chmod 2750 "$LUKS_BASE" # setgid so new files inherit KeyAdmin group
|
||||
chown -R "$POLICY_STORE_USER:$POLICY_STORE_USER" "$POLICY_STORE_BASE"
|
||||
|
|
@ -120,16 +106,6 @@ _write_smb_conf() {
|
|||
printcap name = /dev/null
|
||||
disable spoolss = yes
|
||||
|
||||
[ansipa-scans]
|
||||
comment = Ansipa scan results — managed by ansipa-enforce-policies
|
||||
path = $SCAN_BASE
|
||||
valid users = $SMB_USER
|
||||
read only = no
|
||||
browseable = no
|
||||
create mask = 0644
|
||||
directory mask = 0755
|
||||
force user = $SMB_USER
|
||||
|
||||
[ansipa-luks-keys]
|
||||
comment = Ansipa LUKS backup keys — KeyAdmin read, luks-upload write only
|
||||
path = $LUKS_BASE
|
||||
|
|
@ -365,7 +341,6 @@ _setup_policystore() {
|
|||
}
|
||||
|
||||
# ── Write smb.conf, set passwords, configure shares ──────────────────────────
|
||||
_smb_set_pass "$SMB_USER" "$SMB_PASS"
|
||||
_smb_set_pass "$LUKS_UPLOAD_USER" "$LUKS_PASS"
|
||||
|
||||
# Write base smb.conf first, then append dynamic share stanzas.
|
||||
|
|
@ -376,14 +351,4 @@ _setup_policystore
|
|||
# Reload smbd if it is already running (picks up new user shares without restart).
|
||||
smbcontrol smbd reload-config 2>/dev/null || true
|
||||
|
||||
# ── Server-side scan checker cron (hourly, analysed on the IPA server itself) ─
|
||||
# Always (re-)write: /etc/cron.d is on the ephemeral container layer and is
|
||||
# lost on container recreation, so we must restore it on every start.
|
||||
cat > /etc/cron.d/ansipa-check-scans <<'CRON'
|
||||
# ansipa: analyze client scan logs and write alerts — managed, do not edit.
|
||||
0 * * * * root /usr/local/sbin/ansipa-check-scans.sh 2>&1 | logger -t ansipa-check-scans
|
||||
CRON
|
||||
chmod 644 /etc/cron.d/ansipa-check-scans
|
||||
log "Installed hourly scan-checker cron"
|
||||
|
||||
log "Samba setup complete. Shares: ansipa-scans ($SMB_USER), ansipa-policystore ($POLICY_STORE_USER)"
|
||||
log "Samba setup complete. Shares: ansipa-luks-keys, ansipa-policystore ($POLICY_STORE_USER)"
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ services:
|
|||
IPA_SETUP_DNS: ${IPA_SETUP_DNS:-false}
|
||||
IPA_DNS_FORWARDER: ${IPA_DNS_FORWARDER:-}
|
||||
IPA_SETUP_KRA: ${IPA_SETUP_KRA:-false}
|
||||
SMB_SCAN_PASSWORD: ${SMB_SCAN_PASSWORD:?set SMB_SCAN_PASSWORD in .env}
|
||||
CMK_URL: http://172.30.0.12:5000
|
||||
# Client-facing CheckMK URL stored in the dev_mon_base description —
|
||||
# must be routable from enrolled clients (e.g. http://<docker-host>:8090).
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ start_freeipa() {
|
|||
-e IPA_SETUP_DNS="${IPA_SETUP_DNS:-false}" \
|
||||
-e IPA_DNS_FORWARDER="${IPA_DNS_FORWARDER:-}" \
|
||||
-e IPA_SETUP_KRA="${IPA_SETUP_KRA:-false}" \
|
||||
-e SMB_SCAN_PASSWORD="${SMB_SCAN_PASSWORD:?}" \
|
||||
-e LUKS_KEY_UPLOAD_PASSWORD="${LUKS_KEY_UPLOAD_PASSWORD:?}" \
|
||||
-e CMK_URL="http://172.30.0.12:5000" \
|
||||
-e CMK_ADVERTISED_URL="${CMK_ADVERTISED_URL:-}" \
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ mkdir -p "$OUT_DIR"
|
|||
section "Generating secrets"
|
||||
IPA_ADMIN_PASSWORD=$(gen_pw); IPA_DM_PASSWORD=$(gen_pw)
|
||||
CMK_ADMIN_PASSWORD=$(gen_pw); KC_ADMIN_PASSWORD=$(gen_pw); KC_DB_PASSWORD=$(gen_pw)
|
||||
SMB_SCAN_PASSWORD=$(gen_pw); LUKS_KEY_UPLOAD_PASSWORD=$(gen_pw)
|
||||
LUKS_KEY_UPLOAD_PASSWORD=$(gen_pw)
|
||||
log "Generated admin/service passwords (saved in $OUT_DIR/.env — keep it safe)."
|
||||
|
||||
# ─── .env for the ansipa stack ────────────────────────────────────────────────
|
||||
|
|
@ -91,7 +91,6 @@ IPA_DM_PASSWORD=$IPA_DM_PASSWORD
|
|||
IPA_SETUP_DNS=false
|
||||
IPA_SETUP_KRA=false
|
||||
|
||||
SMB_SCAN_PASSWORD=$SMB_SCAN_PASSWORD
|
||||
LUKS_KEY_UPLOAD_PASSWORD=$LUKS_KEY_UPLOAD_PASSWORD
|
||||
|
||||
CMK_ADMIN_PASSWORD=$CMK_ADMIN_PASSWORD
|
||||
|
|
|
|||
Loading…
Reference in New Issue