agent: read chrony status from tracking.log instead of the command socket
Bench on comet-beacon-54 proved every command-socket route is blocked for the hardened agent: chronyd's unix socket is owner-write-only (0755, so even a chrony-group member can't connect), and STIG closes the UDP command port (cmdport 0). Rather than re-open a port or expose chrony's privileged socket, enable chronyd's tracking log and have the agent READ it — no port, no socket, no group, no SELinux domain transition, full hardening intact. - chrony.conf: enable 'log tracking' (idempotent) so chronyd appends source/stratum/offset to /var/log/chrony/tracking.log. Write volume is a ~130B line per clock update (backing off to ~maxpoll when stable) and capped by the chrony RPM's logrotate — negligible on the RAM overlay. cmdport 0 stays, so no STIG deviation. - agent: chronyTracking() now reads the last data line of tracking.log via parseTrackingLog() (source f[2], stratum f[3], offset f[6], leap/sync f[7]); replaces the chronyc exec + parseChrony. Unit test swapped accordingly. - revert the two abandoned approaches: drop the bindcmdaddress line (394ad10) and the fleet_agent_chronyc SELinux nnp_transition module + provisioner block (e6fd4a2, .te deleted) — no chronyc exec means no transition to allow. Removed stig-deviations #16 and #17 (both waivers no longer needed). Needs a workstation image rebuild + reboot. BENCH-VERIFY: tracking.log is world-readable so the DynamicUser agent can read it; under enforcing unconfined_service_t can read chronyd_var_log_t (add a minimal file-read allow if denied); and the offset sign matches chronyc on a synced host.
This commit is contained in:
@@ -1,44 +0,0 @@
|
||||
# Raw module-policy syntax (compiled with `checkmodule -M -m`), NOT the refpolicy
|
||||
# `policy_module()` m4 macro — that macro is only expanded by the refpolicy
|
||||
# Makefile and checkmodule rejects it. See chrony-dhcp-dispatcher.te for the why.
|
||||
module fleet_agent_chronyc 1.0.0;
|
||||
|
||||
########################################
|
||||
# Let the fleet-agent's chrony probe transition to chronyc_t under NoNewPrivileges.
|
||||
#
|
||||
# fleet-agent (telemetry) shells out to `chronyc -n tracking` to report the host's
|
||||
# clock offset / NTP source / stratum. The agent runs as unconfined_service_t, and
|
||||
# the shipped chrony policy has a type_transition so executing chronyc moves the
|
||||
# child into the confined chronyc_t domain. BUT the fleet-agent unit is hardened
|
||||
# with NoNewPrivileges (set explicitly AND forced by DynamicUser + SystemCallFilter
|
||||
# + MemoryDenyWriteExecute), and SELinux forbids an NNP process from transitioning
|
||||
# domains unless process2:nnp_transition is granted for that source->target pair.
|
||||
# The shipped policy has no such grant, so under enforcing the exec is DENIED:
|
||||
# avc: denied { nnp_transition } comm="fleet-agent"
|
||||
# scontext=...:unconfined_service_t tcontext=...:chronyc_t tclass=process2
|
||||
# chronyc never runs, chronyTracking() returns empty, and every chrony_* health
|
||||
# field stays unset (the UI shows chrony as "—"). uptime/cpu/mem are unaffected —
|
||||
# they read /proc directly and need no domain transition.
|
||||
#
|
||||
# This single allow lets the transition proceed to the MORE-confined chronyc_t
|
||||
# domain (the safe direction NNP's nnp_transition permission exists to gate), with
|
||||
# no loosening of the agent's own sandbox. Minimal + auditable; justified in
|
||||
# docs/stig-deviations.md #16.
|
||||
#
|
||||
# NB this is necessary but NOT sufficient: the agent reaches chronyd over the
|
||||
# LOOPBACK UDP command socket (`chronyc -h 127.0.0.1 tracking`; the image binds it
|
||||
# via `bindcmdaddress 127.0.0.1`, see stig-deviations #17) because the unix socket
|
||||
# is unusable under the agent's sandbox. Under enforcing, once chronyc runs in
|
||||
# chronyc_t it must also be allowed to reach chronyd_t on UDP 323 — the base chrony
|
||||
# policy is expected to cover chronyc_t's command traffic, but BENCH-VERIFY on the
|
||||
# first enforcing boot and, if a FOLLOW-ON chronyc_t AVC appears (e.g. a corenet
|
||||
# udp_socket/name_connect denial to chronyd), extend here.
|
||||
########################################
|
||||
|
||||
require {
|
||||
type unconfined_service_t;
|
||||
type chronyc_t;
|
||||
class process2 nnp_transition;
|
||||
}
|
||||
|
||||
allow unconfined_service_t chronyc_t:process2 nnp_transition;
|
||||
Reference in New Issue
Block a user