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
sub
claim identifying them as eitheralice
orbob
. - A user with the
email
claimcarl@example.com
. - All users with a
groups
claim containing either thedevops
orkargo-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.
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 Secret
s.
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 ServiceAccount
s using ClusterRoleBinding
s. Project admins retain
control over the project-level permissions of those ServiceAccount
s using
RoleBinding
s 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
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 theseServiceAccount
resources. -
Configure Kargo to look for
ServiceAccount
resources in these designated namespaces, by settingapi.oidc.globalServiceAccounts.namespaces
at installation time. For example: