Skip to content

Overview

The OpenTestFactory orchestrator uses JWT tokens to ensure proper authorization.

It can generate a unique token at initialization time, but this should not be used in a proper production deployment: if the orchestrator restarts, a new token will be generated and the previous one will no longer be valid.

In the following sections, we explore common usage scenarios, so that you can choose the best identity and access management strategy to implement.

Actors

In the following, a ‘user’ may be a user or a group of users. For example, ‘Carol’ may represent an individual user or a group of users with the ‘QA’ role in the ‘Triangle’ department. Depending on the size of your organization, one may make more sense than the other.

Who Name Role Department
Alice Administrator
Bob Developer Triangle
Carol QA Triangle
Dave Developer Square
Sybil Intern Square

One Place for All

That is the default strategy: all users are equals and have access to all resources. It is suitable for small organizations.

One Private Key

The simplest way to proceed is to create a private key, extract its corresponding public key, generate a set of tokens signed using said private key, and provide the corresponding public key to the orchestrator.

You may want to define an expiration date for some (or all) tokens you generate.

All tokens will have the same rights.

Using this simple scheme, you cannot revoke a given token: you either have to wait until it expires, or you have to generate a new private key, generate new tokens, and update your orchestrator configuration so that it now uses your new public key for validating incoming requests.

Multiple Private Keys

Another simple way to proceed is to create a set of private keys. For example, one per department, or even one per user if the number of users is small.

All tokens still have the same rights, but you can more easily revoke a given token (or at least all tokens signed by a given key) without interfering with other users, by removing the corresponding public key from the list of trusted ones.

It also allows you to delegate the token generation to your users: they provide you with a public key, and they manage their own tokens.

One Place per Department

The One Place for All strategy is not always what suits your use cases best. You may have organizational, application, or security constraints that force you to segregate resources such as execution environments.

One way to achieve that is to deploy multiple orchestrator instances, but this may not be practical, and may not be the most effective use of resources.

The orchestrator offers namespaces, that group resources. An execution environment may be accessible from only one namespace, from some namespaces, or from all namespaces.

You can define a triangle namespace, for use by department Triangle members, and a square namespace, for use by department Square members. Alice, the orchestrator’s administrator, will have access to all namespaces.

For more information on namespaces, see “Namespaces and Permissions.”

One Private Key per Namespace

In this scenario, you will typically generate a set of 3 private keys: an ‘administrator’ key, a ‘triangle’ key, and a ‘square’ key.

In addition to the corresponding public keys, you will have to provide a ‘trusted authorities’ file to the orchestrator. This file defines the namespaces accessible from each public key:

trustedkeys.csv
/etc/opentf/admin.pub,administration public key,,"*"
# we could have used this instead:
# /etc/opentf/admin.pub,administration public key,,"triangle,square"

/etc/opentf/triangle.pub,department triangle public key,,"triangle"
/etc/opentf/square.pub,department square public key,,"square"

The first item is the full path to the public key, as seen by the orchestrator. The second item is a description. The third item is not used in this scenario and can be left blank. The last item is a comma-separated list of namespace names or "*", which means ‘all namespaces’.

You make this file known to the orchestrator by adding it to your deployment and by defining an OPENTF_TRUSTEDKEYS_AUTH_FILE environment variable that refers to its location.

For more information on this file’s format, see “Signature-based Access Control.”

When using Carol’s token (signed by the private key corresponding to triangle.pub), you will only have access to resources (execution environments, workflows, …) in the triangle namespace.

When using Alice’s token (signed by the private key corresponding to admin.pub), you will have access to all resources, in all namespaces.

Multiple Private Keys per Namespace

If that makes sense in your context, you can have multiple keys granting access to the same namespace, or any subset of the namespaces you use.

Tailored Access Control

Namespaces are convenient, but you may want to only allow some of your users to register an agent in a namespace. Or you want a junior member of your team to only have ‘read’ access to some resources, in a given namespace.

The resources commonly used are workflows, agents, and channels (there are more). You can have no access to a given resource, read access to a given resource, or full access to a given resource.

The ‘read access’ rights allow you to list and view resources in a given namespace. The full access’ rights add creation (running, registering) and deletion (killing, deregistering) to that list.

If you want to be able to run a workflow in a given namespace, you have to have full access to the workflow resources in this namespace.

In this scenario, access rights are no longer carried by the key used to sign the token, as they were in the previous scenarios, but by the token itself.

Access grants are explicit: access requests not explicitly granted to a given resource for a given token are rejected.

For more information on tailored access rights, see “Attribute-based Access Control.”

Using Keys, Tokens, and Attributes

This scenario still uses JWT tokens and public keys, as usual, for authentication, but it uses tokens for authorization.

  • You enable this alternate authorization mode by specifying the ABAC (Attribute-based access control) mode. The OPENTF_AUTHORIZATION_MODE environment variable exists for this purpose.

  • You must provide a ‘static token’ file that binds tokens with user IDs and group IDs.

    static_tokens_auth.csv
    ey...,Alice Doe,alice
    ey...,Bob Doe,bob,"department_triangle"
    ey...,Carol Doe,carol,"department_triangle"
    ey...,Dave Doe,dave,"department_square"
    ey...,Sybil Doe,sybil,"department_square_interns"
    

    The first item is the JWT token, the second item is a descriptive name, and the third item is the user ID. The fourth item is optional and is a comma-separated list of group IDs.

    You make this file known to the orchestrator by adding it to your deployment and by defining an OPENTF_TOKEN_AUTH_FILE environment variable that refers to its location.

  • You finally provide a ‘policy’ file that binds user IDs or group IDs to access rights.

    policies.jsonl
    {"apiVersion": "abac.opentestfactory.org/v1alpha1", "kind": "Policy", "spec": {"user": "alice", "namespace": "*", "resource": "*", "apiGroup": "*"}}
    {"apiVersion": "abac.opentestfactory.org/v1alpha1", "kind": "Policy", "spec": {"group": "department_triangle", "namespace": "triangle", "resource": "*", "apiGroup": "*"}}
    {"apiVersion": "abac.opentestfactory.org/v1alpha1", "kind": "Policy", "spec": {"group": "department_square_interns", "namespace": "square", "resource": "workflows", "readonly": true}}
    {"apiVersion": "abac.opentestfactory.org/v1alpha1", "kind": "Policy", "spec": {"group": "department_square", "namespace": "square", "resource": "*"}}
    

    Rules are evaluated in order. If a rule matches the request, access is granted. If no rule matches the request, access is denied.

    You make this file known to the orchestrator by adding it to your deployment and by defining an OPENTF_AUTHORIZATION_POLICY_FILE environment variable that refers to its location.

When using Sybil’s token, you will only be able to list and view workflows in the square namespace.

When using Alice’s token, you will have access to all resources, in all namespaces.

Hybrid Authorization Methods

Having to maintain a list of static tokens for all users may be tedious. You may prefer to restrict administrator’s access rights but leave your departments ‘free reign’ on their namespaces.

In this scenario, you mix token-based authorization and trusted authority-based authorization.

You do so by defining both authorization modes, by specifying the ABAC,JWT mode. The OPENTF_AUTHORIZATION_MODE environment variable is there for this purpose.

You then provide the 3 previously described files, the ‘trusted authorities’ file, the ‘static tokens’ file, and the ‘policy’ file.

The authorization modes are checked in order. If a token is present in the ‘static tokens’ file, its authorizations will be specified by the ‘policy’ file. If a token is not present in the static token file, its accesses will be defined by the trusted authority used to sign it.

Next Steps

The three scenarios presented above are common usage scenarios that can be tailored to your specific needs. Here are some helpful resources for taking your next steps with identity and access management: