Active Directory for SFTP — read-only vs read-write groups

· ~4 minute read

The most common pre-sales question we hear from enterprise prospects is some version of: “We authenticate against Active Directory. Can we control who gets upload access and who gets download-only?”

The answer is yes, and it is two XML elements in the LDAP block of your server configuration. No scripts, no scheduled tasks, no per-user overrides to maintain by hand. The server reads the user’s memberOf attribute at login and decides on the spot.

The two group lists

Stylus SFTP Server’s LDAP provider accepts two lists of Active Directory group names inside the <ldap> block of sftp-server.xml:

<ldap>
    <url>ldap://dc01.corp.example.com:389</url>
    <base-dn>ou=Users,dc=corp,dc=example,dc=com</base-dn>
    <bind-dn>cn=sftpservice,ou=Service,dc=corp,dc=example,dc=com</bind-dn>
    <bind-password>...</bind-password>
    <username-attribute>sAMAccountName</username-attribute>

    <access-groups>
        <group>SFTP-Writers</group>
        <group>FileTransfer-Team</group>
    </access-groups>

    <read-only-groups>
        <group>SFTP-Readers</group>
        <group>Auditors</group>
    </read-only-groups>
</ldap>

<access-groups> names the AD groups whose members get full read-write access to their home directory: upload, download, create subdirectories, rename, delete. <read-only-groups> names the groups whose members can download and list files but cannot upload, create, rename, or delete anything.

Each list can hold as many <group> entries as you need. The value is the Common Name (CN) of the AD group — not the full distinguished name.

How it works at login

When a user authenticates, the server performs a two-bind LDAP flow: first it binds as the service account to search for the user’s entry, then it rebinds with the user’s own password to verify credentials. During the service-account search, the server fetches the memberOf attribute and walks each group DN in the list. For every group, it extracts the CN and checks whether it appears in either configured list. The matching is case-insensitiveSFTP-Writers, sftp-writers, and Sftp-Writers all match the same entry.

The result is one of three access levels:

  1. READ_WRITE — the user matched at least one access group (and no read-only group).
  2. READ_ONLY — the user matched at least one read-only group.
  3. DEFAULT — no configured groups matched at all, or the user has no memberOf attribute, or no groups are configured.

Most restrictive wins

If a user is a member of both an access group and a read-only group — say they are in SFTP-Writers and Auditorsread-only wins. This is a deliberate design choice. The principle is that the restrictive assignment should never be overridden by a permissive one. An AD administrator can always remove the user from the read-only group if write access is needed; the server will not silently escalate.

In the source code (LdapUserManager.resolveAccessLevel), the logic checks read-only membership first. If the hasReadOnly flag is set, the method returns READ_ONLY regardless of whether hasAccess is also true.

What DEFAULT means

When the user does not match any configured group, the server falls back to the <default-access> setting in filesystem-config.xml:

<default-access>read-write</default-access>

This default also applies when the LDAP block has no <access-groups> or <read-only-groups> at all — meaning every authenticated LDAP user gets whatever the default is. In most installations, the default is read-write. For tighter postures, set it to read-only and use access groups as the explicit opt-in for upload rights.

This three-tier model — explicit write, explicit read-only, fallback default — covers the two most common AD deployment patterns we see:

Where enforcement happens

The read-only flag travels from the LDAP provider through the UserEntry record into the session’s HomeContext. Every protocol surface — SFTP, FTP, FTPS, WebDAV, and the browser-based File Portal — passes write operations through the same PathAuthorizer. If the session is marked read-only, any write action (upload, mkdir, rename, delete) is rejected with the protocol-appropriate permission-denied error. There is no separate enforcement path per protocol — a read-only user is read-only everywhere.

Managing it day to day

Because the access decision is derived from AD group membership at every login, there is nothing to synchronize. Add a user to SFTP-Writers in Active Directory, and their next SFTP session has upload access. Move them to Auditors, and their next session is read-only. Remove them from all configured groups, and they fall back to the default. The SFTP server never caches group membership across sessions — it asks AD every time.

The group lists are also manageable from the Web Admin console (Security → LDAP Groups), the Swing GUI, and the CLI. All three admin surfaces read and write the same <access-groups> and <read-only-groups> elements in the config file.

Try Active Directory authentication

Free evaluation key. Point the LDAP block at your domain controller and see group-based access control working in minutes.

Request Evaluation Key More articles ›