kube-policy-advisor is a tool that makes it easier to create K8s Pod Security Policies (PSPs) or OPA Policy from either a live K8s environment or from a single .yaml file containing a pod specification (Deployment, DaemonSet, Pod, etc).
It has 2 subcommands, kube-policy-advisor inspect
and kube-policy-advisor convert
. inspect
connects to a K8s API server, scans the security context of workloads in a given namespace or the entire cluster, and generates a PSP or an OPA Policy based on the security context. convert
works without connecting to an API Server, reading a single .yaml file containing a object with a pod spec and generating a PSP or OPA Policy based on the file.
Follow the instructions to install krew
. Then run the following command:
kubectl krew install advise-policy
The plugin will be available as kubectl advise-policy
.
make build
./kube-policy-advisor inspect
to generate OPA Policy based on running cluster configuration. OPA is the default output.- 2.1
./kube-policy-advisor inspect --namespace=<ns>
to print report or OPA Policy within a given namespace (default to all) - 2.2
./kube-policy-advisor inspect --deny-by-default
to generate an OPA Policy, where OPA Default Rule is Deny ALL - 2.3
./kube-policy-advisor inspect --policy psp
to generate PSP based on running cluster configuration - 2.4
./kube-policy-advisor inspect --policy psp --report
to print the details reports (why this PSP is recommended for the cluster) - 2.5
./kube-policy-advisor inspect --policy psp --grant
to print PSPs, roles and rolebindings for service accounts (refer to psp-grant.yaml)
- 2.1
./kube-policy-advisor convert --podFile <path> --pspFile <path>
to generate a OPA Policy from a single .yaml file.- 4.1
./kube-policy-advisor convert --podFile <path> --policy <path> --deny-by-default
to generate an OPA Policy from a single .yaml file, where OPA Default Rule is Deny ALL. - 4.2
./kube-policy-advisor convert --policy psp --podFile <path> --policyFile <path>
to generate PSP from a single .yaml file.
- 4.1
docker build -t <Image Name> -f container/Dockerfile .
docker run -v ~/.kube:/root/.kube -v ~/.aws:/root/.aws <Image Name>
(the.aws
folder mount is optional and totally depends on your clould provider)
- Help verify the deployment, daemonset settings in cluster and plan to reduce unnecessary privileges/resources
- Apply Pod Security Policy to the target cluster
- Apply OPA Policy to the target cluster
- flag
--namespace=<namespace>
is introduced to debug and narrow down the security context per namespace
- allowPrivilegeEscalation
- allowedCapabilities
- allowedHostPaths
- readOnly
- hostIPC
- hostNetwork
- hostPID
- privileged
- readOnlyRootFilesystem
- runAsUser
- runAsGroup
- Volume
- hostPorts
- allowedUnsafeSysctls
Some attributes(e.g. capabilities) required gathering runtime information in order to provide the followings:
- Least privilege (capabilities captured from runtime)
- Basic functionalities;
- Create PSP's for common charts
- Kubectl plugin
- Generate OPA policies
Command: ./kube-policy-advisor inspect --namespace=psp-test
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
creationTimestamp: null
name: pod-security-policy-20181130114734
spec:
allowedCapabilities:
- SYS_ADMIN
- NET_ADMIN
allowedHostPaths:
- pathPrefix: /bin
- pathPrefix: /tmp
- pathPrefix: /usr/sbin
- pathPrefix: /usr/bin
fsGroup:
rule: RunAsAny
hostIPC: false
hostNetwork: false
hostPID: false
privileged: true
runAsUser:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- hostPath
- configMap
- secret
Command: ./kube-policy-advisor inspect --namespace=psp-test --report | jq .podSecuritySpecs
{
"hostIPC": [
{
"metadata": {
"name": "busy-rs",
"kind": "ReplicaSet"
},
"namespace": "psp-test",
"hostPID": true,
"hostNetwork": true,
"hostIPC": true,
"volumeTypes": [
"configMap"
]
},
{
"metadata": {
"name": "busy-job",
"kind": "Job"
},
"namespace": "psp-test",
"hostIPC": true,
"volumeTypes": [
"hostPath"
],
"mountedHostPath": [
"/usr/bin"
]
}
],
"hostNetwork": [
{
"metadata": {
"name": "busy-rs",
"kind": "ReplicaSet"
},
"namespace": "psp-test",
"hostPID": true,
"hostNetwork": true,
"hostIPC": true,
"volumeTypes": [
"configMap"
]
},
{
"metadata": {
"name": "busy-pod",
"kind": "Pod"
},
"namespace": "psp-test",
"hostNetwork": true,
"volumeTypes": [
"hostPath",
"secret"
],
"mountedHostPath": [
"/usr/bin"
]
}
],
"hostPID": [
{
"metadata": {
"name": "busy-deploy",
"kind": "Deployment"
},
"namespace": "psp-test",
"hostPID": true,
"volumeTypes": [
"hostPath"
],
"mountedHostPath": [
"/tmp"
]
},
{
"metadata": {
"name": "busy-rs",
"kind": "ReplicaSet"
},
"namespace": "psp-test",
"hostPID": true,
"hostMetwork": true,
"hostIPC": true,
"volumeTypes": [
"configMap"
]
}
]
}
Generating PSPs based on runtime activity, simulating PSPs and managing different PSPs across Kubernetes namespaces can simplify the life of every Kubernetes operator. Check out how Sysdig Secure can help - https://sysdig.com/blog/psp-in-production/