Skip to content

08. Authorization

Kubernetes APIs

An official overview on Kubernets APIs

List of useful APIs

  • /metrics
  • /healthz
  • /version
  • /api (core group)
  • /apis (named group)
  • /logs

Exampal

curl https://[master-node-addr]:6443/apis --key mehrdad.key --cert mehrdad.crt --cacert ca.crt

or setup a porxy via kubectl

kubectl proxy

# in the other shell
curl http://localhost:8001

Authorization

Authorization in Kubernetes means which verbs an authenticated user can do

Authorization Modes

The Kubernetes API server may authorize a request using one of several authorization modes

  • AlwaysAllow
  • AlwaysDeny
  • ABAC (attribute-based access control)
  • RBAC (role-based access control)
  • Node
  • Webhook

Authorization Modes Config Location

switch --authorization-mode in API-Server as a binary or pod depends on your installation method.

Example:

--authorization-mode=Node,RBAC,Webhook

The order of mode placements is important, it will execute sequentially.

+----------+----------+---------+
|   node   |   rbac   | webhook |
+----------+----------+---------+

RBAC

Roll Base Access Control

Note: if you don't specific authorization mode, apiserver consider AlwaysAllow mode.

Role and RoleBinding

  • rbac role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: collector
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["list", "get", "create", "update", "delete"]
  - apiGroups:
      - apps
    resources:
      - deployments
      - replicasets
    verbs:
      - list
      - get
      - create
      - update
      - delete
    resourceName:
      - nginx
  • role-binder
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mehrdad-as-developer
  namespace: collector
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io
subjects:
  - kind: User
    name: mehrdad
    apiGroup: rbac.authorization.k8s.io

Context

switch between contexts via kubectx

ClusterRole

Some of the resources are independent from namespace, such and nodes, namespaces, pv and ect. so we can need to the another role across the entire of cluster. It called ClusterRole.

Also you can get all kubernetes resources via these commands

  • get all kubernetes resources
kubectl api-resources
  • get the resources outside from namespace scope
kubectl api-resources --namespaced=false
  • get the resources inside in namespace scope
kubectl api-resources --namespaced=false
  • cluster role
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: amdins-role
rules:
  - apiGroups:
      - apps
    resources:
      - pods
      - deployments
      - replicasets
      - namespases
      - nodes
      - persistentvolumes
    verbs:
      - list
      - get
      - create
      - update
      - delete
  • cluster role binder
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admins-role-binder
roleRef:
  kind: ClusterRole
  name: admins-role
  apiGroup: rbac.authorization.k8s.io
subjects:
  - kind: User
    name: mehrdad
    apiGroup: rbac.authorization.k8s.io

Note: during the creation of client certificate you can assign a created kubernetes role to Organization Unit, and after the user gives all roles from kubernetes.

  • check the list of available ClusterRole
kubectl get clusterroles

Image Security

image schema structure

assume we have a image link like this: docker.io/mehrdad/nginx:1.7 and k8s.io/kubernetes/kubelet:1.29

repo:    | registry  | account name | image name   |
         -------------------------------------------
image1:  | docker.io | mehrdad      | nginx:1.7    |
image2:  | k8s.io    | kubernetes   | kubeadm:1.29 |

If we want to use a private repository in our cluster, we need to set secret config for authenticate in private registry.

Create Secret

create in dry-run mode and get yaml output

kubectl -n <namespace-name> create secret docker-registry <secret-cluster-name> --docker-username=<username> --docker-password=<password> --dry-run=client -o yaml > docker-secret.yaml
 ```

Check your secret value:

```bash
 echo "<value of .dockerconfigjson key"> | base64 -d | jq .

after check validation run

kubectl apply -f docker-secret.yaml

create pod with private registry address

apiVersion: v1
kind: Pod
metadata:
  name: "pod-private-repo"
  namespace: collector
spec:
  imagePullSecrets:
    - name: prv-reg-secret
  containers:
  - name: pod-private-repo
    image: "private-repo-url"
    command:
    - sleep
    - infinity

Note: imagePullSecrets is the critical key to handle private registry authentication

Security Context

change user-id in pod and container spec and deny to access user root!

apiVersion: apps/v1
kind: Deployment
metadata:
  name: security-context-deployment
  namespace: collector
spec:
  selector:
    matchLabels:
      app: security-context-sample
  replicas: 1
  template:
    metadata:
      labels:
        app: security-context-sample
    spec:
      securityContext:
        runAsUser: 1000 # change user-id
      containers:
        - name: security-context
          image: alpine:3.11.3
          command:
            - sleep
            - infinity
          securityContext:
              runAsUser: 1001 # override pod spec.securityContext.runAsUser
              runAsGroup: 2000
              capabilities:
                  add:
                   - "MAC_ADMIN"
                   - "SYS_ADMIN"

Network Policy

Traffic Direction

  • Ingress: incoming traffic
  • Egress: outgoing traffic
                       +------------+
Ingress: 80     -->    | WebServer  |    -->     Egress: 5000
                       +------------+
Ingress: 5000   -->    | API Server |    -->     Egress: 3306
                       +------------+
Ingress: 3306   -->    |    ETCD    |
                       +------------+

Tips

  • By default:
  • all the Ingress traffic are closed
  • all the Egress traffic are opened

Network Policy Ingress Scenario

we need to a cluster-ip service with it's pod

apiVersion: v1
kind: Service
metadata:
  name: webserver
  namespace: collector
spec:
  type: ClusterIP
  selector:
    app: webserver
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webserver
  namespace: collector
  labels:
    app: webserver
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webserver
  template:
    metadata:
      labels:
        app: webserver
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
          ports:
            - containerPort: 80

we should have pods, "green" and "red" and we want to set a network policy that just green can connect to our webserver

apiVersion: apps/v1
kind: Deployment
metadata:
  name: green/red
  namespace: collector
  labels:
    app: green/red
spec:
  replicas: 1
  selector:
    matchLabels:
      app: green/red
  template:
    metadata:
      labels:
        app: green/red
    spec:
      containers:
        - name: green/red
          image: apline:3.11.3
          command:
            - sleep
            - infinity

go to red and green container and run

curl webserver
curl webserver.collector.services.cluster.local # FQDN

it times to add network policy and apply some rules

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: webserver-netpolicy
  namespace: collector
spec:
  podSelector:
    matchLabels:
      app: webserver
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: green
      ports:
        - protocol: TCP
          port: 80

check again

curl webserver
curl webserver.collector.services.cluster.local # FQDN

Commands

Check verb access to specific resource

kubectl auth can-i <verb-name> <resource-name>

on be half of the other user

kubectl auth can-i <v-name> <res-name> --as <user-name> --namespace <namespace-name>