Skip to main content

Kubernetes with kops for PodSecurityPolicy Lab

Hands-On Lab

 

Photo of

Training Architect

Length

01:00:00

Difficulty

Beginner

This lab guides the student through a step-by-step hands-on example of creating a pod security policy, testing it, and using role bindings to enable it to prevent privileged pods.

What are Hands-On Labs?

Hands-On Labs are scenario-based learning environments where learners can practice without consequences. Don't compromise a system or waste money on expensive downloads. Practice real-world skills without the real-world risk, no assembly required.

Kubernetes with kops for PodSecurityPolicy Lab

Introduction

This lab guides the student through a step-by-step hands-on example of creating a pod security policy, testing it, and using role bindings to enable it to prevent privileged pods.

Solution

Use kops to create the cluster

From the bastion host, use kops to create a cluster:

  1. Use the terminal emulator or SSH to gain access to the 'Bastion Host' Cloud Server server instantiated for the lab.

    ssh cloud_user@[IP Address of Bastion Host]
  2. Once you have access you should be able to do a ls -l and see the k8s-create.sh.

    ls -l
  3. Execute the script to create the cluster configuration files.

    . ./k8s-create.sh

    > Note: Answer any prompts as needed.

  4. Use kops to edit the cluster configuration.

    kops edit cluster
  5. Under the spec: for the cluster, add the following lines.

    spec:
      kubeAPIServer:
        admissionControl:
          - NamespaceLifecycle
          - LimitRanger
          - ServiceAccount
          - PersistentVolumeLabel
          - DefaultStorageClass
          - ResourceQuota
          - PodSecurityPolicy
          - DefaultTolerationSeconds
  6. After editing the cluster configuration to add the admission controller, use kops to update the cluster and create the nodes.

    kops update cluster --name=$KOPS_CLUSTER_NAME --yes

Copy the command at the bottom to connect to the master node using SSH.

  1. After about 5 minutes, run the following command to ensure your cluster is ready:

    kops validate cluster

    Keep running this command every few minutes until you receive the "Your cluster is ready" message.

  2. Once the validation is successful, use the SSH command that was copied from step 6 to connect to the master node.

Create namespace, serviceaccount, and rolebinding

  1. Create the psp-ns namespace.

    kubectl create namespace psp-ns
  2. Create the psp-sa serviceaccount within the psp-ns namespace.

    kubectl create serviceaccount -n psp-ns psp-sa
  3. Create a rolebinding binding the cluster role verb edit to the service account psp-sa.

    kubectl create rolebinding -n psp-ns rb-id --clusterrole=edit --serviceaccount=psp-ns:psp-sa
  4. Now for convenience, create an alias for the psp-admin within the namespace.

    alias psp-admin='kubectl -n psp-ns'
  5. And create an alias for the psp-user within the namespace.

    alias psp-user='kubectl --as=system:serviceaccount:psp-ns:psp-sa -n psp-ns'

Create the Pod Security Policy

  1. Use vi or a Linux editor to create the psp-policy YAML file.

    vi psp-policy.yaml
  2. Make sure the file is as follows.

    apiVersion: policy/v1beta1 
    kind: PodSecurityPolicy 
    metadata:   
      name: psp-policy
    spec:   
      privileged: false  # Don't allow privileged pods!   
      seLinux:     
          rule: RunAsAny   
      supplementalGroups:    
          rule: RunAsAny   
      runAsUser:     
          rule: RunAsAny   
      fsGroup:     
          rule: RunAsAny   
      volumes:   
       - '*'
  3. Then create the policy.

    psp-admin create -f psp-policy.yaml

Create a YAML file to deploy a pod, and attempt to create it

  1. Use an editor to create a YAML file to create a pod.

    vi pod-pause.yaml
  2. Edit the file as follows.

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-pause
    spec:
      containers:
      - name: pause
        image: k8s.gcr.io/pause
  3. Now attempt to create the pod.

    psp-user create -f pod-pause.yaml
  4. To explain the error, you can use 'can-i' to see that the policy is not being used by the service account psp-sa.

    psp-user auth can-i use podsecuritypolicy/psp-policy

Create a rolebinding to allow the psp-sa service account to use the policy and then re-attempt to create the pod

  1. Create a role to use the psp-policy.

    psp-admin create role psp-role --verb=use --resource=podsecuritypolicy --resource-name=psp-policy
  2. Create a rolebinding to bind the role to the serviceaccount.

    psp-admin create rolebinding rb-id2 --role=psp-role --serviceaccount=psp-ns:psp-sa
  3. Retry to create the pod as before.

    psp-user create -f pod-pause.yaml
  4. The pod should deploy. Check with:

    psp-user get pods

Delete the pod from the previous step and attempt to deploy a privileged pod

  1. Delete the pod previously deployed.

    psp-user delete po/pod-pause
  2. Use the editor to create a YAML file for a privileged pod.

    vi priv-pod.yaml
  3. The YAML file should contain the following:

    apiVersion: v1 
    kind: Pod 
    metadata:   
        name: privileged 
    spec:   
        containers:
        - name:  pause
          image: k8s.gcr.io/pause
          securityContext:         
            privileged: true
  4. Now try to create the pod.

    psp-user create -f priv-pod.yaml

    The attempt should fail.

Attempt to use a deployment to create the unprivileged pod

  1. Use an editor to create a YAML file for the deployment.

    vi psp-deploy.yaml
  2. The file contents should be:

    apiVersion: apps/v1 
    kind: Deployment 
    metadata:  
        name: psp-deploy 
          labels: 
            app: paused 
    spec: 
      replicas: 1 
      selector: 
        matchLabels: 
          app: paused 
      template: 
        metadata: 
          labels:  
            app: paused 
        spec: 
          containers: 
          - name: paused 
            image: k8s.gcr.io/pause 
  3. Now attempt to create the deployment.

    psp-user create -f psp-deploy.yaml
  4. See if the pod deployed.

    psp-user get pods

    It should not have deployed.

  5. Check the events to see what happened.

    psp-user get events --sort-by='.metadata.creationTimestamp'

Clean up the failed deployment, add the needed role binding, and re-attempt the deployment

  1. Check if there are any pods running and delete as needed.

    psp-user get pods

    (delete as needed)

    psp-user delete po/[pod name]
  2. Check if the failed deployment exists and delete as needed.

    psp-user get deploy 

    (delete as needed)

    psp-user delete deploy/[deployment name]
  3. Create a role binding linking the role that allows use of the policy with the default service account.

    psp-admin create rolebinding rb-id3 --role=psp-role --serviceaccount=psp-ns:default
  4. Now reattempt to create the deployment as before.

    psp-user create -f psp-deploy.yaml
  5. Check the events to see what happened.

    psp-user get events  --sort-by='.metadata.creationTimestamp'
  6. Check the deployment.

    psp-user get deploy
  7. Check the pod.

    psp-user get pods
  8. Clean up as needed, and experiment with other namespaces and service accounts until this material is comfortable.

Clean up

  1. Show the cluster name:

    kops get clusters
  2. Delete the cluster:

    kops delete cluster CLUSTER_NAME --yes

Conclusion

Congratulations, you've completed this hands-on lab!