Authorization¶
Authorization Mechanisms (Modes)¶
Refer here 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.
Node Authorization¶
Info
The node authorizer only handles node requests.
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)¶
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.
Step 1: Create a Policy File¶
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.
Step 2: Enable ABAC mode¶
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.
--authorization-mode=ABAC
--authorization-policy-file=policy.jsonl
- Remember to mount the policy file through a volume.
Step 3: Create a new user and test¶
You can create a service account and use service account token to create a new user.
Create service account token.
apiVersion: v1
kind: Secret
metadata:
name: alice-token
annotations:
kubernetes.io/service-account.name: alice
type: kubernetes.io/service-account-token
Retrieve the service account token and store the token securely in a file as it is used to authenticate the user.
Setup new user credentials with the token.
Setup new context with the new user.
Verify the permissions of the user.
Role-based Access Control (RBAC)¶
Info
RBAC mainly used to authorize users or service accounts to namespace resources.
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.
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-nameandmy-secret. secret-nameandmy-secretare 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