Using authorization
BuildGrid supports authorization using either JWTs or request headers. When using request headers, the authenticity of the claimed identity is not verifiable by BuildGrid. This means that the headers should be set by (for example) a trusted proxy which does some identity verification rather than the client directly.
Controlling access to individual requests is done by configuring an ACL. This configuration is optional, but if present must completely define access to all instances specified in the main configuration file. Missing instances default to denying all access.
ACL configuration
Regardless of the authorization mode, the acls
configuration key can
be used to provide the path to an ACL configuration file.
The config is of the format:
<instance-name>:
allow:
- actor: .*
subject: .*
workflow: .*
requests:
# List of request name strings
- Execute
- ...
actor
, subject
, and workflow
are optional keys which allow limiting
access based on the client’s identity. These keys are regular expressions used
to match against the identity information provided by the client.
There can be multiple entries in this allow
list, if different client
identities need to be able to have different access permissions.
If an ACL configuration file is provided, then all instance names in the main config file must have a corresponding entry defined in the ACL configuration file. Any missing instance names will have all requests denied by default. To ease verbosity if not all instance names actually need authorization, there is a shorthand for “allow all”.
<instance-name>:
allow: all
An exhaustive example could be as follows.
prod:
allow:
# All prod user accounts have CAS write access
- actor: prod.*
requests:
- BatchUpdateBlobs
- QueryWriteStatus
- Write
# Only requests with the correct actor claim can perform read/write
# requests
- actor: prodbuilder
requests:
- Execute
- WaitExecution
- CancelOperation
# Only workers should be able to connect to the Bots service
- actor: prodworker
requests:
- CreateBotSession
- UpdateBotSession
# BuildGrid itself needs to be able to create LogStreams and
# update ActionResults
- actor: bgd
requests:
- CreateLogStream
- UpdateActionResult
# Read-only requests should be allowed regardless of header claims
- requests:
- GetCapabilities
- GetActionResult
- GetOperation
- ListOperations
- Read
- FindMissingBlobs
- BatchReadBlobs
- GetTree
Header-based authorization
authorization:
mode: headers
acls: /path/to/acl.yaml
allow-unauthorized-instances: [ '', 'dev' ]
This authorization method reads the x-request-actor
, x-request-subject
,
and x-request-workflow
headers and compares them with the corresponding
regular expressions defined in the ACL configuration.
If no ACL is configured then this method does no authorization, and all requests are permitted.
Since there is no way to verify the authenticity of these headers, it is important to only use this method when the requests are from a trusted source. A deployment architecture where this may be useful is deploying BuildGrid strictly behind a reverse proxy, where the reverse proxy is responsible for validating the client identity and setting these headers before forwarding the request.
If you want to allow some instances to skip the authorization you can optionally add your instances in allow-unauthorized-instances. The instances listed here will not be validated in any way
Secret-based JWT authorization
authorization:
mode: jwt
algorithm: hs256
secret: /path/to/secret.key
acl-config: /path/to/acl.yaml
allow-unauthorized-instances: [ '', 'dev' ]
Secret-based JWT authorization expects incoming requests to populate the
Authorization
request header with a JWT containing some claims about
the client identity. The JWT must be able to be decoded using the given
secret and algorithm.
If an ACL configuration is provided, the act
, sub
, and aud
JWT
claims are compared with the actor, subject, and workflow regular expressions
respectively for the given instance to determine whether or not the request
is permitted.
If no ACL configuration is provided, then this authorization mode only ensures that the JWT is valid and not expired.
If you want to allow some instances to skip the authorization you can optionally add your instances in allow-unauthorized-instances. The instances listed here will not be validated in any way
JWKS-based JWT authorization
authorization:
mode: jwt
algorithm: hs256
jwks-url: http://example.com/jwks
jwks-fetch-minutes: 30
acls: /path/to/acl.yaml
allow-unauthorized-instances: [ '', 'dev' ]
JWKS-based JWT authorization works in the same way as the secret-based JWT
approach, except the secret key(s) for decoding JWTs are fetched from a remote
server as a JWKS. For a JWT to be valid it must be able to be decoded with
one of the keys in the key set returned from the given jwks-url
.
The JWKS will be cached locally for jwks-fetch-minutes
minutes, which
defaults to 60 if unset.
ACLs and unauthorized instances are handled in exactly the same was as in the secret-based JWT approach.