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:
/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. TheOPENTF_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.csvey...,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:
- “Namespaces and Permissions” for two detailed implementations of the One Place per Department and Tailored Access Control scenarios
- “Authentication” for an in-depth view of authentication
- “Authorization” for an in-depth view of authorization
- “Attribute-based Access Control” for an in-depth view of attribute-based access control