Day 25/#30daysofK8s

Parthvi Vala
4 min readFeb 26, 2021

--

  1. Node Authorization — While creating a certificate, the issue-e(?) states the group and node it belongs to so that whenever it sends a request, the server can authorize it and let it access the node it is supposed to. The same goes for the user. Examples of components that could use node authorization are kubelet, which talks to the kube-apiserver to read from its services, endpoints, nodes, and pods, and also write to it node status, pod status, and events. This kubelet could belong to a system:node:node01 and can only access node01 data.
  2. ABAC — With this type of authorization, a user is given a set of permissions with which it can perform only a certain set of activities. Remember GitHub or Jenkins? Every time you want to create a token, you check a few permissions that the user with the token can access, for e.g read:public-repo, read:user-email, etc. This is the same thing. In terms of K8s, these permissions could be — view pods, create pods, delete pods or any resource for that matter.
    A policy can be defined for this type of authorization.
    {"kind": "Policy", "spec": {"user": "pvala", "resource": "pods", "apigroup": "*", namespace: "*"}}
    {"kind": "Policy", "spec": {"group": "admins", "namespace": "*", "apigroup": "*", "resource": "csr"}}
    To make any change to these security policies, these policy files must be edited manually and the kube-apiserver must be restarted.
    For some reason(?), ABAC is difficult to manage, and hence RBAC.
  3. RBAC — Hardly needs any introduction. Instead of assigning policies to every user, we assign these policies/permissions to a role and then assign the user a role. RBAC is a more standard approach to managing access.
  4. Webhook — This authorization is where we use external agents to handle the authorization. Anytime a user requests something from the kube-apiserver, the server asks the agent to check if the user has correct permissions for their requested thing, and if so, kube-apiserver responds. Open Policy agent is one such example.
  5. AlwaysAllow — Always allow all the requests without any authorization.
  6. AlwaysDeny — Always denies all the requests.

The authorization modes can be set via --authorization-mode flag in the kube-apiserver service. By default, it is set to AlwaysAllow.

Can I specify multiple authorization modes? — Yes! We can provide comma-separated multiple authorization modes. For e.g. --authorization-mode=Node,RBAC,Webhook The authorization is done one by one by all the nodes. For an incoming request from a user, the request will be first authorized by Node, if it denies, RBAC comes into action, if it allows, the request goes through, if not, Webhook takes in charge.

Authorization with RBAC —

  1. Create a role with — kubectl apply-f qe-role.yaml
qe-role.yamlapiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: QE
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list", "get", "create", "update", "delete"]
resourceNames: ["pod-1", "pod-2"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list"]

We can mention resourceNames in case we want the role to only access certain resources.

2. Bind the user with the role with RoleBinding — kubectl create -f qe-role-binding.yaml

qe-role-binding.yamlapiversion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: QE-Role-Binder
namespace: ["default", "myproject"]
subjects:
- kind: User
name: pvala
apiGroup: rbac.authorizaton.k8s.io
roleRef:
kind: Role
name: QE
apiGroup: rbac.authorization.k8s.io

roles and rolebindings are the 2 resources here. Notice singular apiGroup in role-binding yaml and plural apiGroups in role yaml.

Checking access as a user can be done with — kubectl auth can-i <verb> <resource> --as <user> and it replies with a yes or no. Append --namespace flag to check within a namespace.

Fun fact — We can mention both the role and role-binding config in a single yaml file and then do kubectl apply on it, it works like magic.

Namespaced vs. Cluster-scoped —

Nodes cannot be bound to a namespace, they are cluster scoped resources. So resources can be either namespaced or cluster-scoped. Namespace itself is a cluster scoped resource.

Namespaces resources include — pods, replicasets, deployments, roles, roleBindings, services, secrets, PVC, configmaps, jobs

Cluster scoped resources include — nodes, PV, clusterRoles, clusterRoleBindings, CSR, namespaces.

ClusterRoles and ClusterRoleBindings can be defined in the same way as Roles and RoleBindings, with the exception in kind . There is no need to mention the namespace, of course. There is no rule to use ClusterRole and ClusterRB for only cluster-scoped resources, they can be used for namespaced resources too, but then the user will be able to access resources through all the namespaces.

Image security —

Image names are usually written as a single noun, for e.g. nginx . But what it really means is nginx/nginx, where the first nginx points to user or account name and the second nginx points to the image name. By default it works like that. But ideally it can be like — <registry_url>/<account_name>/<image_name>:<version>

If it is a private registry, it is required for us to login or provide credentials to it.

These credentials can be defined in the pod definition file by first creating the secret like —

kubectl create secret docker-registry <secret_name> --docker-server <server> --docker-username <username> --docker-password <pwd> --docker-email <email---
pod-def.yaml
apiVersion: v1
kind: Pod
metadata:
name: some-pod
spec:
containers:
- name: secretnginx-container
image: privateregistry.io/secretorg:secretnginx
imagePullSecrets:
- name: <secret_name>

One can create a total of 3 types of secrets — 1)docker-registry, 2) generic and, 3) tls.

Docker allows defining security contexts. A security context defines setting OS level security settings(SELinux, uid, guid, capabilities, etc.) in a container. for e.g. the user which can run a particular command or linux capabilities that can be added or removed from the container.

docker run --user=1001 ubuntu sleep 100
docker run --cap-add MAC_ADMIN ubuntu

In K8s, these security contexts can be defined at pod level and container level. Container level trumps the pod level setting. Capabilities can only be set at container level.

pod-def.yamlapiVersion: v1
kind: Pod
metadata:
name: some-pod
securityContext:
runAsUser: 1000
spec:
containers:
- image: nginx
name: nginx
securityContext:
runAsUser: 1000
capabilities:
add: ["MAC_ADMIN"]

--

--

No responses yet