realms

package
v0.0.0-...-d3da680 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 4, 2024 License: Apache-2.0 Imports: 5 Imported by: 10

Documentation

Overview

Package realms contains functionality related to LUCI Realms.

Index

Constants

View Source
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

func Join(project, realm string) (global string)

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

func Split(global string) (project, realm string)

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

func ValidatePermissionName(name string) error

ValidatePermissionName returns an error if the permission name is invalid.

It checks the name looks like "<service>.<subject>.<verb>".

func ValidateProjectName

func ValidateProjectName(project string) error

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

type Attrs map[string]string

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"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL