You are reading the documentation for an outdated Corteza release. 2023.9 is the latest stable Corteza release.

Access control

Corteza defines a RBAC access control facility. RBAC uses the roles of the given user to determine if they have access to the given resource.

The access control facility should be invoked whenever an identity is trying to access a protected resource. The only exception are resources that are only accessed by the system itself, such as settings, configuration options, and other system metadata.

DevNote some diagrams outlining the different flows

Structure overview

pkg/rbac

RBAC rules are loaded into memory and accessed from there. The store layer is only involved when loading, reloading, or updating RBAC rules.

pkg/rbac contains the core logic, later referenced by other components and their services.

The important parts of the package:
  • rbac.service (struct): encapsulates rule management and access control check logic. Initialized with rbac.NewService(…​). A singleton can be initialized with rbac.SetGlobal(…​) and accessed with rbac.Global().

  • rbac.Resource (interface): a generic interface for a more structured resource handling

  • rbac.Session (interface): a security session interface for a specific user-roles combinations. Predefined structures can be initialized with rbac.ContextToSession(…​) or rbac.NewSession(…​).

<component>/service

Each components' service defines an accessControl struct that is generated from def/\*.yaml files. See the Extending sub-sections for more details.

The accessControl struct defines all resources and operations relevant to the given component and serves as a proxy to the internal pkg/rbac.Service. The accessControl struct also performs grant action logging, validation, and access control.

Extending

Add a new resource

To add an entirely new resource, define a new file in the /def directory.

The file should follow the pattern of: {component}(.{resource}).yaml. For example: system.user.yaml.

If you’re defining component-level rules, omit the (.{resource}) part. For example: system.yaml.

The content template
rbac:
  operations:
    {operation}:
      description: {optional notes here}

This uses the new WIP codegen v3; run with go run pkg/codegen-v3/*.go def

Add new rules to existing resources

To add a new rule to an existing resource, navigate the file in the /def directory.

The file should follow the pattern of: {component}(.{resource}).yaml. For example: system.user.yaml.

If you’re defining component-level rules, omit the (.{resource}) part. For example: system.yaml.

If the file does not yet exist, create it.

Add entry under rbac.operations

The content template
rbac:
  operations:
    {operation}:
      description: {optional notes here}

This uses the new WIP codegen v3; run with go run pkg/codegen-v3/*.go def

Role types

List of roles for the bypass, authenticated, and anonymous type can not be changed at runtime. These roles can not be modified or renamed.

If a role is assigned as a bypass, it may not appear as any other role type (such as an authenticated or anonymous). In the case where this is not the case, Corteza will refuse to start.

Bypass

Bypass roles allow their members unlimited access to Corteza with no permission checking.

The list of bypass roles is defined in the RBAC_BYPASS_ROLES .env variable and can not be changed during runtime. The default role is super-admin.

Common

Common roles are any additional roles defined in the administration panel, such as a CRM admin and application builder.

Contextual

Contextual roles define a series of expressions, which determine when the role is assigned to the user based on the operations' context.

Each role can define an expression for each resource type. Each role can only use a resource type once.

An example use case would allow us to assign roles to resource owners, which would give them permissions that they shouldn’t have over other resources.

Authenticated

Authenticated roles are implicit, meaning that users can not explicitly be set as role members.

The list of authenticated roles is defined in the RBAC_AUTHENTICATED_ROLES .env variable and can not be changed during runtime. The default role is authenticated.

Anonymous

Anonymous roles are implicit, meaning that users can not explicitly be set as role members.

The list of anonymous roles is defined in the RBAC_ANONYMOUS_ROLES .env variable and can not be changed during runtime. The default role is anonymous.

Role importance

Role importance specifies the order in which the provided roles and their corresponding rules are evaluated.

Role importance for authenticated users:
  1. bypass roles

  2. context roles

  3. common roles

  4. authenticated roles

Role importance for authenticated users:
  1. anonymous roles

Resource identifiers

The resource identifier structure follows the pattern of:
{rbac-ns}:: (1)
  {component}: (2)
  {service} (3)
  {path} (4)
1 The RBAC namespace allows us to group RBAC rules based on the area, allowing us to support custom rules in the future. The namespace must match te regex of [a-z]*
2 The component must match te regex of [a-z]*
3 The service must match te regex of [a-zA-Z]+
4 The path must follow the pattern of (/[*,a-z,A-Z,0-9]\*)+

When defining resource identifiers, the n-th path item must be more or equally specific to the (n+1)-th path item. The following example is invalid, as the first item is less specific (wildcard *) than the second one: corteza::compose:record/\*/21/2.

Resource specificity

Resource specificity defines the order in which rules for the corresponding resources are evaluated. Resource specificity is defined based on "how specific is this rule to this resource".

As an example, a rule that allows users to create records on the account module in the CRM namespace is more specific than the rule just on the CRM namespace.

Under the hood, this is calculated based on the number of wildcard characters (*) in the resource definition. If the resource has no wildcard characters, the level is 0. If the resource has n wildcard characters, the level is n-1 (0-based).

Example resource identifiers

Compose component permissions

corteza::compose/

Permissions for any namespace (level=1)

corteza::compose:namespace:/*

Permissions for a specific namespace (level=0)

corteza::compose:namespace:/42

Permissions for all records on a specific namespace (level=2)

corteza::compose:record/42/*/*

Permissions for all records on a any namespace or any module (level=3)

corteza::compose:record/*/*/*

Permissions for a specific record (level=0)

corteza::compose:record/42/21/2

Permissions for record values on a specific module fields (level=0)

corteza::compose:moduleField/42/21/12

Access evaluation flow

The access is evaluated based on the security context (namely the role importance and resource specificity) and the operation they are trying to perform.

Access evaluation flow:
  1. If any rule defines an explicit deny, the evaluation results with deny.

  2. If at least one rule defines an explicit allow, the evaluation results with allow.

  3. If the current level has no explicit allow or deny, the evaluation continues to the next set of rules based on role importance.

  4. If the evaluation cannot find an explicit allow or deny, the evaluation results with deny.

The original RBAC evaluation flow:
  1. can this combination of roles perform an operation on this specific resource

  2. can this combination of roles perform an operation on any resource of the type (wildcard)

  3. can anyone/everyone perform an operation on this specific resource

  4. can anyone/everyone perform an operation on any resource of the type (wildcard)

Glossary

A user

A user is an entity that is accessing Corteza. A user can be a member of security roles and cannot get permissions directly without an assigned role.

A role

A role represents a set of users and a set of permissions over resources.

Corteza’s RBAC implementation defines a flat structure that removes role hierarchy (two roles can not explicitly specify a parent/child relationship).

Access

Defines if the rule permits (allow) or denies (deny).

A resource

A structured piece of information stored within Corteza that we may or may not control access to. Each resource belongs to a component and has a unique type.

A resource type

A resource type defines the structure of information within the Corteza component.

Operation

Defines what operation the given RBAC rule defines access to.

RBAC rule

A RBAC rule combines operation, role, access, and resource. It defines what someone can (or can not) do on one or more resources inside Corteza.

Security session

A security session is created when a user requests to access Corteza.