Documentation ¶
Overview ¶
Package realms contains functionality related to LUCI Realms.
Index ¶
- Constants
- func ForbidPermissionChanges()
- func Join(project, realm string) (global string)
- func RegisteredPermissions() map[Permission]PermissionFlags
- func Split(global string) (project, realm string)
- func ValidatePermissionName(name string) error
- func ValidateProjectName(project string) error
- func ValidateRealmName(realm string, scope RealmNameScope) error
- type Attrs
- type Permission
- type PermissionFlags
- type RealmNameScope
Constants ¶
const ( // InternalProject is an alias for "@internal". // // There's a special set of realms (called internal realms or, sometimes, // global realms) that are defined in realms.cfg in the LUCI Auth service // config set. They are not part of any particular LUCI project. Their full // name have form "@internal:<realm>". InternalProject = "@internal" // RootRealm is an alias for "@root". // // 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. // // HasPermission() automatically falls back to corresponding root realms if // any of the realms it receives do not exist. You still can pass a root realm // to HasPermission() if you specifically want to check the root realm // permissions. RootRealm = "@root" // LegacyRealm is an alias for "@legacy". // // The legacy realm should be used for legacy resources created before the // realms mechanism was introduced in case the service can't figure out a more // appropriate realm based on resource's properties. The service must clearly // document when and how it uses the legacy realm (if it uses it at all). // // Unlike the situation with root realms, HasPermission() has no special // handling of legacy realms. You should always pass them to HasPermission() // explicitly when checking permissions of legacy resources. LegacyRealm = "@legacy" // ProjectRealm is an alias for "@project". // // The project realm is used to store realms-aware resources which are global // to the entire project, for example the configuration of the project itself, // or derevations thereof. The root realm is explicitly NOT recommended for // this because there's no way to grant permissions in the root realm without // also implicitly granting them in ALL other realms. ProjectRealm = "@project" )
Variables ¶
This section is empty.
Functions ¶
func ForbidPermissionChanges ¶
func ForbidPermissionChanges()
ForbidPermissionChanges explicitly forbids registering new permissions or changing their flags.
All permissions should be registered before the server starts running its loop. The runtime relies on this when building various caches. After this function is called, RegisterPermissions and AddFlags would start panicking.
Intended for internal server code.
func Join ¶
Join returns "<project>:<realm>".
Doesn't validate the result. If this is a concern, use ValidateRealmName explicitly.
func RegisteredPermissions ¶
func RegisteredPermissions() map[Permission]PermissionFlags
RegisteredPermissions returns a snapshot of all registered permissions along with their flags.
Implicitly calls ForbidPermissionChanges to make sure no new permissions are added later.
func Split ¶
Split splits a global realm name "<project>:<realm>" into its components.
Panics if `global` doesn't have ":". Doesn't validate the resulting components. If this is a concern, use ValidateRealmName explicitly.
func ValidatePermissionName ¶
ValidatePermissionName returns an error if the permission name is invalid.
It checks the name looks like "<service>.<subject>.<verb>".
func ValidateProjectName ¶
ValidateProjectName validates a project portion of a full realm name.
It should match `^[a-z0-9\-_]{1,100}$` or be "@internal".
func ValidateRealmName ¶
func ValidateRealmName(realm string, scope RealmNameScope) error
ValidateRealmName validates a realm name (either full or project-scoped).
If `scope` is GlobalScope, `realm` is expected to have the form "<project>:<realm>". If `scope` is ProjectScope, `realm` is expected to have the form "<realm>". Any other values of `scope` cause panics.
In either case "<realm>" is tested against `^[a-z0-9_\.\-/]{1,400}$` and compared to literals "@root" and "@legacy".
When validating globally scoped names, "<project>" is tested using ValidateProjectName.
Types ¶
type Attrs ¶
Attrs are the context of a particular permission check.
Attributes specified here are used as inputs to `conditions` predicates in conditional bindings. If a service supports conditional bindings, it must document what attributes it passes with each permission it checks.
For example, a service may document that when it checks permission "service.entity.create" it supplies an attribute with key "service.entity.name" and the value matching the name of the entity being created.
One then can create a binding like:
role: "role/service.entities.creator" principals: ["user:restricted-creator@example.com"] conditions: { restrict { attribute: "service.entity.name" values: ["name1", "name2"] } }
That binding encodes that "user:restricted-creator@example.com" can create entities *only* if they are named "name1" or "name2".
type Permission ¶
type Permission struct {
// contains filtered or unexported fields
}
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>").
Each individual LUCI service should document what permissions it checks and when. It becomes a part of service's public API. Usually services should check only permissions of resources they own (e.g. "<service>.<subject>.*"), but in exceptional cases they may also check permissions intended for other services. This is primarily useful for services that somehow "proxy" access to resources.
func GetPermissions ¶
func GetPermissions(names ...string) ([]Permission, error)
GetPermissions returns the permissions with the matching names. The order of the permission is the same as the provided names.
Implicitly calls ForbidPermissionChanges to make sure no new permissions are added later.
Returns an error if any of the permission isn't registered.
func RegisterPermission ¶
func RegisterPermission(name string) Permission
RegisterPermission adds a new permission with the given name to the process registry or returns an existing one.
Panics if the permission name doesn't look like "<service>.<subject>.<verb>".
Must to be called during startup, e.g. in init(). Panics if called when the process is already serving requests.
func (Permission) AddFlags ¶
func (p Permission) AddFlags(flags PermissionFlags)
AddFlags appends given flags to a registered permission.
Permissions are usually defined in shared packages used by multiple services. Flags that makes sense for one service do not always make sense for another. For that reason RegisterPermission and AddFlags are two separate functions.
Must to be called during startup, e.g. in init(). Panics if called when the process is already serving requests.
func (Permission) Name ¶
func (p Permission) Name() string
Name is "<service>.<subject>.<verb>" string.
func (Permission) String ¶
func (p Permission) String() string
String allows permissions to be used as "%s" in format strings.
type PermissionFlags ¶
type PermissionFlags uint8
PermissionFlags describe how a registered permission is going to be used in the current process.
These are purely process-local flags. It is possible for the same single permission to be defined with different flags in different processes.
const ( // UsedInQueryRealms indicates the permission will be used with QueryRealms. // // It instructs the runtime to build an in-memory index to speed up the query. // This flag is necessary for QueryRealms function to work. It implies some // performance and memory costs and should be used only with permissions that // are going to be passed to QueryRealms. UsedInQueryRealms PermissionFlags = 1 << iota )
type RealmNameScope ¶
type RealmNameScope string
RealmNameScope specifies how realm names are scoped for ValidateRealmName.
const ( // GlobalScope indicates the realm name is not scoped to a project. // // E.g. it is "<project>:<realm>". GlobalScope RealmNameScope = "global" // ProjectScope indicates the realm name is scoped to some project. // // E.g. it is just "<realm>" (instead of "<project>:<realm>"). ProjectScope RealmNameScope = "project-scoped" )