Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Trust files and TLS

Trust files

These files decide who gets in and what they can do: anyone who can write them can grant themselves access. The server judges them at startup, and at reload for those that reload.

FileJudged
the file passed to --configstartup, reload
sftp.host_keysstartup
auth.users_file, auth.methods.local.users_file, or an adopted users.tomlstartup, reload
auth.roles_file, or an adopted roles.tomlstartup, reload
auth.jwt.public_key_filestartup
admin.tls.cert_file, admin.tls.key_filestartup, reload
admin.session.key_filestartup
CRAFT_FILE_GATE_JWT_SECRET_FILE, CRAFT_FILE_GATE_ADMIN_BEARER_TOKEN_FILEstartup
auth.password_file and ca_bundle of a webhdfs backendbackend construction
SSL_CERT_FILE, SSL_CERT_DIR, if setstartup

The file, and every directory crossed from / to reach it (symbolic links included), is judged on its mode bits, its owner and its group. The server then reads the file through the descriptor it judged.

Setting them up

SetupVerdict
owned by root, writable by its owner only, directories the sameaccepted silently
owned by the server’s uid, writable by it onlyaccepted, reported at startup
on a read-only mount (Kubernetes Secret or ConfigMap, :ro volume)accepted; the directories are not judged
/, /tmp (root, sticky bit) on the pathaccepted

The recommended setup:

chown root:root /etc/craft-file-gate /etc/craft-file-gate/*
chmod 755 /etc/craft-file-gate
chmod 644 /etc/craft-file-gate/config.toml /etc/craft-file-gate/roles.toml
chmod 640 /etc/craft-file-gate/users.toml /etc/craft-file-gate/host_ed25519
chgrp craft-file-gate /etc/craft-file-gate/users.toml /etc/craft-file-gate/host_ed25519

In a container, mount the configuration read-only (readOnly: true, :ro): a Kubernetes Secret in 0440 with the pod’s fsGroup works as is.

[security]

All keys: Reference [security].

Read at startup. Keep it for a deployment where the server’s group contains only the server.

What the server creates itself

The process sets umask(077) at startup.

Created by the serverMode
generated host key, generated admin TLS key0600 (generated certificate: 0644)
directory of a generated key, bans file, temporary files0700 / 0600
files uploaded by clients, home directories (local backend)0666 / 0777 masked by the umask inherited at launch
log and audit files0640 masked by the inherited umask

Instances that share a bans volume run under the same uid.

Client paths

A client path is judged on its virtual form, then the backend resolves it under its root. On a local backend, a symbolic link never leaves the root: see Local.

TLS trust roots

This is outgoing TLS: S3 backend over HTTPS, jwks_url, authorization service, OTLP collector over https://, WebHDFS backend. Incoming TLS for the console is set in [admin.tls] (see Admin API and console).

The server embeds no root: it reads the system store.

VariableContent
SSL_CERT_FILEa PEM file, any number of certificates
SSL_CERT_DIRdirectories, separated by :

When set, either variable replaces the system store, it does not add to it. To trust an internal authority and the public roots, concatenate:

cat /etc/ssl/certs/ca-certificates.crt ca-interne.pem > bundle.pem

Without a variable, the first file found among the usual paths wins (/etc/ssl/certs/ca-certificates.crt, /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem, /etc/pki/tls/certs/ca-bundle.crt, /etc/ssl/ca-bundle.pem, /etc/ssl/cert.pem), then the directories /etc/ssl/certs and /etc/pki/tls/certs. The :latest and :alpine images carry a store; the :scratch image has none.

Mounting a set of roots

The Mozilla bundle maintained by the curl project works:

curl -fsSLo bundle.pem https://curl.se/ca/cacert.pem

Mount it at the default path (/etc/ssl/certs/ca-certificates.crt, read-only), or anywhere with SSL_CERT_FILE; in Kubernetes, a ConfigMap is enough, it is not a secret.

A deployment without outgoing TLS connections (local backend or SFTP proxy, local accounts or static JWT key, no OTLP) needs no root.

Deployment recommendations

TopicRecommendation
trust filesread-only, owned by root; a Secret or a ConfigMap mounted readOnly: true
secretsthe _FILE forms rather than variables, readable in /proc/<pid>/environ
uida dedicated uid per instance, NoNewPrivileges=yes, a seccomp filter (SystemCallFilter=@system-service, seccompProfile: RuntimeDefault)
podthe Helm chart applies the restricted profile: see Kubernetes
admin portcontrol_listen on an internal interface; in a container, behind a NetworkPolicy (the Helm chart sets one, and a separate ClusterIP Service)
OpenAPI description[api] openapi, off by default: without authentication, it describes the whole API
console TLS[admin.tls], certificate provided or generated
brute forcethe three ban lists and the two limiters (see Bans)
audit trailexported in full off the host; authentication refusals are at INFO, a WARN filter loses them
JWTregular rotation of the signing keys; issuer and audience set