Skip to main content

Authorization

This document describes how authorization is implemented in the ORT Server.

Keycloak

The ORT Server is integrated with Keycloak for identity and access management. Therefore, all roles and permissions are managed by Keycloak, and the server defines which roles and permissions exist. Keycloak itself knows only roles, therefore, all roles and permissions described below will be represented by roles in Keycloak.

Entities

This section summarizes the entities that are relevant to the access management.

Permission

A permission to perform a specific action or access a resource on the ORT Server. It is implemented as a role in Keycloak.

Role

A role is a group of permissions. It is implemented as a composite role in Keycloak.

User

A single user that can log in to the ORT Server. A user can have assigned roles or be member of groups.

Group

A group of users that can have assigned roles. All users in the group inherit all roles from the group.

Specification

This specifies the available groups, roles, and permissions for organizations, products, and repositories in the ORT Server.

Organizations are a root entity used for grouping content in the ORT Server. Each organization can have multiple products, and each product can have multiple repositories. A repository represents a VCS repository, for example, a Git repository on GitHub.

For each of those entities, the ORT Server defines a set of fine-grained permissions which are grouped into reader, writer, and admin roles. For each role, the ORT Server creates a group in Keycloak which makes it easier to manage the users that are assigned to the roles.

For now, the ORT Server supports a static role concept which might later be extended to support the customization of roles and permissions assigned to them. It is possible to edit roles and groups in Keycloak, but the ORT Server needs to know the meaning of those roles and groups, so manual changes in Keycloak can lead to unexpected results. Therefore, the ORT Server performs an automatic synchronization of roles and groups.

Please note that the roles and permissions below are not complete and serve just as examples. The currently defined roles and permissions can be looked up in the enum classes where they are defined.

Organizations

Permissions

NameFunctionName in Keycloak
READRead organization detailspermissionorganization$id_read
WRITEWrite organization detailspermissionorganization$id_write
READ_PRODUCTSRead list of productspermissionorganization$id_read_products
CREATE_PRODUCTCreate a new product in the organizationpermissionorganization$id_create_product
DELETE_ORGANIZATIONDelete the organizationpermissionorganization$id_delete

Roles

NamePermissionsName in KeycloakGroup name in Keycloak
ReaderREAD, READ_PRODUCTSroleorganization$id_readerORGANIZATION_$id_READERS
WriterREAD, READ_PRODUCTS, WRITE, CREATE_PRODUCTroleorganization$id_writerORGANIZATION_$id_WRITERS
Admin*roleorganization$id_adminORGANIZATION_$id_ADMINS

Products

Permissions

NameFunctionName in Keycloak
READRead product detailspermissionproduct$id_read
WRITEWrite product detailspermissionproduct$id_write
READ_REPOSITORIESRead list of repositoriespermissionproduct$id_read_repositories
CREATE_REPOSITORYCreate a new repository in the productpermissionproduct$id_create_repository
DELETE_PRODUCTDelete the productpermissionproduct$id_delete

Roles

NamePermissionsName in KeycloakGroup name in Keycloak
ReaderREAD, READ_REPOSITORIESroleproduct$id_readerPRODUCT_$id_READERS
WriterREAD, READ_REPOSITORIES, CREATE_REPOSITORYroleproduct$id_writerPRODUCT_$id_WRITERS
Admin*roleproduct$id_adminPRODUCT_$id_ADMINS

Repositories

Permissions

NameFunctionName in Keycloak
READRead repository detailspermissionrepository$id_read
WRITEWrite repository detailspermissionrepository$id_write
READ_ORT_RUNSRead scan resultspermissionrepository$id_read_ort_runs
TRIGGER_ORT_RUNTrigger a new ORT run for the repositorypermissionrepository$id_trigger_ort_run
DELETE_REPOSITORYDelete the repositorypermissionrepository$id_delete

Roles

NamePermissionsName in KeycloakGroup name in Keycloak
ReaderREAD, READ_SCANSrolerepository$id_readerREPOSITORY_$id_READERS
WriterREAD, READ_SCANS, TRIGGER_SCANrolerepository$id_writerREPOSITORY_$id_WRITERS
Admin*rolerepository$id_adminREPOSITORY_$id_ADMINS

Superuser

In addition to the roles and permissions defined above, the ORT Server also creates a "superuser" role and a "SUPERUSERS" group which can be used for server administrators. Users with the "superuser" role have access to all resources.

Hierarchy

The roles defined above are also hierarchical, that means that, for example, the reader role for an organization includes reader roles for all products in the organization, and the reader role for a product includes reader roles for all repositories in the product.

The idea behind this is to simplify checking for access permissions in the backend, because there are often multiple roles that can give access to a resource. For example, an organization administrator is also an administrator for all products in the organization. So, when performing an action on a product that requires admin permissions, the backend would have to check if the user is either an administrator for the product or an administrator for the organization. With the hierarchical concept, it only needs to check for the specific permission, because the organization administrator role contains all product administrator roles and therefore also all permissions for all products within the organization.

Examples

Below is a list of the roles and permissions for the following setup:

  • Organization 1
    • Product 1
      • Repository 1

Roles

NamePermissionsContained Roles
role_organization_1_readerpermission_organization_1_read, permission_organization_1_read_productsrole_product_1_reader
role_organization_1_writerpermission_organization_1_read, permission_organization_1_read_products, permission_organization_1_write, permission_organization_1_create_productrole_product_1_writer
role_organization_1_adminpermission_organization_1_read, permission_organization_1_read_products, permission_organization_1_write, permission_organization_1_create_product, permission_organization_1_deleterole_product_1_admin
role_product_1_readerpermission_product_1_read, permission_product_1_read_repositoriesrole_repository_1_reader
role_product_1_writerpermission_product_1_read, permission_product_1_read_repositories, permission_product_1_write, permission_product_1_create_repositoryrole_repository_1_writer
product1_administratorpermission_product_1_read, permission_product_1_read_repositories, permission_product_1_write, permission_product_1_create_repository, permission_product_1_deleterole_repository_1_administrator
role_repository_1_readerpermission_repository_1_read, permission_repository_1_read_ort_runs
role_repository_1_writerpermission_repository_1_read, permission_repository_1_read_ort_runs, permission_repository_1_writer, permission_repository_1_trigger_ort_run
role_repository_1_administratorpermission_repository_1_read, permission_repository_1_read_ort_runs, permission_repository_1_writer, permission_repository_1_trigger_ort_run, permission_repository_1_delete

Groups

NameContained Role
ORGANIZATION_1_READERSrole_organization_1_reader
ORGANIZATION_1_WRITERSrole_organization_1_writer
ORGANIZATION_1_ADMINSrole_organization_1_admin
PRODUCT_1_READERSrole_product_1_reader
PRODUCT_1_WRITERSrole_product_1_writer
PRODUCT_1_ADMINSrole_product_1_admin
REPOSITORY_1_READERSrole_repository_1_reader
REPOSITORY_1_WRITERSrole_repository_1_writer
REPOSITORY_1_ADMINSrole_repository_1_admin

Authentication

Authentication is implemented using OpenID Connect (also see the Keycloak specific docs).

The client roles of a user are not read from the JWT token, but are requested using the Keycloak API. This has the benefit that all role changes in Keycloak are recognized immediately, not only when an access token is refreshed. Another benefit is that the client roles do not have to be contained in the access token which makes it smaller.

An alternative to using the Keycloak API would have been to use the userinfo endpoint. However, the implementation would have been more complex, because access to the API was already implemented for the role and group management.

Keycloak Configuration

The JWT token created by Keycloak must contain the audience configured in the jwt.audience configuration property of the core module. For this, it is required to add an audience mapper to the client scope that adds the name of the audience to the JWT token.

By default, Keycloak creates a "roles" client scope that includes a "client roles" token mapper which adds all client roles of a user to the JWT token. This can lead to very large JWT tokens if a user has many roles assigned, therefore, this mapper should be configured to not add the client roles to the access token.

Access Management

While roles and groups should not be manually edited in Keycloak, the Keycloak UI is currently the only place where users can be granted permissions. This might later be changed by introducing API endpoints to manage permissions, or by implementing a UI for this.

To manage user access, users should be added to the groups created for the entities. For example, to give a user read access to the organization with the id "1", the user should be added to the group "ORGANIZATION_1_READERS". Assigning roles directly to users is not recommended, because the role definitions could change with any update of the ORT Server, for example, by adding or removing permissions, or changing which permissions belong to a role. If a user is added to a group, the ORT Server ensures that the group always has the correct roles and permissions assigned.

Please note that it is possible to configure a prefix for group names, so the actual group names could be different to those used in this documentation. For example, if the group name prefix is set to "PREFIX_", the group from the previous paragraph would be called "PREFIX_ORGANIZATION_1_READERS". The prefix option is useful in a testing setup where multiple instances of the ORT Server share the same Keycloak realm.

Keycloak Synchronization

The ORT Server automatically synchronizes the defined roles and permissions with the roles and groups in Keycloak. Currently, this happens when the core module is started. This might later be extended by triggering synchronization periodically or by adding an endpoint to trigger synchronization manually.

Synchronization is required because:

  • The role and permission definitions could have changed when upgrading to a newer version of the ORT Server.
  • The roles and groups could have been manually changed in Keycloak, leading to unexpected results.

During synchronization, the ORT Server verifies that:

  • All permissions for all hierarchy entities (organizations, products, and repositories) are represented by roles in Keycloak.
  • All roles for all hierarchy entities are represented by composite roles in Keycloak and have the correct child roles assigned.
  • All roles for all hierarchy entities are represented by groups in Keycloak and have the correct roles assigned.