mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-12 17:52:48 +03:00
Container security hardening (phase 2) (#24068)
* Create frigate and go2rtc runtime users in the image * Add single fix-ownership helper for volume permission migration * Add init-usermod oneshot for PUID and PGID remapping * Chown newly created runtime directories to the frigate user * Run sentinel-guarded ownership sweep during prepare * Add host-side volume permission migration script * Guard log directory ownership for user-mode startup * Fall back to plain s6-log when running without root * Assert PUID remapping and sweep sentinel in CI smoke test * Skip the ownership sweep in the devcontainer * Pin FRIGATE_RUN_AS_ROOT in ownership tests * Do not record the sweep as complete when a chown failed * Validate PUID and PGID in the migration script * Treat a failed ownership scan as an incomplete sweep * Reject PUID and PGID of 0 during remapping * Handle symlinks, dry runs, and sentinel write failures in the sweep * Treat an absent sweep root as an incomplete sweep
This commit is contained in:
committed by
Nicolas Mowen
parent
c004d0a1c9
commit
40793b8478
@@ -0,0 +1,43 @@
|
||||
"""Helpers for aligning created files with the non-root runtime user."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import pwd
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
RUNTIME_USER = "frigate"
|
||||
|
||||
|
||||
def get_runtime_ids() -> tuple[int, int] | None:
|
||||
"""Return (uid, gid) that services run as, or None when chown is not applicable.
|
||||
|
||||
None when: not root (docker --user, so the host already mapped us),
|
||||
FRIGATE_RUN_AS_ROOT=true (escape hatch must not mutate ownership),
|
||||
or outside the Frigate container image (no frigate user).
|
||||
"""
|
||||
if os.geteuid() != 0:
|
||||
return None
|
||||
|
||||
if os.environ.get("FRIGATE_RUN_AS_ROOT", "false") == "true":
|
||||
return None
|
||||
|
||||
try:
|
||||
user = pwd.getpwnam(RUNTIME_USER)
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
return (user.pw_uid, user.pw_gid)
|
||||
|
||||
|
||||
def chown_to_runtime(path: str) -> None:
|
||||
"""Best-effort chown of path to the runtime user."""
|
||||
ids = get_runtime_ids()
|
||||
|
||||
if ids is None:
|
||||
return
|
||||
|
||||
try:
|
||||
os.chown(path, *ids)
|
||||
except OSError as err:
|
||||
logger.warning(f"Unable to set ownership of {path}: {err}")
|
||||
Reference in New Issue
Block a user