Skip to content

infratographer/permissions-api

logo

permissions-api - Permissions management service

Hello, and welcome to permissions-api! permissions-api is a service designed for checking and managing permissions on resources in the Infratographer ecosystem.

permissions-api is made up of two components:

  • A policy decision endpoint for making permissions checks
  • A management API for resources necessary to make decisions

To get started using permissions-api, see the Usage section of this README.

Concepts

permissions-api is designed to answer the following question: Does the given subject have permission to perform the requested action on the requested resource?

Permission is granted by the assignment of roles to subjects.

The concepts necessary to accomplish this are described in this section.

Resource

A resource is any uniquely identifiable thing in the Infratographer ecosystem. Resources have types and are identified using Prefixed IDs in permissions-api. For example, the Prefixed ID loadbal-hWV_xTSoYqIkXXWyK6eco corresponds to a resource of type loadbalancer.

Subject

A subject is any resource that can be granted permission to perform some action. A subject may be a user, an OAuth client, a server instance, or any other resource.

Relationship

A relationship is a named link between a resource and a subject (another resource). Resources in permissions-api are defined entirely in terms of their relationships. For example, a load balancer and tenant might be related to each other using a relationship with the name tenant, where the resource is a load balancer and the subject is a tenant.

Action

An action is a verb that describes something that can be done to a resource (e.g., "update"). Actions map to permissions in SpiceDB, and are scoped to and named based on resources. For example, an action called update scoped to the loadbalancer resource is referred to as loadbalancer_update.

When making authorization decisions, permissions-api walks the graph of known relationships to determine whether a path exists between the resource and subject, and whether that path meets the constraints of the action's corresponding SpiceDB permission.

Role

A role is a collection of actions that are allowed to be performed on a resource. A role like loadbalancer_readonly might allow the actions loadbalancer_get and loadbalancer_list, for example.

Role assignment

A role assignment is a relationship that binds a subject to a role. This is how a subject is granted access to a resource.

Usage

permissions-api is a Go service. To build it, you can use make build to build a Go binary. Configuration is done using environment variables and/or a YAML config file. An example config is available at permissions-api.example.yaml, and an example environment file is available at .devcontainer/.env.

Generating SpiceDB schema

To generate a SpiceDB schema based on the resource types defined in permissions-api, use the schema command:

$ ./permissions-api schema --dry-run --config permissions-api.example.yaml

Omit the --dry-run flag to apply the schema to your SpiceDB server.

Running a server

To run the permissions-api server, use the server command:

$ ./permissions-api server --config permissions-api.example.yaml

Generating access tokens

permissions-api requests are authenticated using JWT access tokens. If you are using the provided dev container, permissions-api is already configured to accept JWTs from the included mock-oauth2-server service. A UI to manually create access tokens is available at http://localhost:8081/default/debugger. Tokens must be configured with a "scope" value in the UI set to openid permissions-api (which maps to an audience in the JWT of permissions-api) and a Prefixed ID (ex: idntusr-0xqwVtYKHjjuLfjSItHLU).

Creating relationships

Resources are defined in terms of their relationships to other resources using the /relationships API endpoint. Using curl, one can create a relationship tenant between two tenants like so:

$ curl --oauth2-bearer "$AUTH_TOKEN" \
    -d '{"relationships": [{"relation": "tenant", "subject_id": "tnntten-OJrD-JdCFThZiRgqk6vs6"}]}' \
    http://localhost:7602/api/v1/resources/tnntten-MCR3xIIMWfVpVM22w82NZ/relationships

Creating roles

Roles are created using the /roles API endpoint. For example, the following curl command creates a role scoped to a tenant that allows the loadbalancer_create action:

$ curl --oauth2-bearer "$AUTH_TOKEN" \
    -d '{"actions": ["loadbalancer_create"]}' \
    http://localhost:7602/api/v1/resources/tnntten-MCR3xIIMWfVpVM22w82NZ/roles

Assigning roles to subjects

Roles are assigned to subjects using the /assignments API endpoint. The curl command below will assign the subject with the given ID to the given role:

$ curl --oauth2-bearer "$AUTH_TOKEN" \
    -d '{"subject_id": "idntusr-0xqwVtYKHjjuLfjSItHLU"}' \
    http://localhost:7602/api/v1/roles/permrol-XqGKCT8L5CikBuIpbFQEt/assignments

Checking permissions

The /allow API endpoint is used to check whether the authenticated subject in the given bearer token has permission to perform the requested action on the given resource. The following example checks to see whether a subject can perform the loadbalancer_create operation on a tenant:

$ curl --oauth2-bearer "$AUTH_TOKEN" \
    http://localhost:7602/api/v1/allow?action=loadbalancer_create&resource=tnntten-MCR3xIIMWfVpVM22w82NZ

Development

identity-api includes a dev container for facilitating service development. Using the dev container is not required, but provides a consistent environment for all contributors as well as a few perks like:

  • gopls integration out of the box
  • Host SSH auth socket mount
  • Git support
  • Auxiliary services (SpiceDB, CRDB, etc)

To get started, you can use either VS Code or the official CLI.

Manually setting up SSH agent forwarding

The provided dev container listens for SSH connections on port 2222 and bind mounts ~/.ssh/authorized_keys from the host to facilitate SSH. In order to perform Git operations (i.e., committing code in the container), you will need to enable SSH agent forwarding from your machine to the dev container. While VS Code handles this automatically, for other editors you will need to set this up manually.

To do so, update your ~/.ssh/config to support agent forwarding. The following config snippet assumes the existence of a remote host used for development and uses it to make permissions-api reachable at the host permissions-api-devcontainer:

Host permissions-api-devcontainer
  ProxyJump YOUR_HOST_HERE
  Port 2224
  User vscode
  ForwardAgent yes

Host YOUR_HOST_HERE
  User YOUR_USER_HERE
  ForwardAgent yes

See the man page for ssh_config for more information on what these options do.