mirror of
https://github.com/brunopostle/ifcurl.git
synced 2026-07-12 02:08:13 +00:00
render_service.py: new FastAPI app with /render, /select, /render_diff endpoints that wrap run_sandboxed — listens on a Unix domain socket. service.py: imports the three pipeline functions from render_service.py; delegates to render service via httpx when IFCURL_RENDER_SOCKET is set, falls back to direct run_sandboxed when unset (single-service mode). __main__.py: add 'render-service' subcommand (--socket PATH). pyproject.toml: add httpx to service optional deps. ifcurl-api.service: renamed from ifcurl-preview.service; sets IFCURL_RENDER_SOCKET, adds AF_UNIX to RestrictAddressFamilies. ifcurl-render.service: new hardened unit — AF_UNIX only, ~execve ~execveat blocked, no credentials, separate ifcurl-render user. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60 lines
2.1 KiB
Desktop File
60 lines
2.1 KiB
Desktop File
[Unit]
|
|
Description=ifcurl render isolation service (IFC parsing + rendering)
|
|
Documentation=https://github.com/brunopostle/ifcurl
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=ifcurl-render
|
|
Group=ifcurl-render
|
|
RuntimeDirectory=ifcurl
|
|
RuntimeDirectoryMode=0775
|
|
RuntimeDirectoryPreserve=yes
|
|
ExecStart=/usr/local/bin/ifcurl render-service \
|
|
--socket /run/ifcurl/render.sock
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
# Render configuration — override in /etc/ifcurl/render-env:
|
|
# IFCURL_SANDBOX_TIMEOUT=120 max seconds per render subprocess
|
|
# IFCURL_SANDBOX_MEMORY_MB=0 address-space cap per subprocess (0=unlimited)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Sandbox hardening
|
|
#
|
|
# This service processes untrusted IFC data via ifcopenshell and pyvista.
|
|
# It has no credentials, no git access, and no outbound network.
|
|
#
|
|
# AF_UNIX only: the service receives requests from ifcurl-api over the
|
|
# render socket and communicates with its own sandbox child processes.
|
|
# AF_INET/AF_INET6 are excluded — a compromised subprocess cannot reach
|
|
# git hosts or any other external service.
|
|
#
|
|
# execve/execveat are blocked: pyvista and ifcopenshell use fork()/clone()
|
|
# only (verified with strace). git is never called from this service.
|
|
# The render sandbox (run_sandboxed) uses multiprocessing.Process which
|
|
# uses fork on Linux — safe with ~execve.
|
|
#
|
|
# ProtectSystem=strict + no ReadWritePaths: this service writes nothing to
|
|
# disk; all output is returned over the Unix socket to the API service.
|
|
# ---------------------------------------------------------------------------
|
|
EnvironmentFile=-/etc/ifcurl/render-env
|
|
NoNewPrivileges=yes
|
|
RestrictSUIDSGID=yes
|
|
PrivateTmp=yes
|
|
ProtectSystem=strict
|
|
ProtectHome=yes
|
|
ProtectKernelTunables=yes
|
|
ProtectKernelModules=yes
|
|
ProtectControlGroups=yes
|
|
RestrictNamespaces=yes
|
|
LockPersonality=yes
|
|
RestrictRealtime=yes
|
|
RestrictAddressFamilies=AF_UNIX
|
|
SystemCallArchitectures=native
|
|
SystemCallFilter=@system-service @process @files @io-event
|
|
SystemCallFilter=~execve ~execveat
|
|
SystemCallErrorNumber=EPERM
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|