Exercise 3: Pod Security Standards

In this exercise, you’ll learn about Pod Security Standards in Kubernetes and how to implement them to enhance the security posture of your AKS cluster. You’ll also explore how to create and manage namespaces with specific security policies.

Task 1: Using Pod Security Standards

Pod Security Standards in Kubernetes help enforce security best practices for your pods. Let’s explore how to use them:

  1. Create a namespace with enforced Pod Security Standards:

    kubectl create namespace restricted-ns
    kubectl label namespace restricted-ns pod-security.kubernetes.io/enforce=restricted
    kubectl create namespace restricted-ns
    kubectl label namespace restricted-ns pod-security.kubernetes.io/enforce=restricted
  2. Try to create a privileged pod in this namespace:

    $privilegedPodYaml = @"
    apiVersion: v1
    kind: Pod
    metadata:
      name: privileged-pod
    spec:
      containers:
      - name: nginx
        image: k8sonazureworkshoppublic.azurecr.io/nginx
        securityContext:
          privileged: true
    "@
    
    $privilegedPodYaml | kubectl apply -f - -n restricted-ns
    cat << EOF | kubectl apply -f - -n restricted-ns
    apiVersion: v1
    kind: Pod
    metadata:
      name: privileged-pod
    spec:
      containers:
      - name: nginx
        image: k8sonazureworkshoppublic.azurecr.io/nginx
        securityContext:
          privileged: true
    EOF

    This should fail because the Pod Security Standard doesn’t allow privileged containers.

  3. Create a pod that complies with the restricted policy. This uses the nginx-unprivilaged image to remove the need for privilage escalation, binds to a non-privilaged port and does not try and write to root-owned directories.

    $compliantPodYaml = @"
    apiVersion: v1
    kind: Pod
    metadata:
      name: compliant-nginx
      namespace: restricted-ns
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: nginx
        image: k8sonazureworkshoppublic.azurecr.io/nginx
        ports:
        - containerPort: 8080
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          runAsNonRoot: true
    "@
    
    $compliantPodYaml | kubectl apply -f - -n restricted-ns
    cat << EOF | kubectl apply -f - -n restricted-ns
    apiVersion: v1
    kind: Pod
    metadata:
      name: compliant-nginx
      namespace: restricted-ns
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: nginx
        image: k8sonazureworkshoppublic.azurecr.io/nginx
        ports:
        - containerPort: 8080
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          runAsNonRoot: true
    EOF
  4. Verify that the compliant pod is running:

    kubectl get pods -n restricted-ns
    kubectl get pods -n restricted-ns
  5. Alternatively, if we did have a requirement to run the privileged version of Nginx, we can remove the restricted policy from the namespace. By default AKS applies the restricted policy to all namespaces, you can see this by running:

    kubectl describe namespace restricted-ns
    kubectl describe namespace restricted-ns

    You should see the pod security labels in the output.

  6. Remove the restricted policy from the namespace:

    kubectl label namespace restricted-ns pod-security.kubernetes.io/enforce-
    kubectl label namespace restricted-ns pod-security.kubernetes.io/enforce-
  7. Now try to create the privileged pod again:

    $privilegedPodYaml = @"
    apiVersion: v1
    kind: Pod
    metadata:
      name: privileged-pod
    spec:
      containers:
      - name: nginx
        image: k8sonazureworkshoppublic.azurecr.io/nginx
        securityContext:
          privileged: true
    "@
    
    $privilegedPodYaml | kubectl apply -f - -n restricted-ns
    cat << EOF | kubectl apply -f - -n restricted-ns
    apiVersion: v1
    kind: Pod
    metadata:
      name: privileged-pod
    spec:
      containers:
      - name: nginx
        image: k8sonazureworkshoppublic.azurecr.io/nginx
        securityContext:
          privileged: true
    EOF
  8. Verify that both pods are now running:

    kubectl get pods -n restricted-ns
    kubectl get pods -n restricted-ns

    You should see both the compliant-nginx and privileged-pod running.

  9. Clean up the namespace:

    kubectl delete namespace restricted-ns
    kubectl delete namespace restricted-ns