blob: 39f4b04b81a0f94246b606b07d34391355337ade [file] [log] [blame]
// Copyright 2020 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Schema for realms.cfg project configuration file.
//
// RealmsCfg describes configuration of all realms of some single LUCI project.
syntax = "proto3";
package auth_service;
import "go.chromium.org/luci/common/proto/options.proto";
option (luci.file_metadata) = {
doc_url: "https://luci-config.appspot.com/schemas/projects:realms.cfg";
};
option go_package = "go.chromium.org/luci/common/proto/realms;realms";
// RealmsCfg defines a schema for realms.cfg project configuration file.
message RealmsCfg {
// List of all realms in the project in arbitrary order.
repeated Realm realms = 1;
// Optional list of custom roles that can be referenced from Bindings in this
// project.
repeated CustomRole custom_roles = 2;
}
// Realm is a named container for (<principal>, <permission>) pairs.
//
// A LUCI resource can point to exactly one realm by referring to its full
// name ("<project>:<realm>"). We say that such resource "belongs to the realm"
// or "lives in the realm" or is just "in the realm". We also say that such
// resource belongs to the project "<project>". The corresponding Realm message
// then describes who can do what to the resource.
//
// The logic of how resources get assigned to realms is a part of the public API
// of the service that owns resources. Some services may use a static realm
// assignment via project configuration files, others may do it dynamically by
// accepting a realm when a resource is created via an RPC.
//
// A realm can "extend" one or more other realms. If a realm `A` extends `B`,
// then all permissions defined in `B` are also in `A`. Remembering that a realm
// is just a set of (<principal>, <permission>) pairs, the "extend" relation is
// just a set inclusion.
//
// The primary way of populating the permission set of a realm is via bindings.
// Each binding assigns a role to a set of principals. Since each role is
// essentially just a set of permissions, each binding adds to the realm a
// Cartesian product of a set of permissions (defined via the role) and a set of
// principals (defined via a direct listing or via groups).
//
// There are two special realms (both optional) that a project can have: "@root"
// and "@legacy".
//
// The root realm is implicitly included into all other realms (including
// "@legacy"), and it is also used as a fallback when a resource points to
// a realm that no longer exists. Without the root realm, such resources become
// effectively inaccessible and this may be undesirable. Permissions in the root
// realm apply to all realms in the project (current, past and future), and thus
// the root realm should contain only administrative-level bindings. If you are
// not sure whether you should use the root realm or not, err on the side of not
// using it.
//
// The legacy realm is used for existing resources created before the realms
// mechanism was introduced. Such resources usually are not associated with any
// realm at all. They are implicitly placed into the legacy realm to allow
// reusing realms' machinery for them.
//
// Note that the details of how resources are placed in the legacy realm are up
// to a particular service implementation. Some services may be able to figure
// out an appropriate realm for a legacy resource based on resource's existing
// attributes. Some services may not have legacy resources at all. The legacy
// realm is not used in these case. Refer to the service documentation.
//
// A realm can also carry some small amount of data (usually auth related) that
// LUCI services use when dealing with this realm. It should be something that
// all (or at least more than one) LUCI services use. Configuration specific to
// a single service should be in this service's project config instead.
message Realm {
// Name of the realm.
//
// Must match `^[a-z0-9_\.\-/]{1,400}$` or be literals "@root" or "@legacy".
//
// Realm names must be unique within a project.
string name = 1;
// Optional list of realms whose permissions will be included in this realm.
//
// All realms implicitly extend "@root" realm (if it is defined), i.e. all
// permissions specified in the "@root" realm are propagated to all realms in
// the project.
//
// To keep the mental model simple, cycles aren't allowed (i.e. a realm is not
// allowed to directly or indirectly extend itself). The LUCI Config service
// will reject realms.cfg that contains cycles during the config validation
// phase.
repeated string extends = 2;
// List of bindings that define who can do what to resources in this realm.
repeated Binding bindings = 3;
// A list of LUCI service IDs that should enforce this realm's permissions.
//
// Children realms inherit and extend this list.
//
// Used only during Realms migration to gradually roll out the enforcement
// realm by realm, service by service.
repeated string enforce_in_service = 4;
}
// Binding assigns a role to all specified principals.
message Binding {
// Name of the role to assign.
//
// Can either be a predefined role (if starts with "role/") or a custom role
// (if starts with "customRole/"). See TODO for a list of predefined roles
// and their meanings.
//
// A custom role must be defined somewhere in this realms.cfg file.
string role = 1;
// A set of principals to assign the role to.
//
// Each entry can either be an identity string (like "user:<email>") or a
// LUCI group reference "group:<name>".
repeated string principals = 2;
}
// Custom role defines a custom named set of permissions.
//
// Can be used in bindings if predefined roles are too broad or do not map well
// to the desired set of permissions.
//
// Custom roles are scoped to the project (i.e. different projects may have
// identically named, but semantically different custom roles).
message CustomRole {
// Name of this custom role, must start with "customRole/".
string name = 1;
// Optional list of roles whose permissions will be included in this role.
//
// Each entry can either be a predefined role (if starts with "role/") or
// another custom role defined in this realms.cfg (if starts with
// "customRole/").
//
// To keep the mental model simple, cycles aren't allowed (i.e. a custom role
// is not allowed to directly or indirectly extend itself). The LUCI Config
// service will reject realms.cfg that contains cycles during the config
// validation phase.
repeated string extends = 2;
// Optional list of permissions to include in the role.
//
// Each permission is a symbol that has form "<service>.<subject>.<verb>",
// which describes some elementary action ("<verb>") that can be done to some
// category of resources ("<subject>"), managed by some particular kind of
// LUCI service ("<service>").
//
// Examples of permissions:
// * buildbucket.build.create
// * swarming.pool.listBots
// * swarming.task.cancel
//
// See TODO for a list of all possible permissions.
repeated string permissions = 3;
}