Add credential profiles with socket-per-profile isolation#7
Merged
calebfaruki merged 4 commits intomainfrom Mar 19, 2026
Merged
Add credential profiles with socket-per-profile isolation#7calebfaruki merged 4 commits intomainfrom
calebfaruki merged 4 commits intomainfrom
Conversation
Profiles scope credentials to individual containers. Each profile gets its own unix socket — the volume mount is the capability. The daemon reads ~/.config/airlock/profiles/*.toml at startup, binds one socket per profile, and refuses to start without at least one profile. Profile TOML supports an optional command whitelist and env var injection for credential routing (SSH keys, AWS profiles). Env merge order is strip → profile → command module, so command hardening always wins. Adds profile field to audit log entries, profile list/show CLI commands, and profiles/sockets directories to airlock init. Linux sockets use $XDG_RUNTIME_DIR/airlock/sockets/, macOS uses ~/.config/airlock/sockets/. Renames test modules from generic `mod tests` to promise names: idempotent_setup, audit_log, credential_isolation.
XDG_RUNTIME_DIR is ephemeral (cleared on logout/reboot), so airlock init couldn't durably pre-create the sockets directory on Linux. Stale socket files are inert — connection refused, cleaned on next daemon start. Replace InitConfig.socket_path (v1 single-socket vestige) with sockets_dir. Remove all XDG_RUNTIME_DIR and /var/run branching from init.rs and main.rs. Update docs to reflect a single path everywhere.
The socket file is the sole authentication mechanism per profile — any process that can connect inherits that profile's credentials. Set mode 0600 explicitly after bind rather than relying on umask. Extract bind_profile_socket() helper (remove stale file, bind, chmod) into lib.rs so both the daemon and integration tests use the same path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6
Summary
Credential profiles scope credentials and commands to individual containers. Each profile gets its own unix socket. The volume mount is the capability. No identity verification needed.
What changed
Profile system — daemon reads
~/.config/airlock/profiles/*.tomlat startup, binds one socket per profile, refuses to start without at least one profile. Profile TOML supports optional command whitelist and env injection. Env merge order: command strip → profile inject → command harden (command hardening always wins).Socket-per-profile — unified to
~/.config/airlock/sockets/<profile>.sockon all platforms. ReplacedXDG_RUNTIME_DIR(ephemeral, cleared on reboot) with a durable path that survivesairlock init. Stale sockets are cleaned on daemon start.Socket permissions — explicit
0o600after bind viabind_profile_socket()helper in lib.rs. No umask reliance. Daemon fails to start if chmod fails.Audit logging —
profilefield added to every log entry.CLI —
airlock-daemon profile listandprofile show <name>.Init — creates
profiles/andsockets/directories. Prints profile-aware mount example.Tests — renamed from generic
mod teststo promise names:idempotent_setup,audit_log,credential_isolation. New tests for socket permissions and stale socket cleanup.Security model
Addresses two OWASP Agentic Top 10 (2026) risks:
0600closes the host-side gap. NoSO_PEERCRED, works on Linux and macOS.Per-socket tokens were evaluated and deferred as "won't implement" — the container is a single trust domain, so a token colocated with the socket doesn't create a new security boundary.
Migration from v1
touch ~/.config/airlock/profiles/default.tomlairlock initdocker runto mount~/.config/airlock/sockets/default.sock:/run/docker-airlock.sock