Skip to content
Browse files

Added final reports

  • Loading branch information...
aasmall committed Aug 6, 2019
1 parent a4ead5f commit a24e8c3c93b2243c09e7cf8636f250a805bc07f2
@@ -29,18 +29,35 @@ Perform a security audit on k8s with a vendor and produce as artifacts a threat
* [Open Community Issues/PRs](

## Request For Proposals

The RFP will be open between 2018/10/29 and 2018/11/30 and has been published [here](
## Published Documents

## Vendor Selection
Trail of Bits and Atredis Partners, in collaboration with the Security Audit Working Group, have released the following documents which
detail their assessment of Kubernetes security posture and their findings.

The [RFP]( is now closed. The working group selected Trail of Atredis, a collaboration between [Trail of Bits]( and [Atredis Partners]( to perform the audit.
### Findings

You can read more about the vendor selection [here](
* [Kubernetes Security Review](findings/Kubernetes%20Final%20Report.pdf)
* [Attacking and Defending Kubernetes Installations](findings/AtredisPartners_Attacking_Kubernetes-v1.0.pdf)
* [Whitepaper](findings/Kubernetes%20White%20Paper.pdf)
* [Threat Model](findings/Kubernetes%20Threat%20Model.pdf)

### Ancillary Data

* [Rapid Risk Assessments](ancillary-data/rapid-risk-assessments)
* [Dataflow](ancillary-data/dataflow)

## Mailing Lists

* Sensitive communications regarding the audit should be sent to the [private variant of the mailing list](!forum/kubernetes-wg-security-audit-private).

## Request For Proposals

The RFP was open between 2018/10/29 and 2018/11/30 and has been published [here](

## Vendor Selection

The [RFP]( is now closed. The working group selected Trail of Atredis, a collaboration between [Trail of Bits]( and [Atredis Partners]( to perform the audit.

You can read more about the vendor selection [here](

@@ -0,0 +1,47 @@
digraph K8S {
subgraph cluster_apiserverinternal {
node [style=filled];
label = "API Server Data Layer";

subgraph cluster_apiserver {
node [style=filled];
label = "API Server";

subgraph cluster_mastercomponents {
node [style=filled];
label = "Master Control Plane Components";

subgraph cluster_worker {
kubelet->kubeapiserver[label="authenticated HTTPS"]
pods[label="pods with various containers"]

subgraph cluster_internet {
authuser[label="Authorized User via kubebctl"]
generaluser[label="General User"]
authuser->kubeapiserver[label="Authenticated HTTPS"]
generaluser->pods[label="application-specific connection protocol"]

Binary file not shown.
@@ -0,0 +1,3 @@
python3 --dfd >
dot -Tpng < > updated-dataflow.png
open updated-dataflow.png
@@ -0,0 +1 @@
@@ -0,0 +1,106 @@
# !/usr/bin/env python3

from pytm.pytm import TM, Server, Datastore, Dataflow, Boundary, Actor, Lambda, Process

tm = TM("Kubernetes Threat Model")
tm.description = "a deep-dive threat model of Kubernetes"

# Boundaries

inet = Boundary("Internet")
mcdata = Boundary("Master Control Data")
apisrv = Boundary("API Server")
mcomps = Boundary("Master Control Components")
worker = Boundary("Worker")
contain = Boundary("Container")

# Actors

miu = Actor("Malicious Internal User")
ia = Actor("Internal Attacker")
ea = Actor("External Actor")
admin = Actor("Administrator")
dev = Actor("Developer")
eu = Actor("End User")

# Server & OS Components

etcd = Datastore("N-ary etcd servers")
apiserver = Server("kube-apiserver")
kubelet = Server("kubelet")
kubeproxy = Server("kube-proxy")
scheduler = Server("kube-scheduler")
controllers = Server("CCM/KCM")
pods = Server("Pods")
iptables = Process("iptables")

# Component <> Boundary Relations
etcd.inBoundary = mcdata
mcdata.inBoundary = apisrv
apiserver.inBoundary = apisrv
kubelet.inBoundary = worker
kubeproxy.inBoundary = worker
pods.inBoundary = contain
scheduler.inBoundary = mcomps
controllers.inBoundary = mcomps
pods.inBoundary = contain
iptables.inBoundary = worker
miu.inBoundary = apisrv
ia.inBoundary = contain
ea.inBoundary = inet
admin.inBoundary = apisrv
dev.inBoundary = inet
eu.inBoundary = inet

# Dataflows

apiserver2etcd = Dataflow(apiserver, etcd, "All kube-apiserver data")
apiserver2etcd.isEncrypted = True
apiserver2etcd.protocol = "HTTPS"

apiserver2kubelet = Dataflow(apiserver, kubelet, "kubelet Health, Status, &amp;c.")
apiserver2kubelet.isEncrypted = False
apiserver2kubelet.protocol = "HTTP"

apiserver2kubeproxy = Dataflow(apiserver, kubeproxy, "kube-proxy Health, Status, &amp;c.")
apiserver2kubeproxy.isEncrypted = False
apiserver2kubeproxy.protocol = "HTTP"

apiserver2scheduler = Dataflow(apiserver, scheduler, "kube-scheduler Health, Status, &amp;c.")
apiserver2scheduler.isEncrypted = False
apiserver2scheduler.protocol = "HTTP"

apiserver2controllers = Dataflow(apiserver, controllers, "{kube, cloud}-controller-manager Health, Status, &amp;c.")
apiserver2controllers.isEncrypted = False
apiserver2controllers.protocol = "HTTP"

kubelet2apiserver = Dataflow(kubelet, apiserver, "HTTP watch for resources on kube-apiserver")
kubelet2apiserver.isEncrypted = True
kubelet2apiserver.protocol = "HTTPS"

kubeproxy2apiserver = Dataflow(kubeproxy, apiserver, "HTTP watch for resources on kube-apiserver")
kubeproxy2apiserver.isEncrypted = True
kubeproxy2apiserver.protocol = "HTTPS"

controllers2apiserver = Dataflow(controllers, apiserver, "HTTP watch for resources on kube-apiserver")
controllers2apiserver.isEncrypted = True
controllers2apiserver.protocol = "HTTPS"

scheduler2apiserver = Dataflow(scheduler, apiserver, "HTTP watch for resources on kube-apiserver")
scheduler2apiserver.isEncrypted = True
scheduler2apiserver.protocol = "HTTPS"

kubelet2iptables = Dataflow(kubelet, iptables, "kubenet update of iptables (... ipvs, &amp;c) to setup Host-level ports")
kubelet2iptables.protocol = "IPC"

kubeproxy2iptables = Dataflow(kubeproxy, iptables, "kube-prxy update of iptables (... ipvs, &amp;c) to setup all pod networking")
kubeproxy2iptables.protocol = "IPC"

kubelet2pods = Dataflow(kubelet, pods, "kubelet to pod/CRI runtime, to spin up pods within a host")
kubelet2pods.protocol = "IPC"

eu2pods = Dataflow(eu, pods, "End-user access of Kubernetes-hosted applications")
ea2pods = Dataflow(ea, pods, "External Attacker attempting to compromise a trust boundary")
ia2cnts = Dataflow(ia, pods, "Internal Attacker with access to a compromised or malicious pod")


0 comments on commit a24e8c3

Please sign in to comment.
You can’t perform that action at this time.