Skip to content

Status

Which fileshare release these pages describe, what each release added, what has been verified with real clients, and what is not implemented yet.

These pages describe fileshare v0.29.1.

What each release added

v0.7.0a restricted share over NFS, with a kerberos block
v0.8.0the admin API over gRPC; directory shares; /healthz, /readyz, /metrics
v0.9.0TLS for WebDAV, S3 and NFS, from files or ACME; WebDAV with passwords refused in the clear
v0.10.0reading the directory again: reload = "5m", SIGHUP, ReloadDirectory
v0.11.0SFTP for people the identity provider vouches for: its SSH CA, and opkssh
v0.12.0revocation: a KRL for the provider’s SSH certificates, a CRL for NFS identities from certificates
v0.13.0shared signals: a CAEP session-revoked voids everything the provider issued before, on every protocol
v0.14.0the security review’s fixes: share names a protocol can carry, no share containing the configuration or its secrets, source_roots checked again at start, SSF max_age ≥ 1m and retain ≥ 169h
v0.15.0a KRL from ssh_krl_url must be signed and dated
v0.16.0revocation lists never go backwards, across a restart with ssh_krl_state_file / crl_state_file; trust anchors and list files may not lie inside a share
v0.16.1requires Go 1.26.6: nine reachable standard-library advisories in 1.26.4
v0.16.2an NFS CRL’s signature is checked before it is parsed
v0.16.3nobody is named by an unverified email
v0.16.4tests only
v0.16.5tests only (#36: a test read a transport error as success)
v0.16.6the NFS refusal names both ways out: a kerberos block, or identity = "certificate"
v0.16.7go-authn/oidc v0.2.2: an RSA key’s size is counted in bits. Before, a 1024-bit key padded with zero octets verified a WebDAV token or an opkssh PK Token
v0.17.0a security audit’s fixes: one share may not hold another; access files (authorized_keys_file, dsn_file, …) may not lie in a share; WebDAV never turns anonymous because a directory read came back empty; S3 honours protocols; a connection that has not authenticated within 30 s is closed; an opkssh session ends at opkssh_max_age; a revoked session stays revoked and is closed
v0.17.1go-authn/oidc v0.2.4 (no key set behind a redirect to http), servercert v0.3.0 (the ACME cache path checked like sshd’s StrictModes), krl v0.5.0, revocation v0.3.0
v0.17.2go-filesystems/s3 v0.3.0: S3 no longer tells an unauthenticated caller which access keys exist; presigned URLs work, last a week at most, and are refused before their own date
v0.18.0CI pins Go 1.27.1 instead of stable
v0.18.1fileshare check warns when an oidc block has no domains: a provider’s bare name reaches the local account of that name
v0.19.0go-authn/directory v0.11.0: a users "ldap" block refuses a cleartext bind to another machine; passwords are compared as digests, in constant time
v0.20.0local_names: the provider’s names are local names only when the oidc block says so (security audit F4)
v0.21.0volumes: a privileged fileshare provisioner creates ZFS datasets, btrfs subvolumes and XFS/ext4 project-quota directories, and the admin API serves shares from them; a full directory share is one answer on every protocol; the admin socket’s allowed_uids
v0.21.1a full share says so on SMB (STATUS_DISK_FULL) and NFS (NFS3ERR_NOSPC / NFS3ERR_DQUOT)
v0.22.0ssh_domains: an SSH certificate is accepted only where its domain grant (ssh-domain-grant@core.aai.geant.org, the EuroHPC SSH CA profile) names this host, fail-closed; ssh_accept_ungranted lets in certificates with no grant
v0.22.1go-filesystems/sftp v0.5.1: a certificate pinned to an address (source-address) is accepted from that address under ssh_domains, and on the provider’s and OpenPubkey certificates; before, it was refused from every address
v0.22.2tests and documentation only: source-address is tested from ::1 and from a second IPv4 address (127.0.0.2), under ssh_domains, and on an OpenPubkey certificate; on Linux, under FILESHARE_REQUIRE_JUDGE, a missing judge fails instead of skipping
v0.23.0a btrfs volume is the size of its quota over NFS, SMB and WebDAV (go-filesystems/nfs v0.7.0, smb v0.5.0, webdav v0.3.0 report the size at each query); before, btrfs showed the whole filesystem. A server whose shares come from the admin API no longer stops at start when it serves NFS and has no share yet
v0.24.0faster reads: a WebDAV GET of a directory or volume share goes out with sendfile(2) over plain HTTP (not over TLS), NFS reads and writes in 1 MiB (rtmax/wtmax), and SMB clients read more than 64 KiB per request (CAP_LARGE_MTU). On the CI runner, a 256 MiB file: WebDAV 6.6 GB/s, SMB 0.84, NFS 1.47 (one client)
v0.24.1security: an idle NFS connection no longer keeps the 3 MiB its largest call needed (24 idle connections held 59 MiB); an SMB frame header no longer makes the server allocate the 8 MiB it announces before the bytes arrive; an SMB request can no longer pay one credit for 4 GiB (go-filesystems/nfs v0.8.1, smb v0.6.1 and v0.6.2)
v0.25.0SFTP answers limits@openssh.com, so OpenSSH’s sftp reads in up to 255 KiB (+25%); one session holds at most 1024 open handles (go-filesystems/sftp v0.6.0)
v0.26.0server-side copy on every protocol that has one: a WebDAV COPY, an SFTP copy-data (OpenSSH’s sftp cp) and an SMB COPYCHUNK (Explorer, Linux copy_file_range) are made on the server, by copy_file_range(2) between files of the host — a reflink on btrfs and XFS, measured in CI as 0 bytes used for an 8 MiB copy. Security: a WebDAV COPY and every S3 GET/HEAD no longer read the whole file into memory; S3 streams objects of any size. Correction: v0.24.0’s sendfile for WebDAV GET only happened on read-only shares — a wrapper hid it on writable ones; it happens on both since v0.26.0
v0.27.0ACME: the certificate is asked for at start, not at the first connection — retried after 1 min, doubling up to 1 h, while the server keeps serving; a client that sends no SNI (connecting by IP address) is given the first domain’s certificate instead of a failed handshake (go-authn/servercert v0.5.0). HARICA: only an Enterprise Admin (OV) account issues without a challenge, and CAA must allow harica.gr
v0.28.0the admin API is also served over HTTPS for OIDC tokens — Connect, gRPC-Web and gRPC on one listener, one audience per server, callers named by subject or group per issuer — the first step towards the web and native UIs
v0.28.1security: built with Go 1.27.2 and golang.org/x/net v0.60.0, which fix GO-2026-6617 (an HTTP/2 HPACK race that could crash a server), GO-2026-6613, -6612, -6611, -6610 and -6603. The admin API over HTTPS speaks HTTP/2. go install now requires Go 1.27.2, and switches to it by itself
v0.29.1a reload treats a group emptied in the directory as it treats a deleted one: it grants nothing, and the reload’s notes say group @x has no members: it grants nothing (go-authn/directory v0.12.0, which tells an empty group from a missing one)
v0.29.0WebDAV: a PROPFIND of the root lists the shares (207; Depth infinity 403, writes 405), so a file manager can mount the whole server; an upload can go in pieces, each Content-Range appended where the last ended (go-filesystems/webdav v0.6.0) — what the file explorer needs

Upgrading to v0.21.0

A full directory share answers differently. EDQUOT (a quota) and ENOSPC are now one error, “no space left on device (the share is full)”, on every directory share, not only volumes: an EDQUOT that was WebDAV 500 and NFS NFS3ERR_IO is now 507 and NFS3ERR_NOSPC, and SFTP’s text is that sentence, without the path. SMB still answers access denied. See a full share.

Upgrading to v0.20.0

The provider’s alice no longer gets the local alice’s shares. A site whose provider’s names are its local names adds local_names = true to the oidc block (and sets domains); the server logs that line for each name it refuses for want of it.

Upgrading to v0.19.0

A users "ldap" block pointing at ldap:// on another machine without start_tls = true no longer starts: use ldaps://, or StartTLS.

Upgrading to v0.17.0

A configuration with one share inside another, two shares on one source, or an access file (authorized_keys_file, dsn_file, bind_password_file, the ssf ca_file) inside a share no longer starts; the error names the share and the path.

Upgrading past v0.9.0

A configuration serving WebDAV without TLS on an address other machines can reach, with anybody to authenticate, no longer starts. Add tls = true and a tls block, or plaintext = true behind a TLS-terminating proxy. See TLS.

Verified

These are things a client that this project did not write was made to do, not assertions about the code.

  • macOS mounts a share over SMB while curl is writing to the same image over WebDAV, and reads back what WebDAV wrote. Bob’s WebDAV write to a share he may only read is 403; a wrong password is 401.
  • go-smb2 — a client this project did not write — drives twenty concurrent reads through SMB while twenty run through WebDAV, under -race, in CI.
  • The access rules are checked through every protocol rather than in the configuration alone: alice writes and bob does not, over SMB and over WebDAV, and NFS is not offered the share at all.
  • SFTP certificates are verified against OpenSSH’s own client, which also refuses the same key once its certificate is moved aside.
  • NFS identities from certificates were measured with a real Linux client (kernel 6.17, ktls-utils 0.9) in go-filesystems/nfs’s CI — which is how MNT in the clear and tlshd’s pitfalls were found.
  • The KRL’s unsigned form is a measurement: OpenSSH 9.6 and 10.3 read a signed KRL and skip the signature (go-authn/krl, against both).
  • go-authn/bridge’s interop lane (#12, #17) judges fileshare v0.13.0 against the real bridge: the KRL, the CRL over NFS, WebDAV tokens revoked over shared signals, an IdP disabled by scope, and opkssh over shared signals.

Not yet

Writes over S3. PUT and DELETE answer 403. The library can write, but a share a person may only read has to refuse at the same place SFTP does, and that is not wired. Refusing beats a half-written object.

An OIDC token over S3. Tokens work over WebDAV and nowhere else. The usual route for S3 is STS AssumeRoleWithWebIdentity, which exchanges the token for temporary credentials the client then signs with — a different mechanism from accepting a bearer token, and not implemented.

--isolate with an admin or a metrics block. Refused: there is no one process an API change could be applied to. See one process per protocol.

A person per user on a shared Linux NFS client, from a certificate. A Linux client attaches the certificate to a mount, so every user of the mount is the person it names. That is a property of the client, and the answer there is sec=krb5. See what it cannot promise.

S3 itself has shipped: a share is a bucket, served over the same per-user tree SFTP uses.

Measured, and stated as measured

Claims in these pages that are insurance or measurement rather than reproductions of a defect, and are written that way in the source too:

  • Eight goroutines writing through an unwrapped fat32 driver under -race produce no race today. The shared lock is insurance on a contract — go-filesystems/interface promises nothing about concurrent path-based calls — not a fix for an observed failure.
  • The build-tag sizes were measured, including the 13.2 MB that hashicorp/go-plugin costs on its own, which is what decided against a plugin framework — and the 11.7 MB gRPC costs now that the admin API brings it, which is why nogrpc exists.
  • A group-tag certificate extension of its own was designed and measured against Go’s X.509 parser, which refused the whole certificate; the groups travel as tag URIs instead.

Created on by tannevaled

Modified on by tannevaled