This page gives you good practices for planning your role-based access control (RBAC) policies. To learn how to implement RBAC in Google Kubernetes Engine (GKE), refer to Configure role-based access control. RBAC is a core security feature in Kubernetes that lets you create fine-grained permissions to manage what actions users and workloads can perform on resources in your clusters. You create RBAC roles and bind those roles to subjects, which are authenticated users such as service accounts or Google Groups.
This page is for Security specialists and Operators who plan and implement RBAC policies for their organization. To learn more about common roles and example tasks that we reference in Google Cloud content, see Common GKE user roles and tasks.
Before reading this page, ensure that you're familiar with the following concepts:
For a checklist of this guidance, see Checklist summary.
How RBAC worksRBAC supports the following types of roles and bindings:
ClusterRole
to a user or a group for all namespaces in the cluster.Role
or a ClusterRole
to a user or a group within a specific namespace.You define permissions as rules
in a Role
or a ClusterRole
. Each rules
field in a role consists of an API group, the API resources within that API group, and the verbs (actions) allowed on those resources. Optionally, you can scope verbs to named instances of API resources by using the resourceNames
field. For an example, see Restrict access to specific resource instances.
After defining a role, you use a RoleBinding
or a ClusterRoleBinding
to bind the role to a subject. Choose the type of binding based on whether you want to grant permissions in a single namespace or in multiple namespaces.
When assigning permissions in an RBAC role, use the principle of least privilege and grant the minimum permissions needed to perform a task. Using the principle of least privilege reduces the potential for privilege escalation if your cluster is compromised, and reduces the likelihood that excessive access results in a security incident.
When designing your roles, carefully consider common privilege escalation risks, such as escalate
or bind
verbs, create
access for PersistentVolumes, or create
access for Certificate Signing Requests. For a list of risks, refer to Kubernetes RBAC - privilege escalation risks.
Kubernetes creates a set of default ClusterRoles and ClusterRoleBindings that you can use for API discovery and to enable managed component functionality. The permissions granted by these default roles might be extensive depending on the role. Kubernetes also has a set of default users and user groups, identified by the system:
prefix. By default, Kubernetes and GKE automatically bind these roles to the default groups and to various subjects. For a full list of the default roles and bindings that Kubernetes creates, refer to Default roles and role bindings.
The following table describes some default roles, users, and groups. We recommend that you avoid interacting with these roles, users, and groups unless you've carefully evaluated them, because interacting with these resources can have unintended consequences to your cluster's security posture.
Name Type Descriptioncluster-admin
ClusterRole Grants a subject permission to do anything on any resource in the cluster. system:anonymous
User
Kubernetes assigns this user to API server requests that have no authentication information provided.
Binding a role to this user gives any unauthenticated user the permissions granted by that role.
system:unauthenticated
Group
Kubernetes assigns this group to API server requests that have no authentication information provided.
Binding a role to this group gives any unauthenticated user the permissions granted by that role.
system:authenticated
Group
GKE assigns this group to API server requests made by any user who is signed in with a Google Account, including all Gmail accounts. In practice, this isn't meaningfully different from system:unauthenticated
because anyone can create a Google Account.
Binding a role to this group gives any user with a Google Account, including all Gmail accounts, the permissions granted by that role.
system:masters
Group
Kubernetes assigns the cluster-admin
ClusterRole to this group by default to enable system functionality.
Adding your own subjects to this group gives those subjects access to do anything to any resource in your cluster.
If possible, avoid creating bindings that involve the default users, roles, and groups. This can have unintended consequences to your cluster's security posture. For example:
cluster-admin
ClusterRole to the system:unauthenticated
group gives any unauthenticated users access to all resources in the cluster (including Secrets). These highly-privileged bindings are actively targeted by attacks such as mass malware campaigns.system:unauthenticated
group gives unauthenticated users the permissions granted by that Role.When possible, use the following guidelines:
system:masters
group.system:unauthenticated
group to any RBAC roles.system:authenticated
group to any RBAC roles.system:anonymous
user to any RBAC roles.cluster-admin
ClusterRole to your own subjects or to any of the default users and groups. If your application requires many permissions, determine the exact permissions required and create a specific role for that purpose.You can use the gcloud CLI to disable non-default RBAC bindings in a cluster that reference the system:unauthenticated
and system:authenticated
groups or the system:anonymous
user. Use one or both of the following flags when you create a new GKE cluster or update an existing cluster. Using these flags doesn't disable the default Kubernetes bindings that reference these groups. These flags require GKE version 1.30.1-gke.1283000 or later.
--no-enable-insecure-binding-system-authenticated
: Disable non-default bindings that reference system:authenticated
.--no-enable-insecure-binding-system-unauthenticated
: Disable non-default bindings that reference system:unauthenticated
and system:anonymous
.cluster-admin
access misconfigurations, GKE clusters running version 1.28 and later won't allow you to bind the cluster-admin
ClusterRole to the system:anonymous
user or to the system:unauthenticated
or system:authenticated
groups.
To check whether your clusters reference these users and groups in RBAC bindings, enable the standard tier of Kubernetes security posture scanning for your clusters or fleet so that GKE can show you results in the security posture dashboard in the Google Cloud console. For instructions, see Enable workload configuration auditing.
The following sections show you how to find the specific RoleBindings or ClusterRoleBindings that reference default users and groups, and how to delete those resources.
ClusterRoleBindingsList the names of any ClusterRoleBindings with the subject system:anonymous
, system:unauthenticated
, or system:authenticated
:
kubectl get clusterrolebindings -o json \
| jq -r '["Name"], ["-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
The output should list only the following ClusterRoleBindings:
Name
----
"system:basic-user"
"system:discovery"
"system:public-info-viewer"
If the output contains additional non-default bindings, do the following for each additional binding. If your output doesn't contain non-default bindings, skip the following steps.
List the permissions of the role associated with the binding:
kubectl get clusterrolebinding CLUSTER_ROLE_BINDING_NAME -o json \
| jq ' .roleRef.name +" " + .roleRef.kind' \
| sed -e 's/"//g' \
| xargs -l bash -c 'kubectl get $1 $0 -o yaml'
Replace CLUSTER_ROLE_BINDING_NAME
with the name of the non-default ClusterRoleBinding.
The output is similar to the following:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
...
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- watch
- list
If you determine that the permissions in the output are safe to grant to the default users or groups, no further action is required. If you determine that the permissions granted by the binding are unsafe, proceed to the next step.
Delete an unsafe binding from your cluster:
kubectl delete clusterrolebinding CLUSTER_ROLE_BINDING_NAME
Replace CLUSTER_ROLE_BINDING_NAME
with the name of the ClusterRoleBinding to delete.
List the namespace and name of any RoleBindings with the subject system:anonymous
, system:unauthenticated
, or system:authenticated
:
kubectl get rolebindings -A -o json \
| jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
If your cluster is configured correctly, the output should be blank. If the output contains any non-default bindings, do the following steps for each additional binding. If your output is blank, skip the following steps.
If you only know the name of the RoleBinding then you can use the following command to find matching rolebindings across all namespaces:
kubectl get rolebindings -A -o json \
| jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(.metadata.name == "ROLE_BINDING_NAME") | [.metadata.namespace, .metadata.name]) | @tsv'
Replace ROLE_BINDING_NAME
with the name of the non-default RoleBinding.
List the permissions of the Role associated with the binding:
kubectl get rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE -o json \
| jq ' .roleRef.name +" " + .roleRef.kind' \
| sed -e 's/"//g' \
| xargs -l bash -c 'kubectl get $1 $0 -o yaml --namespace ROLE_BINDING_NAMESPACE'
Replace the following:
ROLE_BINDING_NAME
: the name of the non-default RoleBinding.ROLE_BINDING_NAMESPACE
: the namespace of the non-default RoleBinding.The output is similar to the following:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
...
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- watch
- list
If you determine that the permissions in the output are safe to grant to the default users or groups, no further action is required. If you determine that the permissions granted by the binding are unsafe, proceed to the next step.
Delete an unsafe binding from your cluster:
kubectl delete rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE
Replace the following:
ROLE_BINDING_NAME
: the name of the RoleBinding to delete.ROLE_BINDING_NAMESPACE
: the namespace of the RoleBinding to delete.Use bindings and roles as follows, depending on the needs of your workload or user:
Role
with a RoleBinding
.ClusterRole
with a RoleBinding
for each namespace.ClusterRole
with a ClusterRoleBinding
.Grant permissions in as few namespaces as possible.
Don't use wildcardsThe *
character is a wildcard that applies to everything. Avoid using wildcards in your rules. Explicitly specify API groups, resources, and verbs in RBAC rules. For example, specifying *
in the verbs
field would grant get
, list
, watch
, patch
, update
, deletecollection
, and delete
permissions on the resources. The following table shows examples of avoiding wildcards in your rules:
- rules: apiGroups: ["apps","extensions"] resources: ["deployments"] verbs: ["get","list","watch"]
Grants get
, list
, and watch
verbs specifically to the apps
and extensions
API groups.
- rules: apiGroups: ["*"] resources: ["deployments"] verbs: ["get","list","watch"]
Grants the verbs to deployments
in any API group.
- rules: apiGroups: ["apps", "extensions"] resources: ["deployments"] verbs: ["get", "list", "watch"]
Grants only get
, list
, and watch
verbs to deployments in the apps
and extensions
API groups.
- rules: apiGroups: ["apps", "extensions"] resources: ["deployments"] verbs: ["*"]
Grants all verbs, including patch
or delete
.
When planning your rules, try the following high-level steps for a more efficient least-privilege rule design in each role:
verbs
list. Combine those rules into a single rule.This approach results in a more organized rule design, where rules that grant the same verbs to multiple resources are combined, and rules that grant different verbs to resources are separate.
For example, if your workload needs get permissions for the deployments
resource, but needs list
and watch
on the daemonsets
resources, you should use separate rules when creating a role. When you bind the RBAC role to your workload, it won't be able to use watch
on deployments
.
As another example, if your workload needs get
and watch
on both the pods
resource and the daemonsets
resource, you can combine those into a single rule, because the workload needs the same verbs on both resources.
In the following table, both rule designs work, but the split rules more granularly restrict resource access based on your needs:
Recommended Not recommended- rules: apiGroups: ["apps"] resources: ["deployments"] verbs: ["get"] - rules: apiGroups: ["apps"] resources: ["daemonsets"] verbs: ["list", "watch"]
Grants get
access for Deployments and watch
and list
access for DaemonSets. Subjects can't list Deployments.
- rules: apiGroups: ["apps"] resources: ["deployments", "daemonsets"] verbs: ["get","list","watch"]
Grants the verbs to both Deployments and DaemonSets. A subject who might not require list
access on deployments
objects would still get that access.
- rules: apiGroups: ["apps"] resources: ["daemonsets", "deployments"] verbs: ["list", "watch"]
Combines two rules because the subject needs the same verbs for both the daemonsets
and deployments
resources.
- rules: apiGroups: ["apps"] resources: ["daemonsets"] verbs: ["list", "watch"] - rules: apiGroups: ["apps"] resources: ["deployments"] verbs: ["list", "watch"]
These split rules would have the same result as the combined rule, but would create unnecessary clutter in your role manifest
Restrict access to specific resource instancesRBAC lets you use the resourceNames
field in your rules to restrict access to a specific named instance of a resource. For example, if you're writing an RBAC role that needs to update
the seccomp-high
ConfigMap and nothing else, you can use resourceNames
to specify only that ConfigMap. Use resourceNames
whenever possible.
resourceNames
for list
and create
verbs. For example, if you're writing a role that needs to list
all ConfigMaps in addition to updating the seccomp-high
ConfigMap, you need to split the rules. Recommended Not recommended
- rules: apiGroups: [""] resources: ["configmaps"] resourceNames: ["seccomp-high"] verbs: ["update"]
Restricts the subject to only update the seccomp-high
ConfigMap. The subject can't update any other ConfigMaps in the namespace.
- rules: apiGroups: [""] resources: ["configmaps"] verbs: ["update"]
The subject can update the seccomp-high
ConfigMap and any other ConfigMap in the namespace.
- rules: apiGroups: [""] resources: ["configmaps"] verbs: ["list"] - rules: apiGroups: [""] resources: ["configmaps"] resourceNames: ["seccomp-high"] verbs: ["update"]
Grants list
access to all ConfigMaps in the namespace, including seccomp-high
. Restricts update
access to only the seccomp-high
ConfigMap. The rules are split because you can't grant list
for named resources.
- rules: apiGroups: [""] resources: ["configmaps"] verbs: ["update", "list"]
Grants update
access for all ConfigMaps, along with list
access.
Do not bind Role
or ClusterRole
resources that have bind
, escalate
, create
, update
, or patch
permissions on the rbac.authorization.k8s.io
API group to service accounts in any namespace. escalate
and bind
in particular can let an attacker bypass the escalation prevention mechanisms built into RBAC.
Create a separate Kubernetes service account for each workload. Bind a least-privilege Role
or ClusterRole
to that service account.
Kubernetes creates a service account named default
in every namespace. The default
service account is automatically assigned to Pods that don't explicitly specify a service account in the manifest. Avoid binding a Role
or ClusterRole
to the default
service account. Kubernetes might assign the default
service account to a Pod that doesn't need the access granted in those roles.
The automountServiceAccountToken
field in the Pod specification tells Kubernetes to inject a credential token for a Kubernetes service account into the Pod. The Pod can use this token to make authenticated requests to the Kubernetes API server. The default value for this field is true
.
In all GKE versions, set automountServiceAccountToken=false
in the Pod specification if your Pods don't need to communicate with the API server.
By default, the kubelet process on the node retrieves a short-lived, automatically rotating service account token for each Pod. The kubelet mounts this token on the Pod as a projected volume unless you set the automountServiceAccountToken
field to false
in the Pod specification. Any calls to the Kubernetes API from the Pod use this token to authenticate to the API server.
If you're manually retrieving service account tokens, avoid using Kubernetes Secrets to store the token. Secret-based service account tokens are legacy credentials that don't expire and aren't rotated automatically. If you need credentials for service accounts, use the TokenRequest
API to obtain short-lived tokens that are automatically rotated.
Review your RBAC roles and access regularly to identify potential escalation pathways and redundant rules. For example, consider a situation where you don't delete a RoleBinding
that binds a Role
with special privileges to a deleted user. If an attacker creates a user account in that namespace with the same name as the deleted user, they'd be bound to that Role
and would inherit the same access. Periodic reviews minimize this risk.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4