Skip to main content

Access Controls

Most access controls in Kargo are within the purview of highly-privileged users -- ones who might be considered to be "project admins." There are only a few access controls that an operator might need to be concerned with and this documentation focuses on those.

note

Not what you were looking for?

If you're a project admin looking to understand more about access controls, you may find some value in this document, but most of what you need to know can be found in the User Guide's Access Controls section.

Overview

Kargo is usually configured to support single-sign-on (SSO) using an identity provider (IDP) that implements the OpenID Connect (OIDC) protocol. This topic is explored in much greater depth in the dedicated OpenID Connect section of the Operator Guide.

Kargo also implements access controls through pure Kubernetes RBAC.

info

Kargo's creators learned from previous experience that when APIs are modeled as Kubernetes resources, it is best to rely solely on Kubernetes-native authorization mechanisms. By doing so, access controls are enforced even for users with direct access to the Kargo control plane's underlying cluster who might shun the Kargo CLI and UI in favor of kubectl.

There is a natural impedance between users authenticating to Kargo through some IDP and access controls being implemented through pure Kubernetes RBAC. To make a finer point of it: It is impossible for a Kubernetes cluster to enforce RBAC for users it does not recognize. Assuming you do not wish to resolve this by granting direct cluster access to a large number of developers and training them to use kubectl, a different solution is required.

Kargo resolves this impedance through a simple scheme that permits users authenticated via the IDP to be mapped to Kubernetes ServiceAccount resources. For the most part, these mappings are best managed at the project level by project admins. The remainder of this document, therefore, touches on the few access controls that an operator might need to be concerned with.

User to ServiceAccount Mappings

First, operators should understand how the mapping of users to ServiceAccount resources works.

Most Kargo users interact with Kargo via its API server, using its UI or CLI as a client. In either case, those users are authenticated by a bearer token issued by the IDP.

For every request, the Kargo API server validates and decodes the token to obtain trusted information about the user which, importantly, includes claims such as username, email address, and group membership. The exact claims available depend on the IDP and the configuration of the Kargo API server. For more details on this topic, refer to the OpenID Connect section of the Operator Guide.

Also for every request, the Kargo API server queries the Kubernetes API server to obtain a list of all ServiceAccount resources to which the user has been mapped. This search is mostly limited to ServiceAccount resources in Kargo project namespaces only (i.e. only those labeled with kargo.akuity.io/project: "true"). This section focuses on the exceptions to that rule.

ServiceAccount resources may be mapped to users through the use of annotations whose key begins with rbac.kargo.akuity.io/claim.. The value of the annotation may be a single value, or a comma-delimited list of values.

In the following example, the ServiceAccount resource is mapped to all of:

  • Users with a sub claim identifying them as either alice or bob.
  • A user with the email claim carl@example.com.
  • All users with a groups claim containing either the devops or kargo-admin group.
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kargo-demo
annotations:
rbac.kargo.akuity.io/claim.sub: alice,bob
rbac.kargo.akuity.io/claim.email: carl@example.com
rbac.kargo.akuity.io/claim.groups: devops,kargo-admin

A user may be mapped to multiple ServiceAccount resources. A user's effective permissions are therefore the union of the permissions associated with all such ServiceAccount resources.

Global Mappings

Now that we've seen how users are mapped to ServiceAccount resources, we can zero in on the few places where these details are relevant to the operator role.

As previously mentioned, most access controls are managed at the project level by project admins, however, there are two ways in which an operator can also map users to ServiceAccount resources.

api.oidc.admins / api.oidc.viewers

The api.oidc.admins and api.oidc.viewers configuration options of the Kargo Helm chart permit an operator to map users with specific claims to system-wide admin and viewer roles respectively. If, for example, every user in the group devops should be an admin, and every user in the group developers should be a viewer, you would set these accordingly:

api:
oidc:
# ... omitted for brevity ...
admins:
claims:
groups:
- devops
viewer:
claims:
groups:
- developers

Behind the scenes, the configuration above merely results in the kargo-admin and kargo-viewer ServiceAccounts in the namespace in which Kargo is installed being annotated as discussed in the previous section.

kargo-admin:

apiVersion: v1
kind: ServiceAccount
metadata:
name: kargo-admin
namespace: kargo
annotations:
rbac.kargo.akuity.io/claim.groups: devops

kargo-viewer:

apiVersion: v1
kind: ServiceAccount
metadata:
name: kargo-viewer
namespace: kargo
annotations:
rbac.kargo.akuity.io/claim.groups: developers

ClusterRoleBinding resources associating these ServiceAccount resources with the correct permissions are pre-defined by the chart.

note

It is common to map all authenticated users to the kargo-viewer ServiceAccount to effect broad read-only permissions. These permissions do not extend to credentials and other project Secrets.

info

For additional information, once again, refer to the OpenID Connect section of the Operator Guide.

Global ServiceAccount Namespaces

In some cases, an operator, in collaboration with project admins, may wish to create a small number of ServiceAccount resources that are pre-mapped to users with specific claims. Operators can assign system-wide permissions to such ServiceAccounts using ClusterRoleBindings. Project admins retain control over the project-level permissions of those ServiceAccounts using RoleBindings in the project namespaces.

info

The main convenience of this approach is that it enables individual project admins to take the existence of certain classes of user for granted instead of having to manage user-to-ServiceAccount mappings themselves.

info

"Global" is a misnomer. ServiceAccount resources in designated namespaces are not truly global because they are still mapped to users according to the rules described in the previous sections.

Enabling global ServiceAccount namespaces requires three steps be taken by the operator:

  1. Create one or more namespaces dedicated to this purpose. Typically, just one should suffice.

  2. Define ServiceAccount resources in these namespaces, each annotated appropriately to effect the desired user-to-ServiceAccount mappings.

    Optionally, use a ClusterRoleBinding to grant any necessary system-wide permissions to these ServiceAccount resources.

  3. Configure Kargo to look for ServiceAccount resources in these designated namespaces, by setting api.oidc.globalServiceAccounts.namespaces at installation time. For example: