<

Starting to Learn Kubernetes a Step Behind - 15. Security -

Story

  1. Starting to Learn Kubernetes a Step Behind - 01. Environment Selection -
  2. Starting to Learn Kubernetes a Step Behind - 02. Docker For Mac -
  3. Starting to Learn Kubernetes a Step Behind - 03. Raspberry Pi -
  4. Starting to Learn Kubernetes a Step Behind - 04. kubectl -
  5. Starting to Learn Kubernetes a Step Behind - 05. workloads Part 1 -
  6. Starting to Learn Kubernetes a Step Behind - 06. workloads Part 2 -
  7. Starting to Learn Kubernetes a Step Behind - 07. workloads Part 3 -
  8. Starting to Learn Kubernetes a Step Behind - 08. discovery&LB Part 1 -
  9. Starting to Learn Kubernetes a Step Behind - 09. discovery&LB Part 2 -
  10. Starting to Learn Kubernetes a Step Behind - 10. config&storage Part 1 -
  11. Starting to Learn Kubernetes a Step Behind - 11. config&storage Part 2 -
  12. Starting to Learn Kubernetes a Step Behind - 12. Resource Limitations -
  13. Starting to Learn Kubernetes a Step Behind - 13. Health Checks and Container Lifecycle -
  14. Starting to Learn Kubernetes a Step Behind - 14. Scheduling -
  15. Starting to Learn Kubernetes a Step Behind - 15. Security -
  16. Starting to Learn Kubernetes a Step Behind - 16. Components -

Last time

In Starting to Learn Kubernetes a Step Behind - 14. Scheduling -, we learned about Pod scheduling with Affinity and others. This time, we will learn about security.

Service Account

A service account is said to be an account assigned to control the process to be executed in a Pod.

# sample-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sample-serviceaccount
  namespace: default
imagePullSecrets:
  - name: hogehoge

Let's apply this.

pi@raspi001:~/tmp $ k apply -f sample-serviceaccount.yaml
pi@raspi001:~/tmp $ k get serviceaccounts sample-serviceaccount -o yaml
...
secrets:
- name: sample-serviceaccount-token-4xhgm

The service account has been created. Also, the contents of imagePullSecrets have been registered in secrets. (sample-serviceaccount-token-4xhgm) imagePullSecrets is used for private docker registries.

pi@raspi001:~/tmp $ k get secrets sample-serviceaccount-token-4xhgm -o yaml
apiVersion: v1
data:
  ca.crt: ...
  namespace: ZGVmYXVsdA==
  token: ...
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: sample-serviceaccount
    kubernetes.io/service-account.uid: 4bd076da-8854-11e9-af26-b827eb8ccd80
  creationTimestamp: "2019-06-06T12:12:04Z"
  name: sample-serviceaccount-token-4xhgm
  namespace: default
  resourceVersion: "584634"
  selfLink: /api/v1/namespaces/default/secrets/sample-serviceaccount-token-4xhgm
  uid: 4bfbe8bb-8854-11e9-af26-b827eb8ccd80
type: kubernetes.io/service-account-token

The necessary token for authentication has been registered.

RBAC (Role Based Access Control)

RBAC manages permissions by linking (RoleBinding) the service account created earlier and the Role that defines what operations are allowed. Multiple service accounts can be RoleBound to one Role.

RBAC has two levels, one at the Namespace level and the other at the cluster level. The cluster level has a larger setting range. (set at the cluster level when setting across namespaces)

  • Role and ClusterRole
  • RoleBinding and ClusterRoleBinding

As for the types of operations, there are the following for resources like Deployment or DaemonSet.

*All operations
createCreate
deleteDelete
getGet
listList
updateUpdate
patchPartial change
watchFollow changes

About Kubernetes RBAC

This time, we will proceed with reference to Kubernetes Dojo Day 20 - About Role / RoleBinding / ClusterRole / ClusterRoleBinding.

We will try to retrieve Pod information from the newly created service account by creating a context with it. To do this, you need to pass through the authentication information of the service account.

※ There is no significant difference between Role and ClusterRole, so we will try Role.

pi@raspi001:~/tmp $ TOKEN=$(k get secret/sample-serviceaccount-token-jd279 -o json | jq -r .data.token)
pi@raspi001:~/tmp $ DECODE_TOKEN=$(echo -n $TOKEN | base64 -d)
pi@raspi001:~/tmp $ k config set-credentials sample-serviceaccount --token $DECODE_TOKEN

Now, let's create a context (sample-sa-context) and use it.

pi@raspi001:~/tmp $ k config set-context sample-sa-context --user sample-serviceaccount --cluster kubernetes
pi@raspi001:~/tmp $ k config use-context sample-sa-context
pi@raspi001:~/tmp $ k config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO                NAMESPACE
          kubernetes-admin@kubernetes   kubernetes   kubernetes-admin
*         sample-sa-context             kubernetes   sample-serviceaccount

Let's try to retrieve Pod information with the newly created service account.

pi@raspi001:~/tmp $ k get po
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:sample-serviceaccount" cannot list resource "pods" in API group "" in the namespace "default"

An error occurred. This is because the sample-serviceaccount has no Role bound to it. So, let's do RoleBinding.

Let's go back.

pi@raspi001:~/tmp $ k config use-context kubernetes-admin@kubernetes
# sample-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: sample-role
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
# sample-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: sample-rolebinding
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: sample-role
subjects:
  - kind: ServiceAccount
    name: sample-serviceaccount
    namespace: default
pi@raspi001:~/tmp $ k apply -f sample-role.yaml
pi@raspi001:~/tmp $ k apply -f sample-rolebinding.yaml

Now, let's try again.

pi@raspi001:~/tmp $ k config use-context sample-sa-context
pi@raspi001:~/tmp $ k get po
NAME                                      READY   STATUS    RESTARTS   AGE
...

Oh, it was retrieved! Let's go back.

pi@raspi001:~/tmp $ k config use-context kubernetes-admin@kubernetes

SecurityContext

You can set security settings for containers. For example, you can add or remove Capabilities, change the user and group to run, and make files ReadOnly.

# sample-capabilities.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-capabilities
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
      securityContext:
        capabilities:
          add: ["SYS_ADMIN"]
          drop: ["AUDIT_WRITE"]

Apply it and check the contents.

pi@raspi001:~/tmp $ k apply -f sample-capabilities.yaml
pi@raspi001:~/tmp $ k exec -it sample-capabilities /bin/bash
root@sample-capabilities:/# apt update && apt install libcap2-bin
root@sample-capabilities:/# capsh --print | grep Current
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_sys_admin,cap_mknod,cap_setfcap+eip
root@sample-capabilities:/# exit

cap_sys_admin has increased. audit_write is not found. I didn't know what kind of types there are, so I referred to this.

PodSecurityContext

You can set security settings for Pods (all containers). For example, you can control the user and group to run, deny root execution, and overwrite kernel parameters.

# sample-runuser.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-runuser
spec:
  securityContext:
    runAsUser: 99
    # runAsGroup: 99
    supplementalGroups:
      - 1001
      - 1002
  containers:
    - name: centos-container
      image: centos:7
      command: ["/bin/sleep", "3600"]

Now, apply it.

pi@raspi001:~/tmp $ k apply -f sample-runuser.yaml
pi@raspi001:~/tmp $ k exec -it sample-runuser -- id
uid=99(nobody) gid=99(nobody) groups=99(nobody),1001,1002
pi@raspi001:~/tmp $ k exec -it sample-runuser -- ps aux | grep sleep
nobody       1  0.0  0.0   2032   372 ?        Ss   14:02   0:00 /bin/sleep 3600

The user who executed it has been changed to nobody(99). Also, with supplementalGroups, you can add the specified GID to the primary GID.

Others

There seems to be something called PodSecurityPolicy, NetworkPolicy, and AdmissionControl for authentication and authorization.

Cleaning up

pi@raspi001:~/tmp $ k delete -f sample-serviceaccount.yaml -f sample-role.yaml -f sample-rolebinding.yaml -f sample-capabilities.yaml -f sample-runuser.yaml
pi@raspi001:~/tmp $ k config delete-context sample-sa-context

Finally

We mainly learned about RBAC. When developing with multiple people, it seems good to divide the context and proceed with development. As we tackled this time, with RBAC, you can manage who has what authority, so there will be fewer accidents where more authority than necessary is given. (Although I still don't know because I've only used it personally...) Next time, the end is here.

If it was helpful, support me with a ☕!

Share

Related tags