Understanding Pod Security Admission(PSA)

Sahil
6 min readJan 14, 2024

--

This is a beginner’s guide for understanding PSA and it will provide a brief overview of PSA.

WAIT A MIN !!! What is PSA, I heard about PSP, what the heck is PSA?

Before going into PSP or PSA, let me give a brief overview of k8s security, and why it is required?

Understanding Kubernetes Security

Kubernetes(k8s) is a powerful and popular open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications.

As organisations increasingly embrace Kubernetes for deploying and managing containerized applications, ensuring the security of these clusters becomes a paramount concern. Let’s explore few of the key aspects of k8s security:

  • Authentication and Authorization
  • Network Security
  • Container Security
  • Secrets Management
  • Image Security
  • Audit logging and Monitoring
  • Pod Isolation and Resource Quotas
  • Disaster Recovery and Backup

I will briefly cover about Container Security and Audit logging/Monitoring which is going to be used in this document.

Container Security

  • Security Policies for pods, restricting the capabilities and permissions of containers within pods. This ensures that pod comply to predefined pod security standards.
  • Administrators can set security contexts at both the pod and container levels, which can control aspects such as user privileges, capabilities and SELinux options.

Audit logging/Monitoring

  • Audit logging in k8s can be enabled which captures events and actions within the cluster. Monitoring these logs helps to detect suspicious activities and provides insights into potential security incidents.

Pod Security Policies(PSP) [Deprecated as of Kubernetes v1.21]

Pod Security Policies(PSP) were a feature which has been available from the early days of Kubernetes and was designed to block misconfigured pods from being created on a given cluster. PSP had several limitations and challenges:

Complexity and Rigidity

  • Policies were often static and inflexible, making it challenging to adapt to dynamic application requirements.
  • Lack of support for other resource types and a limited list of controls that don’t cover some container runtime-specific parameters.

Maintenance Overhead

  • Keeping PSP policies up to date and aligned with changing security best practices required significant maintenance efforts.

There are several other factors behind deprecating PSPs, please refer this document for detail explanation.

Replace PodSecurityPolicy with a new built-in admission controller that enforces the Pod Security Standards.

Now, without further ado let’s dive into Pod Security Admission

Pod Security Admission(PSA)

Kubernetes offers a built-in Pod Security admission controller to enforce the Pod Security Standards. Pod security restrictions are applied at the namespace level when pods are created.

Pod Security Admission relies on both Pod Security Standards which defines the different security policies and Pod Admission Modes that define how the security standards are applied for a given namespace.

Pod Security Standards

These are the standards defined which are getting implemented by PSA. And these stands can be updated with every Kubernetes release to include/adapt new security rules.

There are three PSS defined as of now: (Follow this link to read more)

Source: k8s docs

Pod Admission Modes

The cluster admin/namespace admin can configure an admission mode that will be used to do admission validations against workloads being deployed in the namespace. There are three admission modes that can be configured for a namespace:

  • enforce: Policy violations will cause the pod to be rejected.
  • audit: Policy violations will be logged in the audit log, won’t be rejected.
  • warn: Policy violations will cause a user-facing warning, won’t be rejected.

A namespace can configure any or all modes, or even set a different level for different modes.

Hands-On

Pre-requisites

  • K8s cluster v1.22 with –feature-gates=”PodSecurity=true” flag enabled or version greater than v1.25
  • kubectl command cli tool

Step 1: Start kubernetes

Note: Enable audit logging for minikube

minikube stop

mkdir -p ~/.minikube/files/etc/ssl/certs

cat <<EOF > ~/.minikube/files/etc/ssl/certs/audit-policy.yaml
# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
EOF

minikube start \
--extra-config=apiserver.audit-policy-file=/etc/ssl/certs/audit-policy.yaml \
--extra-config=apiserver.audit-log-path=-

Step 2: Enforce Pod Security Admission

As mentioned above, there are three modes through which we can configure the policies.

Policies can be applied in two different ways either via namespace labels or through an AdmissionConfiguration resource. For granularity over namespace selection, we can use namespace labels whereas using AdmissionConfiguration can allow to apply policies with respect to whole cluster.

Applying policies over namespace

# The per-mode level label indicates which policy level to apply for the mode.
#
# MODE must be one of `enforce`, `audit`, or `warn`.
# LEVEL must be one of `privileged`, `baseline`, or `restricted`.
pod-security.kubernetes.io/<MODE>: <LEVEL>

# Optional: per-mode version label that can be used to pin the policy to the
# version that shipped with a given Kubernetes minor version (for example v1.29).
#
# MODE must be one of `enforce`, `audit`, or `warn`.
# VERSION must be a valid Kubernetes minor version, or `latest`.
pod-security.kubernetes.io/<MODE>-version: <VERSION> [OPTIONAL]
Kubectl create ns test-psa
kubectl label --overwrite ns test-psa \
pod-security.kubernetes.io/audit=baseline \
pod-security.kubernetes.io/audit-version=latest \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/warn=baseline \
pod-security.kubernetes.io/warn-version=latest

These standards will allow the test-psa namespace to enforce baseline standards i.e block the future pods and will send a warning to the user if any pod tries to run in case of not meeting the configured policy. It will also generate a audit logs for violations which can be used for monitoring.

NOTE: We can also apply policy in the dry-run mode which can warn us about the violations as per the configured policies for all the namespace without enforcing the policy.

Demonstrate (Deploy Pods)

To demonstrate the behaviour for the applied configuration, lets create a pod that violates the baseline standards as defined in the security standards.

cat <<EOF | kubectl -n test-psa apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
securityContext:
privileged: true
EOF

>
Error from server (Forbidden): error when creating "STDIN":
pods "nginx" is forbidden: violates PodSecurity "baseline:latest": privileged
(container "nginx" must not set securityContext.privileged=true)

Error from server (Forbidden): error when creating “STDIN”: pods “nginx” is forbidden: violates PodSecurity “baseline:latest”: privileged (container “nginx” must not set securityContext.privileged=true)

In the above output, we can see that we receive a warning as the Pod violates the baseline policy and lists how to remediate. The Pod violates the baseline policy which is being enforced and hence is not created.

Audit Logs

If audit logging is enabled for kubernetes cluster, we can see an audit message for baseline policy violations as configured by the namespace labels.

{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "Metadata",
"auditID": "a402da4f-0cd8-4a68-9826-e693e2fdae0a",
"stage": "ResponseComplete",
"requestURI": "/api/v1/namespaces/test-psa/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict",
"verb": "create",
"user": {
"username": "minikube-user",
"groups": [
"system:masters",
"system:authenticated"
]
},
"sourceIPs": [
"192.168.49.1"
],
"userAgent": "kubectl/v1.28.2 (darwin/arm64) kubernetes/89a4ea3",
"objectRef": {
"resource": "pods",
"namespace": "test-psa",
"name": "nginx",
"apiVersion": "v1"
},
"responseStatus": {
"metadata": {},
"status": "Failure",
"message": "pods \"nginx\" is forbidden: violates PodSecurity \"baseline:latest\": privileged (container \"nginx\" must not set securityContext.privileged=true)",
"reason": "Forbidden",
"details": {
"name": "nginx",
"kind": "pods"
},
"code": 403
},
"requestReceivedTimestamp": "2024-01-14T16:09:34.494473Z",
"stageTimestamp": "2024-01-14T16:09:34.496522Z",
"annotations": {
"authorization.k8s.io/decision": "allow",
"authorization.k8s.io/reason": "",
"pod-security.kubernetes.io/audit-violations": "would violate PodSecurity \"baseline:latest\": privileged (container \"nginx\" must not set securityContext.privileged=true)",
"pod-security.kubernetes.io/enforce-policy": "baseline:latest"
}
}

Conclusion

With this, we briefly discussed about Pod Security Admission (PSA) in Kubernetes. By demonstrating a simple scenario, we demonstrated how to easily configure the pod security admission for the pods running in different namespaces.

--

--

Sahil

Software Engineer writing about software and technology.