API Server (Authn/Authz)
Authentication
Component |
Description |
Anonymous Auth |
❌ By default, anonymous auth is enabled- Enabling anonymous access to discovery endpoints could increase the likelihood of leaking information about the software that's running
- It is not reckless to allow anonymous access if using RBAC, which by default permit only limited API access for anonymous users
- Explicitly grant RBAC privileges to
system:anonymous user and system:unauthenticated group ✅ Disable anonymous authentication (restrict API access to known, authenticated users)kube-apiserver ... --anonymous-auth=false --authorization-mode=RBAC (enable RBAC authorization module)
|
Authentication Strategies |
✅ Prefer OpenID Connect or X509 Client Certificate-based auth- Use at least two methods:
- service account tokens for service accounts
- OpenID/x509 for user authentication
|
Authorization
Component |
Description |
Verify roles |
- 🗒️ Check what roles are predefined and available:
$ kubectl get clusterroles - 🗒️ Describe the default cluster role:
$ kubectl describe clusterrole view - 🗒️ Verify granted permissions:
$ kubectl --namespace=coolapp auth can-i --as=system:serviceaccount:coolapp:myappid list pods (yes)$ kubectl --namespace=coolapp auth can-i --as=system:serviceaccount:coolapp:myappid list services (no)
|
RBAC |
❌ By default, auth mode is to always authorize all requests to kube-apiserver- Not recommended:
$ kube-apiserver ... --authorization-mode=AlwaysAllow ✅ Enable RBAC- Recommended:
kube-apiserver ... --authorization-mode=RBAC
|
Default Service Account |
❌ By default, the default service account is automatically mounted in the file system of all containers ✅ Disable auto-mounting of the default service account token- The default service account token can be used to query the Kubernetes API
- Without RBAC, this token can be used to do virtually anything in the cluster
- You can specify
automountServiceAccountToken: false in the PodSpec, or you can patch the default service account so that its credentials are not automatically mounted into pods - Recommended:
$ kubectl patch serviceaccount default -p "automountServiceAccountToken: false" ✅ Use dedicated service accounts- If an application needs access to the API server, create a dedicated service account per application and configure RBAC to be specifically limited to the needs of that application
- If a pod is compromised, the attacker will have access to the service account associated with that pod, and its corresponding permissions
|
Impersonation |
❌ Kubernetes has a feature that allows any user to impersonate any other user on the cluster ✅ Limit who can impersonate and what they can do as impersonated users |
Admission Controls
Component |
Description |
Attaching |
❌ If pods are scheduled with the following, it is possible to escalate via attach/execprivileged: true hostPID: true hostIPC: true ✅ Deny privilege escalation via interactive shells or attaching to privileged containers- There are some cases when you need to run privileged containers to interact with the host, but users can potentially kubectl attach or kubectl exec into those privileged containers
- Recommended:
$ kube-apiserver ... --admission-control=...,DenyEscalatingExec
|
Pull Images |
✅ Always pull images- Kubernetes will cache container images that have been pulled from any registry
- Any cached container images can be re-used by any pod on the cluster, meaning pods could gain unauthorized access to potentially sensitive information
- Forcing Kubernetes to always pull images will require that the credentials needed to pull down images from private registries are provided by each requesting resource
- Recommended:
$ kube-apiserver ... --admission-control=...,AlwaysPullImages
|
Pod Security Policies |
✅ Enable Pod Security Policies- Pod Security Policies are security rules that pods have to abide by in order to be scheduled
- A pod security policy is a cluster-wide resource that allows you to enforce the usage of security contexts. The API server automatically enforces those policies for you, using admission controllers
- If a pod’s specification doesn’t meet the requirements of the pod security policy, it won’t be run
- Note that for pod security policies to take effect, the
PodSecurityPolicy admission plugin must be enabled, and permission must be grated to use that policy for the appropriate users - Recommended:
$ kube-apiserver ... --admission-control=...,PodSecurityPolicy
|
Types of Pod Security Policies
Disallow privileged containers
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
Disallow sharing of the host process ID namespace
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
hostPID: false
Disallow sharing of the host IPC namespace (memory)
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
hostIPC: false
Disallow sharing of the host network stack
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
hostNetwork: false
Whitelist allowable volume types
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
# It's recommended to allow the core volume types.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
# Assume that persistentVolumes set up by the cluster admin are safe to use.
- 'persistentVolumeClaim'
Require containers to run as non-root user
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
runAsUser:
# Require the container to run without root privileges.
rule: 'MustRunAsNonRoot'
supplementalGroups:
rule: 'MustRunAs'
ranges:
# Forbid adding the root group.
- min: 1
max: 65535
Set defaultAllowPrivilegeEscalation to false
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
defaultAllowPrivilegeEscalation: false
Apply selinux, seccomp, or apparmor profiles
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
annotations:
# applying default seccomp and apparmor profiles
seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'
apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'