Auth Service manages and distributes data and configuration used for authorization decisions performed by services in a LUCI cluster.
This is the replacement of the GAE v1 version of Auth Service.
It is part of the control plane, and as such it is not directly involved in authorizing every request to LUCI. Auth Service merely tells other services how to do it, and they do it themselves.
There's one Auth Service per LUCI cluster. When a new LUCI service joins the cluster it is configured with the location of Auth Service, and Auth Service is configured with the identity of the new service. This is one time setup. During this initial bootstrap the new service receives the full snapshot of all authorization configuration, which it can cache locally and start using right away. Then the new service can either register a web hook to be called by Auth Service when configuration changes, or it can start polling Auth Service for updates itself.
Whenever authorization configuration changes (e.g. a group is updated), Auth Service prepares a new snapshot of all configuration, makes it available to all polling clients, and pushes it to all registered web hooks until they acknowledge it.
If Auth Service goes down, everything remains operational, except the authorization configuration becomes essentially “frozen” until Auth Service comes back online and resumes distributing it.
This section describes what exactly is “data and configuration used for authorization decisions”.
See AuthDB message in replication.proto for all details.
Groups are how the lowest layer of ACLs is expressed in LUCI, e.g. a service may authorize some action to members of some group. More complex access control rules use groups as building blocks.
Each group has a name (global to the LUCI cluster), a list of identity strings it includes directly (e.g. user:alice@example.com
), a list of nested groups, and a list of glob-like patterns to match against identity strings (e.g. user:*@example.com
).
An identity string encodes a principal that performs an action. It's the result of authentication stage. It looks like <type>:<id>
and can represent:
user:<email>
- Google Accounts (end users and service accounts).anonymous:anonymous
- callers that didn't provide any credentials.project:<project>
- a LUCI service acting in a context of some LUCI project when calling some other LUCI service.bot:<hostname>
- used only by Swarming, individual bots pulling tasks.bot:whitelisted-ip
- callers authenticated exclusively through an IP allowlist.service:<app-id>
- GAE application authenticated via X-Appengine-Inbound-Appid
header.Note that various UIs and configs may omit the user:
prefix; it is implied if no other prefix is provided. For example, *@example.com
in a UI actually means user:*@example.com
.
An IP allowlist is a named set of IPv4 and IPv6 addresses. They are primarily used in Swarming when authorizing RPCs from bots. IP allowlists are defined in the ip_allowlist.cfg
service configuration file.
This is a list of Google OAuth client IDs recognized by the LUCI cluster. It lists various OAuth clients (standalone binaries, web apps, AppScripts, etc) that are allowed to send end-user OAuth access tokens to LUCI. The OAuth client ID allowlist is defined in the oauth.cfg
service configuration file.
These are various bits of configuration (defined partially in the oauth.cfg
and in the security.cfg
service config files) that are centrally distributed to services in a LUCI cluster. Used to establish mutual trust between them.
This is a pRPC service to examine and modify the groups graph. It is used primarily by Auth Service's own web frontend (i.e. it is mostly used by humans). See the RPC Explorer (for chrome-infra-auth-dev). Alternatively, read the Groups service proto definitions and the corresponding Groups service implementation.
Services that care about availability must not use this API for authorization checks. It has no performance or availability guarantees. If you use this API, and your service goes down because Auth Service is down, it is your fault.
Instead, services should use AuthDB replication (normally through a LUCI client library such as go.chromium.org/luci/server) to obtain and keep up-to-date the snapshot of all groups, and use it locally without hitting Auth Service on every request. See the next couple of sections for more information.
All authorization configuration internally is stored in a single Cloud Datastore entity group. This entity group has a revision number associated with it, which is incremented with every transactional change (e.g. when groups are updated).
For every revision, Auth Service:
/auth_service/api/v1/authdb/revisions/<revId>
and the RPC method auth.service.AuthDB/GetSnapshot
.It is distributed in a such diverse way for backward compatibility with variety of AuthDB client implementations (in historical order):
/auth_service/api/v1/authdb/revisions/...
endpoint is how some Go GAE services consume AuthDB via [go.chromium.org/luci/server/auth] client./auth_service/api/v1/authdb/revisions/...
is also polled by Gerrit cria/
groups plugin.In all cases the goal is to let Auth Service know the identity of a new service and let the new service know the location of Auth Service. How this looks depends on where the new service is running and what client library it uses.
Go GAE/GKE/GCE services should use go.chromium.org/luci/server:
auth-trusted-services
group group by filing a go/pdeiosec-bug.-auth-service-host <auth-service>.appspot.com
flag.app.yaml
for the default
service, <service-name>.yaml
for additional services), pass the -auth-service-host
flag in the app's entrypoint./healthz
checks, you are done.How does it work?
-auth-service-host
flag is used to derive a Google Storage (GCS) path to look for an AuthDB snapshot.-auth-db-dump
flag./auth_service/api/v1/authdb/subscription/authorization
endpoint. This asks Auth Service to grant the service account authorization to:New services should not use this method of receiving AuthDB updates. The method is described below primarily for Auth Service developers' understanding.
How does it work?
auth-trusted-services
group./auth_service/api/v1/revisions/<revId|latest>
.auth-trusted-services
or administrators
groups.https://chrome-infra-auth.appspot.com
.<auth_service_url>/auth_service/api/v1/revisions/latest?skip_body=1
<auth_service_url>/auth_service/api/v1/revisions/<revId>
/auth_service/api/v1/authdb/subscription/authorization
endpoint. This asks Auth Service to grant the service account authorization to:Auth Service depends on following services:
Targeting the real datastore:
cd auth_service/services/frontend go run main.go -cloud-project chrome-infra-auth-dev
The server will be available at http://localhost:8800.
Prefer to test everything locally. If you must deploy to GAE, use:
cd auth_service gae.py upload --target ${USER} -A chrome-infra-auth-dev --app-dir services default backend
This will upload versions for both default
and backend
services, with target version name ${USER}
.
Note that it doesn't switch the default serving version. If you really need to set a manually uploaded version to be the default (not recommended), you may use Cloud Console or gcloud app services set-traffic
to switch the serving version of the default
and backend
services.
Deployment to staging and production are performed by gae-deploy builder. Deploying directly to production using gae.py
is strongly ill-advised.