Doors: SFTP, REST API, file explorer, admin console
The file doors (SFTP, REST API, file explorer) share users, roles, mounts and ACLs: a right granted is granted everywhere. The admin console opens no file. SFTP holds sessions; the REST API has none, and the console shows its long transfers in progress (its activity).
| Door | For whom | Listens on | Credential | Section |
|---|---|---|---|---|
| SFTP | SFTP clients (OpenSSH sftp, WinSCP, FileZilla, rclone), sshfs | [sftp] listen | password, SSH key, JWT (sentinel name) | [sftp] |
| REST file API | HTTP scripts, applications | [admin] listen, under [api] prefix | Basic, Bearer (JWT), ticket | [api] |
| Web file explorer | users in a browser | [admin] listen, at [api.ui] path | that of the API, kept in memory | [api.ui] |
| Admin console and API | operators | [admin] listen, or [admin] control_listen | local account (password) or JWT with a role from [[admin.roles]], fallback bearer_token | [admin] |
SFTP
[sftp]
listen = "0.0.0.0:2222"
host_keys = ["/etc/craft-file-gate/host_ed25519"]
- Only the
sftpsubsystem is served: no shell, noscp, noexec, no port or agent forwarding. - With JWT: the sentinel name (
jwtby default) and the token as password,sftp -P 2222 jwt@serveur. - The keys: The SFTP door.
REST file API
[admin]
listen = "0.0.0.0:8080"
bearer_token = "changez-moi-en-production"
[api]
enabled = true
prefix = "/api/v1/files"
# list a directory
curl -u alice:mot-de-passe 'http://serveur:8080/api/v1/files/in?list'
# upload a file
curl -u alice:mot-de-passe -T rapport.csv http://serveur:8080/api/v1/files/in/rapport.csv
# download
curl -u alice:mot-de-passe -o rapport.csv http://serveur:8080/api/v1/files/in/rapport.csv
| Request | Effect |
|---|---|
GET <path>?list&offset=&limit= | paginated listing; limit 100 by default, 10000 at most |
GET <path> | download; a single-interval Range resumes it (206) |
HEAD <path> | metadata |
PUT <path> | upload of the whole file |
PUT <path>?mkdir | directory creation |
DELETE <path> | deletion |
POST <path>?rename=<destination> | rename |
GET <path>?rights | {"path", "rights", "home"}: the caller’s rights on this path, without touching the storage |
POST <file>?ticket | 201 {"url": "<prefix>/<file>?ticket=<token>", "expires_in": 600}; read right; 32 live tickets per user, and a ticket that still has 60 s left is returned again |
GET <file>?ticket=<token> | the file, without Authorization, as many times as wanted for 600 s (less if the JWT of the request expires before), the ACL judged again each time |
All the keys: Reference [api].
- One credential per request; no cookie, no session.
- A downloaded file goes out as
attachment,Cache-Control: no-store,Content-Security-Policy: sandbox,Accept-Ranges: bytes. A leaked ticket URL downloads that file until it expires.
Web file explorer
[api.ui]
enabled = true
path = "/files"
A page at http://serveur:8080/files, a client of the API: same
credentials, same ACLs. See File explorer.
Admin console and API
[admin]
listen = "127.0.0.1:8080"
bearer_token = "changez-moi-en-production"
# control_listen = "127.0.0.1:8081" # a separate door for administration
The console is at / of the admin listener: sessions and mounts, bans,
configuration without secrets, logs, metrics, revocations. You log in with
a username and password, or with a token. /metrics and the probes are on
the same listener, or on control_listen, or on [server] probes_listen:
see One door or two.
What you will see
| Line | Meaning |
|---|---|
INFO SFTP server listening | the SFTP door is open |
INFO starting admin API server (HTTP) (or (HTTPS)) | the admin listener is open |
INFO every configured door started | every configured door is serving (field doors) |
audit connection_accepted | a successful authentication, on any door (on each request for REST) |