Authorization
Authorization Mechanisms (Modes)
Refer here (opens in a new tab) for more details.
In summary;
Mode | Description |
---|---|
AlwaysAllow | Allows all requests without any authorization checks. |
AlwaysDeny | Blocks all requests. |
Node Authorization | A special-purpose authorization mode that authorizes API requests made by kubelets. |
ABAC | It defines an access control paradigm whereby access rights are granted to users through the use of policies that combine attributes together. |
RBAC | It is a method of regulating (control) access to resources in a Kubernetes cluster based on the roles of individual users or service accounts. |
Webhook | A mode that allows you to manage authorization externally. For example, Open Policy Agent (OPA). |
By default, the mode is set to AlwaysAllow
in the kube-apiserver. You can change the mode by setting the --authorization-mode
flag in the kube-apiserver. You can also specify multiple modes by separating them with a comma. When you specify multiple nodes, the kube-apiserver will try to authorize the request with the first mode in the list. If the request is denied, it will try the next mode in the list.
--authorization-mode=RBAC,ABAC,Webhook
Node Authorization
The node authorizer only handles node requests.
Reference (opens in a new tab)
The node authorizer allows a kubelet to perform API operations. All these operations are handled by node authorizer. So, we know that kubelet is part of a system nodes group and have a prefix system:node
. The kubelet will be granted these privileges after the node authorizer has authorized the kubelet so that it can perform the following operations.
Read operations;
- services
- endpoints
- nodes
- pods
- secrets, configmaps, persistent volume claims and persistent volumes related to pods bound to the kubelet's node
Write operations;
- node status
- pod status
- events
Attribute-based Access Control (ABAC)
Reference (opens in a new tab)
ABAC is a method of restricting access to resources based on the attributes of the user. It is a static file that defines the access control policy. The policy file is a set of rules that specify what kind of access is granted to which users.
For example, the following policy file
- allows Alice to create pods and get pods in the default namespace.
- allows Bob to get pods in the prod namespace, but not create pods.
- allows group dev to access all resources in all namespaces.
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": { "user": "alice", "namespace": "default", "resource": "pods", "readonly": false}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "bob", "namespace": "prod", "resource": "pods", "readonly": true}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"group": "dev", "namespace": "*", "resource": "*"}}
- you can specify multiple rules in the policy file.
Once you have the policy file, you will need to enable ABAC in the kube-apiserver by setting the --authorization-mode
flag to ABAC
and the --authorization-policy-file
flag to the path of the policy file. But this method is not recommended, as everytime you need to update the policy file, you need to restart the kube-apiserver.
Role-based Access Control (RBAC)
RBAC mainly used to authorize users or service accounts to namespace resources.
Reference (opens in a new tab)
RBAC is a method of regulating (control) access to resources based on the roles of individual users or service accounts. So we will create and define a role with a set of permissions and then bind the role to a user or service account.
Before we dive into RBAC, we need to understand what resources are under namespace and cluster scope (non-namespaced resources).
# list all resources under namespace
kubectl api-resources --namespaced=true
# this will help you to get the verb
kubectl api-resources --namespaced=true --sort-by name -o wide
Name | API Version | Kind |
---|---|---|
bindings | v1 | Binding |
configmaps | v1 | ConfigMap |
endpoints | v1 | Endpoints |
events | v1 | Event |
limitranges | v1 | LimitRange |
persistentvolumeclaims | v1 | PersistentVolumeClaim |
pods | v1 | Pod |
podtemplates | v1 | PodTemplate |
replicationcontrollers | v1 | ReplicationController |
resourcequotas | v1 | ResourceQuota |
secrets | v1 | Secret |
serviceaccounts | v1 | ServiceAccount |
services | v1 | Service |
controllerrevisions | apps/v1 | ControllerRevision |
daemonsets | apps/v1 | DaemonSet |
deployments | apps/v1 | Deployment |
replicasets | apps/v1 | ReplicaSet |
statefulsets | apps/v1 | StatefulSet |
localsubjectaccessreviews | authorization.k8s.io/v1 | LocalSubjectAccessReview |
horizontalpodautoscalers | autoscaling/v2 | HorizontalPodAutoscaler |
cronjobs | batch/v1 | CronJob |
jobs | batch/v1 | Job |
leases | coordination.k8s.io/v1 | Lease |
endpointslices | discovery.k8s.io/v1 | EndpointSlice |
events | events.k8s.io/v1 | Event |
ingresses | networking.k8s.io/v1 | Ingress |
networkpolicies | networking.k8s.io/v1 | NetworkPolicy |
poddisruptionbudgets | policy/v1 | PodDisruptionBudget |
contourconfigurations | projectcontour.io/v1alpha1 | ContourConfiguration |
contourdeployments | projectcontour.io/v1alpha1 | ContourDeployment |
extensionservices | projectcontour.io/v1alpha1 | ExtensionService |
httpproxies | projectcontour.io/v1 | HTTPProxy |
tlscertificatedelegations | projectcontour.io/v1 | TLSCertificateDelegation |
rolebindings | rbac.authorization.k8s.io/v1 | RoleBinding |
roles | rbac.authorization.k8s.io/v1 | Role |
csistoragecapacities | storage.k8s.io/v1 | CSIStorageCapacity |
Now, from the above table, we can see that roles and rolebindings are under namespace scope, meaning that they are created within a namespace. If you do not specify a namespace, they will be created in the default namespace and control access to resources within that namespace.
Step 1: Create a Role
You can use the following command to get the verb for the resource.
kubectl api-resources --namespaced=true --sort-by name -o wide
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["create", "delete"]
- apiGroups: [""]
resources: ["secrets"] # use * to allow all resources
verbs: ["get"] # use * to allow all verbs
resourceNames: ["secret-name", "my-secret"] # optional
apiGroups
- The API group of the resource. If you are not sure, you can see the above table (API Version).resourceNames
- The names of the resources that the rule applies to. If you do not specify, the rule applies to all resources of the specified type.- In this example, the user can only read the secrets with the name
secret-name
andmy-secret
. secret-name
andmy-secret
are the names of the secrets (metadata name).
- In this example, the user can only read the secrets with the name
# You cannot create a role with different rules, as they will mix it up
kubectl create role developer --verb=get,watch,list --resource=pods
kubectl create role developer --verb=create,delete --resource=deployments.apps # need to append .apps due to apiGroups
kubectl create role developer --verb=get --resource=secrets --resource-name=secret-name --resource-name=my-secret
kubectl get roles
Step 2: Create a RoleBinding
Link the role to a user, group or service account.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-binding
subjects: # users, groups, or service accounts
- kind: User
name: user1 # user name
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: backend-developers # group name
apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
name: my-service-account # service account name
namespace: default # namespace of the service account
- kind: Group
name: system:serviceaccounts:default # all service accounts in the default namespace
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:serviceaccounts # all service accounts in any namespace
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:authenticated # all authenticated users
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:unauthenticated # all unauthenticated users
apiGroup: rbac.authorization.k8s.io
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role # Role or ClusterRole
name: developer # role name
- You can also reference a ClusterRole instead of a role to grant the permissions defined in that ClusterRole to resources inside the RoleBinding's namespace. This kind of reference lets you define a set of common roles across your cluster, then reuse them within multiple namespaces.
kubectl create rolebinding developer-binding --role=developer --user=user1
kubectl create rolebinding developer-binding --role=developer --group=backend-developers
kubectl create rolebinding developer-binding --role=developer --serviceaccount=<namespace>:<service-account-name>
kubectl create rolebinding developer-binding --role=developer --serviceaccount=default:my-service-account
kubectl get rolebinding
Step 3: Verify the access (Optional)
You can check if the user have access to a resource by using the following command.
kubectl auth can-i delete nodes
kubectl auth can-i get pods --as <name-of-the-user>
kubectl auth can-i get pods --as developer
# check if the user can create deployments in the prod namespace
kubectl auth can-i create deployments --as developer --namespace prod
# Check if the group 'developers' can delete nodes
kubectl auth can-i delete nodes --as-group=developers
# Check if the service account 'my-service-account' in the 'default' namespace can get pods
kubectl auth can-i get pods --as=system:serviceaccount:default:my-service-account
# Check if the service account 'my-service-account' in the 'default' namespace can create deployments in the 'prod' namespace
kubectl auth can-i create deployments --as=system:serviceaccount:default:my-service-account --namespace=prod