mirror of
https://github.com/hanzoai/egress.git
synced 2026-10-30 15:08:38 +00:00
The platform's account is read from cloud/aws/<label>/credential in egress's KMS org. A role descriptor there may be in the clear because it holds no secret; a key pair must be sealed. A caller cannot enrol a role, and a role at a caller's own path is refused. A JSON call and a JSON answer are unchanged, and a call with no body no longer sends the literal null. Co-authored-by: Hanzo Dev <[email protected]>
89 lines
3.3 KiB
Desktop File
89 lines
3.3 KiB
Desktop File
[Unit]
|
|
Description=Hanzo Egress — the outbound trust boundary
|
|
Documentation=https://git.hanzo.ai/hanzoai/egress
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=exec
|
|
ExecStart=/usr/local/bin/egress
|
|
Restart=always
|
|
RestartSec=2s
|
|
|
|
# Configuration arrives from this host and nowhere else, and it is only
|
|
# configuration: the identity moved to the sealed credential below, so this file
|
|
# now holds no secret at all. Root-owned 0400 regardless — an endpoint and an
|
|
# audience still describe where this process spends.
|
|
EnvironmentFile=/etc/egress/env
|
|
|
|
# THE IDENTITY, DECRYPTED INTO MEMORY AND NOWHERE ELSE.
|
|
#
|
|
# systemd decrypts this and places it in %d, a per-service directory that is
|
|
# memory-backed and readable only by this unit. So it is ciphertext on disk,
|
|
# plaintext only inside this process, and absent from the environment — where
|
|
# /proc/<pid>/environ would otherwise hand it to anything running as root.
|
|
#
|
|
# --with-key=host binds it to /var/lib/systemd/credential.secret, which lives on
|
|
# the LUKS root: ciphertext at rest twice over, and a disk read without the
|
|
# passphrase yields neither. Encrypt it with:
|
|
# systemd-creds encrypt --with-key=host --name=mnemonic - /etc/egress/mnemonic.cred
|
|
LoadCredentialEncrypted=mnemonic:/etc/egress/mnemonic.cred
|
|
# This service's IAM client secret, encrypted the same way. The https store
|
|
# transport signs in with it, and it buys the web identity an AWS role is assumed
|
|
# with; a missing one is a refusal rather than a fallback.
|
|
LoadCredentialEncrypted=client-secret:/etc/egress/client-secret.cred
|
|
# THE KEY THAT OPENS EVERY PROVIDER CREDENTIAL. Its public half, EGRESS_RECIPIENT
|
|
# in the environment file, seals them, and lives openly wherever it likes —
|
|
# nobody who holds it can read anything. This half is why: it exists on this
|
|
# machine, encrypted to this machine, and every credential in KMS is ciphertext
|
|
# to everyone who does not have it. Mint the pair once, keep this half here and
|
|
# nowhere else:
|
|
# systemd-creds encrypt --with-key=host --name=identity - /etc/egress/identity.cred
|
|
LoadCredentialEncrypted=identity:/etc/egress/identity.cred
|
|
|
|
User=egress
|
|
Group=egress
|
|
DynamicUser=no
|
|
|
|
# A provider key exists only in this process's memory. These stop it reaching
|
|
# anywhere it could be read back.
|
|
#
|
|
# LimitMEMLOCK is what lets the process pin every page it holds: without it
|
|
# mlockall fails, egress refuses to start, and it refuses on purpose — the
|
|
# kernel may page anonymous memory to swap whenever it likes, and a key that has
|
|
# been swapped is a key on a disk that outlives the process.
|
|
LimitMEMLOCK=infinity
|
|
LimitCORE=0
|
|
PrivateTmp=yes
|
|
PrivateDevices=yes
|
|
ProtectSystem=strict
|
|
ProtectHome=yes
|
|
ProtectProc=invisible
|
|
ProcSubset=pid
|
|
ProtectKernelTunables=yes
|
|
ProtectKernelModules=yes
|
|
ProtectKernelLogs=yes
|
|
ProtectControlGroups=yes
|
|
ProtectClock=yes
|
|
ProtectHostname=yes
|
|
RestrictNamespaces=yes
|
|
RestrictRealtime=yes
|
|
RestrictSUIDSGID=yes
|
|
RestrictAddressFamilies=AF_INET AF_INET6
|
|
LockPersonality=yes
|
|
MemoryDenyWriteExecute=yes
|
|
NoNewPrivileges=yes
|
|
CapabilityBoundingSet=
|
|
AmbientCapabilities=
|
|
SystemCallArchitectures=native
|
|
SystemCallFilter=@system-service
|
|
SystemCallFilter=~@debug @mount @obsolete @privileged @resources
|
|
UMask=0077
|
|
|
|
# No writable path at all: egress writes no files by design, and a process that
|
|
# cannot write cannot spill a credential to disk.
|
|
ReadWritePaths=
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|