fedora-intune: give the Intune compliance check a Defender health snapshot
Build containers / fedora-cosmic (44) (pull_request) Canceled after 0s
Build containers / fedora-cosmic (rawhide) (pull_request) Canceled after 0s
Build containers / fedora-remote (44) (pull_request) Canceled after 0s
Build containers / fedora-intune (44) (pull_request) Canceled after 0s
Build containers / Compute changes (pull_request) Canceled after 9s
Build containers / Prune old releases and tags (pull_request) Skipped
Build containers / fedora-cosmic (44) (pull_request) Canceled after 0s
Build containers / fedora-cosmic (rawhide) (pull_request) Canceled after 0s
Build containers / fedora-remote (44) (pull_request) Canceled after 0s
Build containers / fedora-intune (44) (pull_request) Canceled after 0s
Build containers / Compute changes (pull_request) Canceled after 9s
Build containers / Prune old releases and tags (pull_request) Skipped
Himmelblau runs the custom compliance script inside himmelblaud-tasks,
and Defender refuses to answer `mdatp health` there: the daemon can't
read /proc/<himmelblaud_tasks>/cmdline while checking the caller
("Permission denied" in microsoft_defender_err.log). The script saw no
daemon, and every Defender rule failed although Defender was healthy.
Add mdatp-health-snapshot.timer, which saves the health fields to
/run/mdatp-health every 5 minutes as root, outside that service. The
compliance script reads the snapshot when it's under 20 minutes old and
otherwise asks mdatp directly, so it still works on other distros.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4d780e900a
commit
111d3bea66
6 files changed
+75
-2
No files matched your search
@@ -26,6 +26,11 @@ add-files:
|
||||
- ["mdatp-firstboot.service", "/usr/lib/systemd/system/mdatp-firstboot.service"]
|
||||
- ["mdatp-firstboot.conf", "/usr/lib/systemd/system/mdatp.service.d/10-firstboot.conf"]
|
||||
- ["50-defender.preset", "/usr/lib/systemd/system-preset/50-defender.preset"]
|
||||
# Defender health for the Intune compliance script, which can't query
|
||||
# Defender itself from inside himmelblaud-tasks; see the script.
|
||||
- ["mdatp-health-snapshot", "/usr/libexec/mdatp-health-snapshot"]
|
||||
- ["mdatp-health-snapshot.service", "/usr/lib/systemd/system/mdatp-health-snapshot.service"]
|
||||
- ["mdatp-health-snapshot.timer", "/usr/lib/systemd/system/mdatp-health-snapshot.timer"]
|
||||
# Enforced Defender settings (shown as "[managed]" in `mdatp health`; local
|
||||
# changes are refused): real-time protection, behavior monitoring, PUA
|
||||
# blocking, cloud protection at the "high" block level, automatic updates
|
||||
@@ -57,4 +62,4 @@ postprocess:
|
||||
# Fail the build on a typo rather than ship a config Defender can't read.
|
||||
python3 -m json.tool /usr/share/mdatp-managed/mdatp_managed.json > /dev/null
|
||||
rpm -q --qf '%{POSTIN}' mdatp > /usr/libexec/mdatp-postinst
|
||||
chmod 0755 /usr/libexec/mdatp-firstboot /usr/libexec/mdatp-postinst
|
||||
chmod 0755 /usr/libexec/mdatp-firstboot /usr/libexec/mdatp-postinst /usr/libexec/mdatp-health-snapshot
|
||||
@@ -2,3 +2,5 @@
|
||||
enable mdatp-firstboot.service
|
||||
enable mdatp.service
|
||||
enable mde_netfilter_v2.socket
|
||||
# Health snapshot for the Intune compliance script.
|
||||
enable mdatp-health-snapshot.timer
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
# Save `mdatp health` fields to /run/mdatp-health/<field> for the Intune
|
||||
# custom compliance script (intune/defender-compliance.sh).
|
||||
#
|
||||
# That script runs inside himmelblaud-tasks.service, and Defender refuses to
|
||||
# answer it there: the daemon checks the calling process tree, can't read
|
||||
# /proc/<himmelblaud_tasks pid>/cmdline ("Permission denied" in
|
||||
# microsoft_defender_err.log), and the script sees no daemon. This runs from a
|
||||
# timer outside that service instead. Each file holds the raw
|
||||
# `mdatp health --field` output; the directory is replaced as a whole.
|
||||
set -euo pipefail
|
||||
|
||||
MDATP=/usr/bin/mdatp
|
||||
DEST=/run/mdatp-health
|
||||
FIELDS=(
|
||||
healthy
|
||||
licensed
|
||||
org_id
|
||||
real_time_protection_enabled
|
||||
behavior_monitoring
|
||||
cloud_enabled
|
||||
definitions_status
|
||||
definitions_updated_minutes_ago
|
||||
app_version
|
||||
)
|
||||
|
||||
tmp="$(mktemp -d "${DEST}.XXXXXX")"
|
||||
trap 'rm -rf "${tmp}"' EXIT
|
||||
for field in "${FIELDS[@]}"; do
|
||||
"${MDATP}" health --field "${field}" > "${tmp}/${field}" 2>/dev/null || true
|
||||
done
|
||||
chmod 0755 "${tmp}"
|
||||
chmod 0644 "${tmp}"/*
|
||||
|
||||
# Swap in the new snapshot; readers see either the old or the new one.
|
||||
rm -rf "${DEST}.old"
|
||||
[[ -d "${DEST}" ]] && mv "${DEST}" "${DEST}.old"
|
||||
mv "${tmp}" "${DEST}"
|
||||
rm -rf "${DEST}.old"
|
||||
trap - EXIT
|
||||
@@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Save Microsoft Defender health for the Intune compliance check
|
||||
After=mdatp.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/libexec/mdatp-health-snapshot
|
||||
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Save Microsoft Defender health every 5 minutes
|
||||
|
||||
[Timer]
|
||||
OnBootSec=2min
|
||||
OnUnitActiveSec=5min
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@@ -10,11 +10,21 @@
|
||||
# instead of as a script error.
|
||||
|
||||
MDATP=/usr/bin/mdatp
|
||||
# Under Himmelblau, Defender won't answer `mdatp health` from this script, so
|
||||
# a root timer may save the fields in /run/mdatp-health (the fedora-intune
|
||||
# image does). Used when under 20 minutes old, otherwise mdatp is asked.
|
||||
SNAPSHOT=/run/mdatp-health
|
||||
|
||||
if [[ -n "$(find "${SNAPSHOT}/healthy" -mmin -20 2>/dev/null)" ]]; then
|
||||
raw_field() { cat "${SNAPSHOT}/$1" 2>/dev/null; }
|
||||
else
|
||||
raw_field() { "${MDATP}" health --field "$1" 2>/dev/null; }
|
||||
fi
|
||||
|
||||
# Print one `mdatp health` field without quotes or a trailing " [managed]".
|
||||
# Unlicensed or unonboarded, mdatp prints "ATTENTION: ..." lines first.
|
||||
field() {
|
||||
"${MDATP}" health --field "$1" 2>/dev/null | grep -v '^ATTENTION' | tail -n1 \
|
||||
raw_field "$1" | grep -v '^ATTENTION' | tail -n1 \
|
||||
| sed -e 's/ \[managed\]$//' -e 's/^"//' -e 's/"$//'
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user