Some checks failed
morphit-release / Build + publish release tarball (push) Has been cancelled
153 lines
7.1 KiB
YAML
153 lines
7.1 KiB
YAML
# §37.9 — AIDE filesystem integrity baseline.
|
|
---
|
|
- name: Ensure the AIDE drop-in directory exists
|
|
# aide-common creates /etc/aide/aide.conf.d on Ubuntu 24.04, but ensuring it
|
|
# keeps the drop-in write safe on any box/version that doesn't.
|
|
ansible.builtin.file:
|
|
path: /etc/aide/aide.conf.d
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: '0755'
|
|
|
|
- name: Configure AIDE
|
|
ansible.builtin.copy:
|
|
dest: /etc/aide/aide.conf.d/99-morphit
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
content: |
|
|
# Managed by Ansible. Watch the morphit code + config + key
|
|
# systemd unit files.
|
|
{{ morphit_repo_path }}/apps/relay R
|
|
{{ morphit_repo_path }}/apps/indexer R
|
|
/etc/morphit R
|
|
/etc/systemd/system/morphit-*.service R
|
|
/etc/systemd/system/morphit-*.timer R
|
|
|
|
- name: Check if AIDE database exists
|
|
ansible.builtin.stat:
|
|
path: /var/lib/aide/aide.db
|
|
register: hardening_aide_db_stat
|
|
|
|
# cp680 — the AIDE baseline hashes the WHOLE filesystem, which on a low-power CPU
|
|
# takes 20-45+ min and used to BLOCK the wizard (blowing the 15-min target).
|
|
# It doesn't need to: the baseline is built from the freshly-installed files, and
|
|
# whether it finishes during the wizard or shortly after makes no security
|
|
# difference. So we DEFER it to a low-priority background oneshot that runs after
|
|
# the install and yields to the indexer's initial chain sync. The wizard no
|
|
# longer waits on it. (Supersedes the cp678 in-wizard heartbeat.)
|
|
- name: Install the deferred AIDE-baseline builder script
|
|
ansible.builtin.copy:
|
|
dest: /usr/local/lib/morphit/morphit-aide-init.sh
|
|
owner: root
|
|
group: root
|
|
mode: '0755'
|
|
content: |
|
|
#!/bin/sh
|
|
# Build the AIDE filesystem-integrity baseline (deferred, idle-priority),
|
|
# then REMOVE this one-shot service so nothing lingers.
|
|
#
|
|
# Reboot-safe: the real database /var/lib/aide/aide.db is only ever created
|
|
# by the ATOMIC rename at the end, so a reboot mid-build leaves it ABSENT
|
|
# (never a half-written/corrupt file). Any partial aide.db.new from an
|
|
# interrupted run is discarded and rebuilt. The service stays enabled until
|
|
# the baseline exists, so an interrupted build simply retries on next boot.
|
|
#
|
|
# Failure-visible (cp682): if the build FAILS, this exits non-zero WITHOUT
|
|
# self-removing, so the unit stays in systemd's "failed" state — which
|
|
# morphit-systemd-monitor (it auto-watches every morphit-*.service) reports
|
|
# to the operator's Matrix DM. It also logs a high-priority error and drops
|
|
# a marker file, so a background failure is never silent even without the
|
|
# monitor/matrix-bot. The build retries on the next boot regardless.
|
|
set -eu
|
|
on_exit() {
|
|
rc=$?
|
|
if [ "$rc" -ne 0 ] && [ ! -f /var/lib/aide/aide.db ]; then
|
|
logger -p daemon.err -t morphit-aide-init "AIDE baseline build FAILED (exit $rc) — filesystem-integrity monitoring is NOT yet active. It retries on next boot. See: journalctl -u morphit-aide-init.service" 2>/dev/null || true
|
|
mkdir -p /var/lib/morphit 2>/dev/null || true
|
|
printf 'AIDE baseline build failed at %s (exit %s). Retries on boot. See: journalctl -u morphit-aide-init.service\n' "$(date -u +%FT%TZ 2>/dev/null || echo unknown)" "$rc" > /var/lib/morphit/aide-init-failed 2>/dev/null || true
|
|
fi
|
|
}
|
|
trap on_exit EXIT
|
|
if [ ! -f /var/lib/aide/aide.db ]; then
|
|
rm -f /var/lib/aide/aide.db.new
|
|
aideinit -y -f
|
|
mv -f /var/lib/aide/aide.db.new /var/lib/aide/aide.db
|
|
logger -t morphit-aide-init "AIDE integrity baseline built"
|
|
fi
|
|
# Success: clear any prior failure marker, then self-remove. The baseline
|
|
# now exists, so this one-shot has done its job. Disable + delete the unit
|
|
# and this script, then reload so nothing lingers. Guarded with || true so a
|
|
# cleanup hiccup never fails the build (the baseline is already in place).
|
|
rm -f /var/lib/morphit/aide-init-failed 2>/dev/null || true
|
|
systemctl disable morphit-aide-init.service 2>/dev/null || true
|
|
rm -f /etc/systemd/system/morphit-aide-init.service
|
|
rm -f /usr/local/lib/morphit/morphit-aide-init.sh
|
|
systemctl daemon-reload 2>/dev/null || true
|
|
|
|
- name: Install the deferred AIDE-baseline systemd service (idle priority)
|
|
ansible.builtin.copy:
|
|
dest: /etc/systemd/system/morphit-aide-init.service
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
content: |
|
|
[Unit]
|
|
Description=Morphit — build AIDE filesystem-integrity baseline (deferred, idle-priority, self-removing)
|
|
# No ConditionPathExists: the script itself checks whether the baseline
|
|
# already exists (and skips the build if so), then ALWAYS self-removes — so
|
|
# this one-shot cleans itself up on the run after the baseline is in place,
|
|
# even if a reboot landed between building the db and cleaning up.
|
|
After=multi-user.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
# Idle scheduling so this NEVER competes with the indexer's initial chain
|
|
# sync — the node stays responsive and the baseline builds in spare capacity.
|
|
Nice=19
|
|
CPUSchedulingPolicy=idle
|
|
IOSchedulingClass=idle
|
|
ExecStart=/usr/local/lib/morphit/morphit-aide-init.sh
|
|
TimeoutStartSec=0
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
|
|
- name: Enable the deferred AIDE-baseline service (also builds on a fresh boot if needed)
|
|
ansible.builtin.systemd:
|
|
name: morphit-aide-init.service
|
|
enabled: true
|
|
daemon_reload: true
|
|
|
|
# cp681 — the START of the baseline build is deferred to the play's post_tasks,
|
|
# NOT fired here. AIDE watches {{ morphit_repo_path }}/apps/* + /etc/morphit +
|
|
# the morphit-*.service/.timer units, and those are written by the LATER morphit
|
|
# role. Starting the build here (in the hardening role, before the morphit role
|
|
# runs) would hash those paths before / while they're being written, producing an
|
|
# inaccurate baseline and spurious "file changed" alerts. post_tasks runs after
|
|
# every role, so the baseline is captured from the final, settled install.
|
|
|
|
- name: Note that the AIDE baseline will build in the background after the install
|
|
ansible.builtin.debug:
|
|
msg: >-
|
|
The AIDE filesystem-integrity baseline will build in the BACKGROUND at idle
|
|
priority once the install finishes writing files. It does NOT block this
|
|
wizard and will not slow your chain sync — it finishes on its own (typically
|
|
15-45 min on slow hardware), the daily integrity check begins once it's done,
|
|
and the one-shot service removes itself afterward.
|
|
when: not hardening_aide_db_stat.stat.exists
|
|
|
|
- name: Schedule daily AIDE integrity check
|
|
ansible.builtin.copy:
|
|
dest: /etc/cron.daily/aide-check
|
|
owner: root
|
|
group: root
|
|
mode: '0755'
|
|
content: |
|
|
#!/bin/sh
|
|
# Daily AIDE integrity check. Output goes to operator email.
|
|
# cp680 — skip quietly until the deferred baseline has finished building,
|
|
# so we don't email a "no database" error while it's still building.
|
|
[ -f /var/lib/aide/aide.db ] || exit 0
|
|
aide --check 2>&1 | mail -s "[morphit] AIDE check $(date +%F)" {{ morphit_alert_email_to }}
|