I have contributed to many open source projects including Docker, Go, Kubernetes, Runc, & the Linux kernel. Focus on runtime security for containers. Security in a Containerized World 2
a Containerized World 8 Single tenant, multi-identities Multi-user, but no hard enforcement. Still have to treat as one trust boundary Cooperative soft multi-tenancy Multi-user, fine grained authorization. Possibly not fully-hardened Often good enough for multi-tenancy inside single company (can fire bad actors) Hard multi-tenancy Multi-tenant security boundaries more strongly enforced Better resource isolation E.g. comfortable running code from multiple third-parties on the same cluster Kubernetes 1.6+ Long term goal
a Containerized World 9 Authorization permissions granted at project/cluster level All nodes have same authenticated identity All pods have same authorization permissions All pods have full network access my-project/my-cluster node-1 node-2 node-3 team1-fe team1-fe team1-db team1-db team2-fe team2-fe team2-db team2-db
in a Containerized World 10 my-cluster node-1 node-2 node-3 Authorization permissions granted at namespace/resource level Nodes have individual identities w/ per-node permissions Pods have identity with fine-grained permissions Pods network access can be limited to what’s necessary team1-fe team1-fe team1-db team1-db team2-fe team2-fe team2-db team2-db team1-namespace team2-namespace
in a Containerized World 11 Authorization permissions granted at namespace/resource level Nodes have individual identities w/ per-node permissions Pods have identity with fine-grained permissions Pods network access can be limited to what’s necessary Per-namespace/per-resource permissions Move from: Everything has root-in-cluster. To: Users, system have least privilege. Examples: • Alice can list Eng services, but not HR • Bob can create Pods in Test namespace, not Prod • Scheduler can read Pods but not Secrets
in a Containerized World 12 Authorization permissions granted at namespace/resource level Nodes have individual identities w/ per-node permissions Pods have identity with fine-grained permissions Pods network access can be limited to what’s necessary Per-node identity & permissions Move from: All nodes have vast permissions. To: Each node has least privilege. Examples: • Node can only get info about Pods scheduled on it • Compromised node doesn’t allow additional escalation through Kubernetes API
in a Containerized World 13 Authorization permissions granted at namespace/resource level Nodes have individual identities w/ per-node permissions Pods have identity with fine-grained permissions Pods network access can be limited to what’s necessary Pod identity & permissions Move from: Running workloads have full system access by default. To: Workloads must be granted permissions. Example: • Running workload can list other objects in its namespace, but not outside of it
in a Containerized World 14 Authorization permissions granted at namespace/resource level Nodes have individual identities w/ per-node permissions Pods have identity with fine-grained permissions Pods network access can be limited to what’s necessary Network policy Move From: All workloads receive traffic from anywhere on the network. To: Network connectivity is controllable by policy. Example: • Frontend layer can only communicate with application layer, not other frontends.
with filters. Allows developers to write BPF programs that determine whether a given system call will be allowed or not. Security in a Containerized World 27
BPF? Berkeley Packet Filter In-kernel bytecode machine that is used for tracing, virtual networks, seccomp… and more. Security in a Containerized World 29
and audit various process actions such as file (read, write, execute, etc) and system functions (mount, network tcp, etc) AppArmor Security in a Containerized World 33 AppArmor
is a whitelist which specifies the calls that are allowed. It blocks a bunch of bad stuff… not limited to the following... Security in a Containerized World 38 in Docker
new namespaces. Also gated by CAP_SYS_ADMIN for CLONE_* flags, except CLONE_USERNS, which has a history of vulns Security in a Containerized World 40 in Docker
- Whitelist - Prevent cloning new unprivileged user namespaces (has a high rate of past CVEs) - Prevent ~150 other syscalls which are uncommon or dangerous Security in a Containerized World 41 in Kubernetes apiVersion: v1 kind: Pod metadata: name: hello-nginx annotations: container.seccomp.security.alpha.kuberne tes.io/nginx: docker/default spec: containers: - name: nginx image: nginx command: ["nginx", "-g", "daemon off;"]
access control security policies, including mandatory access controls. Controls over file systems, directories, files, and open file descriptors. Controls individual labels and controls for kernel objects and services. SELinux Security in a Containerized World 42 AppArmor Seccomp SELinux
require that proper labels are placed on volume content mounted into a container. Without a label, the security system might prevent the processes running inside the container from using the content. Allows relabeling file objects on Docker volumes. Security in a Containerized World 43 in Docker
carried over `fork`, `clone`, and `execve` to prevent new privileges from being added to a process. No New Privileges Security in a Containerized World 46 AppArmor Seccomp SELinux No new privs
run as a non-root user ReadOnlyRootFilesystem: Set container filesystem as read-only Security Context Security in a Containerized World 50 in Kubernetes
run as a non-root user ReadOnlyRootFilesystem: Set container filesystem as read-only Capabilities: Set containers to run with specific Capabilities Security Context Security in a Containerized World 51 in Kubernetes
a cluster-level resource that controls the actions that a pod can perform and what it has the ability to access. The PodSecurityPolicy objects define a set of conditions that a pod must run with in order to be accepted into the system. Pod Security Policy Security in a Containerized World 55 in Kubernetes
host ports, defines an allowed range. Default empty. List of HostPortRange, defined by min (inclusive) and max (inclusive), which define the allowed host ports. Security in a Containerized World 61 Pod Security Policy in Kubernetes apiVersion: extensions/v1beta1 kind: PodSecurityPolicy metadata: name: restrictive spec: privileged: false seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny hostPorts: min: 8000 max: 8080 volumes: - '*'
be configured if not using pre-allocated values. Uses seLinuxOptions as the default. Validates against seLinuxOptions. RunAsAny: No default provided. Allows any seLinuxOptions to be specified. Security in a Containerized World 64 Pod Security Policy in Kubernetes apiVersion: extensions/v1beta1 kind: PodSecurityPolicy metadata: name: restrictive spec: privileged: false seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny hostPorts: - min: 8000 max: 8080 volumes: - '*'
to be configured. Uses the first value of the range as the default. Validates against the range. MustRunAsNonRoot: Requires that the pod be submitted with a non-zero runAsUser or have the USER directive defined in the image. RunAsAny: No default provided. Allows any runAsUser to be specified. Security in a Containerized World 65 Pod Security Policy in Kubernetes apiVersion: extensions/v1beta1 kind: PodSecurityPolicy metadata: name: restrictive spec: privileged: false seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: MustRunAsNonRoot fsGroup: rule: RunAsAny hostPorts: - min: 8000 max: 8080 volumes: - '*'
one range to be specified. Uses the minimum value of the first range as the default. Validates against all ranges. RunAsAny: No default provided. Allows any supplementalGroups to be specified. Security in a Containerized World 66 Pod Security Policy in Kubernetes apiVersion: extensions/v1beta1 kind: PodSecurityPolicy metadata: name: restrictive spec: privileged: false seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny hostPorts: - min: 8000 max: 8080 volumes: - '*'
one range to be specified. Uses the minimum value of the first range as the default. Validates against the first ID in the first range. RunAsAny: No default provided. Allows any fsGroup ID to be specified. Security in a Containerized World 67 Pod Security Policy in Kubernetes apiVersion: extensions/v1beta1 kind: PodSecurityPolicy metadata: name: restrictive spec: privileged: false seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny hostPorts: - min: 8000 max: 8080 volumes: - '*'
70 Network Policies my-cluster node-1 node-2 node-3 pod pod pod pod pod pod pod pod team1-namespace team2-namespace Behavior without a network policy. Everything can talk to everything.
71 Network Policies my-cluster node-1 node-2 node-3 pod pod pod pod pod pod pod pod team1-namespace team2-namespace Network Isolation with DefaultDeny Explicitly define communication between pods as a whitelist
72 Network Policies Network Isolation with DefaultDeny Explicitly define communication between pods as a whitelist my-cluster node-1 node-2 node-3 pod pod pod pod pod pod pod pod team1-namespace team2-namespace