Explicit permissions API
Sourcegraph's GraphQL API allows users to explicitly set repository permissions. This is an alternative to other mechanisms, which involve directly talking to the code host.
Permissions mechanisms in parallel
Feature is in Experimental stage and is supported up to Sourcegraph 5.0
NOTE: Up to version 5.0, if the Explicit permissions API is enabled, all the other repository permissions mechanisms are disabled. If you're using Sourcegraph with multiple code hosts, it's not possible to use the explicit permissions API for one code host and use other mechanisms for getting permissions for others.
If you want to use explicit permissions API alongside synced permissions, read section permission mechanisms in parallel here.
Recommendations
We only recommend to use explicit permissions API in cases, where the other methods are not possible or effective. E.g. if a code host does not support permission syncing/webhooks or if it would take an unreasonable amount of resources/time to sync permissions from the code host.
It's also a good idea to use explicit permissions API if the source of truth for the codehost permissions is already defined in some external system, e.g. LDAP group membership. In that case, it might be less resource intensive to sync the permissions from external source of truth directly via a periodically running routine.
SLA
Sourcegraph SLA is, that p95 of write requests to the explicit permissions API will be resolved within 10 seconds.
Sourcegraph does not provide SLA for how fresh the permissions are, since the data is provided as is to the API.
Disadvantages
It is important to note, that when using explicit permissions API, the permissions are written to the database as provided, without further verification that such permissions do exist on the code host side.
Keeping the permissions in sync and fresh is the responsibility of the site admins.
Configuration
To enable the permissions API, add the following to the site configuration:
JSON"permissions.userMapping": { "enabled": true, "bindID": "username" }
The bindID
value specifies how to uniquely identify users when setting permissions:
username
: You can set permissions for users by specifying their Sourcegraph usernames. Using usernames is preferred, as usernames are required to be unique for each user.email
: You can set permissions for users by specifying their email addresses (which must be verified emails associated with their Sourcegraph user account). This method can lead to unexpected results if there are multiple Sourcegraph user accounts with the same verified email address.
After you enable the permissions API, you must set permissions to allow users to view repositories (site admins bypass all permissions checks and can always view all repositories).
NOTE: If you were previously using permissions syncing, e.g. syncing permissions from Github, then those permissions are used as the initial state after enabling explicit permissions. Otherwise, the initial state is for all repositories to have an empty set of authorized users, so users will not be able to view any repositories.
NOTE: In some cases, in order for the repo permissions to be enforced, you must re-save the code host connection configuration with some modification to the JSON after enabling the permissions API.
Setting a repository as unrestricted
Sometimes it can be useful to mark a repository as unrestricted
, meaning that it is available to all Sourcegraph users. This can be done with the setRepositoryPermissionsUnrestricted
mutation. Marking a repository as unrestricted will disregard any previously set explicit or synced permissions. Setting unrestricted
back to false
will restore the previous behaviour.
For example:
GRAPHQLmutation { setRepositoryPermissionsUnrestricted(repositories: ["<repo ID>", "<repo ID>", "<repo ID>"], unrestricted: true) }
Setting repository permissions for users
Setting the permissions for a user can be accomplished with 2 GraphQL API calls.
First, obtain the ID of the repository from its name:
GRAPHQLquery { repository(name: "github.com/owner/repo") { id } }
Next, set the list of users allowed to view the repository:
GRAPHQLmutation { setRepositoryPermissionsForUsers( repository: "<repo ID>", userPermissions: [ { bindID: "alice" }, { bindID: "bob" }, ]) { alwaysNil } }
Now, only the users specified in the userPermissions
parameter will be allowed to view the repository. Sourcegraph automatically enforces these permissions for all operations. (Site admins bypass all permissions checks by default. See the Site administrators section)
You can call setRepositoryPermissionsForUsers
repeatedly to set permissions for each repository, and whenever you want to change the list of authorized users.
Setting sub-repository permissions for users
Sourcegraph supports permissions on a per-file/directory basis.
To enable the sub-repo permissions API, add the following to the site configuration:
JSON"experimentalFeatures": { "subRepoPermissions": {"enabled": true} }
Sub-repo permissions can be set for a repository via the following GraphQL API:
GRAPHQLmutation { setSubRepositoryPermissionsForUsers( repository: "<repo ID>", userPermissions: [ { bindID: "alice", paths: ["-/**", "/README.md"] } ] ) { alwaysNil } }
This query denies the user alice
access to all files in the repository, except for the file README.md
.
The paths are specified in the glob syntax, and a -
prefix indicates that the path should be denied.
Permissions are applied in the order they are specified. If we were to want to provide alice
access to all files except for the README.md
file, we could specify the following:
GRAPHQLmutation { setSubRepositoryPermissionsForUsers( repository: "<repo ID>", userPermissions: [ { bindID: "alice", paths: ["/**", "-/README.md"] } ] ) { alwaysNil } }
The default permission if a path is not specified is to deny access.
Listing a user's authorized repositories
You may query the set of repositories visible to a particular user with the authorizedUserRepositories
GraphQL API query, which accepts a username
or email
parameter to specify the user:
GRAPHQLquery { authorizedUserRepositories(username: "alice", first: 100) { nodes { name } totalCount } }