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.
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.
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
subclaim identifying them as eitheraliceorbob. - A user with the
emailclaimcarl@example.com. - All users with a
groupsclaim containing either thedevopsorkargo-admingroup.
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.
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.
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.
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.
"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:
-
Create one or more namespaces dedicated to this purpose. Typically, just one should suffice.
-
Define
ServiceAccountresources in these namespaces, each annotated appropriately to effect the desired user-to-ServiceAccountmappings.Optionally, use a
ClusterRoleBindingto grant any necessary system-wide permissions to theseServiceAccountresources. -
Configure Kargo to look for
ServiceAccountresources in these designated namespaces, by settingapi.oidc.globalServiceAccounts.namespacesat installation time. For example: