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

Users, roles and mounts

user ──authorities──▶ role ──▶ mount ──▶ backend (storage)
                                │
                                └── ACL (rights per path)

No right is implicit: a backend that no role mounts is visible to nobody, and the admin token gives access to no file.

A complete example

[[backends]]                 # one storage, described once
name = "disque"
type = "local"
root = "/srv/sftp"

[[roles]]
name = "utilisateurs"

[[roles.mounts]]             # at least one per role
backend = "disque"           # a [[backends]] name
home_dir = "/{username}"     # where the mount starts on the storage
create_home = true

[[roles.mounts.acl]]         # the rights, relative to the mount
path = "/"
rights = ["read", "write", "list", "delete", "rename"]
recursive = true

[[users]]
username = "alice"
password_hash = "$argon2id$..."   # craft-file-gate hash-password
authorities = ["utilisateurs"]    # alice's roles

alice sees /; this / is /srv/sftp/alice on the disk.

The keys of a role and of a mount

All the keys, with their hot reload: Reference [[roles]], [[roles.mounts]].

Where the files go

A client path goes to the mount whose mount_path is its longest prefix; the rest is appended to home_dir, on the storage (what home_dir points to on each type). .. never climbs above home_dir.

{username}: one directory per user

home_dir = "/{username}" gives each user their own directory, with a single role. The name, never sanitized, is made of A-Z a-z 0-9 . _ -, 1 to 64 characters, with no leading dot.

One mount or several

MountsWhat the user sees
one, at /the backend tree, starting from home_dir
several, under names (/disque, /archives)/ lists the mounts; each one shows its backend
nested (/partenaires/acme)/ and /partenaires are intermediate directories

The paths between mounts are synthetic directories. A rename stays within its mount.

Combining roles

A user often has several roles. Their session has the mounts of all of them.

The mounts of two rolesIn the session
mount_path values none of which is a prefix of another (/a, /b)they coexist
identical: same mount_path, backend, home_dir, and same max_file_mb, create_home, hidden_storesa single mount, ACLs merged

Two different mounts of the same backend have disjoint home_dir values (/a and /b, not / and /a): each file is reached under one ACL only.

The doctrine: a role at / is complete

  • a role at / is complete: on its own it gives everything its user sees, and it combines with no other;
  • a role meant to be combined mounts under a name (/archives).

See the recipes.

Where roles come from

SourceHowThe roles
local userauthorities of their [[users]] entrynames of [[roles]]
JWT tokenthe authorities_path claim (default /groups)names of [[roles]], or authorities to translate
authorization serviceauthz_base_url translates the unknown authoritiesnames of [[roles]]

Roles are always defined in [[roles]] or roles_file. Only the authorities that are not role names go to the service.

The authorization service contract

POST <authz_base_url>/authz/resolve
Content-Type: application/json

{"authorities": ["CN=ACME-Partners,OU=Groups"]}

Expected response: 200 and

{"roles": ["partenaire-acme"]}

authz_base_url and timeout_secs: Reference [auth].

The named roles are added to those found locally; a name that [[roles]] does not define is ignored, and a service that is down leaves the local roles.

An SFTP session builds all its backends at authentication and keeps its mounts until it ends, even after a hot reload; a REST request builds the backend of the mount it reaches.

What you will see

WhenLine
startup, role at {username}INFO role gives each user their own home directory
startup, role that mounts several backendsINFO role mounts several backends: its users hold the credentials of all of them ..., fields role, backends, writable
create_home creates a directoryINFO created missing home directory

A role that mounts several backends holds their credentials: keep it read only, for a dedicated user authenticated by key.