Skip to content

Commit 0ec3da6

Browse files
mikedaneseliggitt
authored andcommitted
design: reduce scope of node on node object
1 parent 44ffd48 commit 0ec3da6

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Limiting Node Scope on the Node object
2+
3+
### Author: Mike Danese, (@mikedanese)
4+
5+
## Background
6+
7+
Today the node client has total authority over its own Node object. This ability
8+
is incredibly useful for the node auto-registration flow. Some examples of
9+
fields the kubelet self-reports in the early node object are:
10+
11+
1. Labels (provided by kubelet commandline)
12+
1. Taints (provided by kubelet commandline)
13+
14+
As well as others.
15+
16+
## Problem
17+
18+
While this distributed method of registration is convenient and expedient, it
19+
has two problems that a centralized approach would not have. Minorly, it makes
20+
management difficult. Instead of configuring labels and taints in a centralized
21+
place, we must configure `N` kubelet command lines. More significantly, the
22+
approach greatly compromises security. Below are two straightforward escalations
23+
on an initially compromised node that exhibit the attack vector.
24+
25+
### Capturing Dedicated Workloads
26+
27+
Suppose company `foo` needs to run an application that deals with PII on
28+
dedicated nodes to comply with government regulation. A common mechanism for
29+
implementing dedicated nodes in Kubernetes today is to set a label or taint
30+
(e.g. `foo/dedicated=customer-info-app`) on the node and to select these
31+
dedicated nodes in the workload controller running `customer-info-app`.
32+
33+
Since the nodes self reports labels upon registration, an intruder can easily
34+
register a compromised node with label `foo/dedicated=customer-info-app`. The
35+
scheduler will then bind `customer-info-app` to the compromised node potentially
36+
giving the intruder easy access to the PII.
37+
38+
This attack also extends to secrets. Suppose company `foo` runs their outward
39+
facing nginx on dedicated nodes to reduce exposure to the company's publicly
40+
trusted server certificates. They use the secret mechanism to distribute the
41+
serving certificate key. An intruder captures the dedicated nginx workload in
42+
the same way and can now use the node certificate to read the company's serving
43+
certificate key.
44+
45+
## Proposed Solution
46+
47+
In many environments, we can improve the situation by centralizing reporting of
48+
sensitive node attributes to a more trusted source and disallowing reporting of
49+
these attributes from the kubelet.
50+
51+
### Label And Taint Restriction
52+
53+
An operator will configure a whitelist of taints and labels that nodes are
54+
allowed to set on themselves. This list should include the taints and labels
55+
that the kubelet is already setting on itself.
56+
57+
Well known taint keys:
58+
```
59+
node.cloudprovider.kubernetes.io/uninitialized
60+
```
61+
62+
Well known label keys:
63+
64+
```
65+
kubernetes.io/hostname
66+
failure-domain.beta.kubernetes.io/zone
67+
failure-domain.beta.kubernetes.io/region
68+
beta.kubernetes.io/instance-type
69+
beta.kubernetes.io/os
70+
beta.kubernetes.io/arch
71+
```
72+
73+
As well as any taints and labels that the operator is setting using:
74+
75+
```
76+
--register-with-taints
77+
--node-labels
78+
```
79+
80+
This whitelist is passed as a command line flag to the apiserver.
81+
NodeRestriction admission control will then prevent setting and modification by
82+
nodes of all taints and labels with keys not in the whitelist.
83+
84+
### NodeRestriction Config
85+
86+
A new configuration API group will be created for the NodeRestriction admission
87+
controller with the name `noderestriction.admission.k8s.io`. It will contain one
88+
config object:
89+
90+
```golang
91+
type Configuration struct {
92+
// AllowedLabels is a list of label keys a node is allowed to set on itself.
93+
// The list also supports whitelisting all label keys with a specific prefix
94+
// by adding an entry of the form `<prefix>*`.
95+
AllowedLabels []string
96+
// AllowedTaints is a list of taint keys a node is allowed to set on itself.
97+
// The list also supports whitelisting all taint keys with a specific prefix
98+
// by adding an entry of the form `<prefix>*`.
99+
AllowedTaints []string
100+
}
101+
```
102+
103+
Labels and taints that are applied by the kubelet itself (and not by
104+
--register-with configurations) do not need to appear in this config. They are
105+
allowed implicitly.
106+
107+
### NodeRestriction Config Examples
108+
109+
A configuration that allows all labels and all taints with prefix `insecure.`
110+
and the `foo` taint:
111+
112+
```yaml
113+
apiVersion: noderestriction.admission.k8s.io/v1
114+
kind: Configuration
115+
allowedLabels:
116+
- *
117+
allowedTaints:
118+
- foo
119+
- insecure.*
120+
```
121+
122+
A configuration that allows only labels for CSI plugins:
123+
124+
```yaml
125+
apiVersion: noderestriction.admission.k8s.io/v1
126+
kind: Configuration
127+
allowedLabels:
128+
- csi.kubernetes.io.*
129+
```
130+
131+
For backwards compatibility, the default config is equivalent to:
132+
133+
```yaml
134+
apiVersion: noderestriction.admission.k8s.io/v1
135+
kind: Configuration
136+
allowedLabels:
137+
- *
138+
allowedTaints:
139+
- *
140+
```
141+
142+
### Removing self-delete from Node Permission
143+
144+
Currently a node has permission to delete itself. A node will only delete itself
145+
when it's external name (inferred through the cloud provider) changes. This code
146+
path will never be executated on the majority of cloud providers and this
147+
capability undermines the usage of taints as a strong exclusion primitive.
148+
149+
For example, suppose an operator sets a taint `compromised` on a node that they
150+
believe has been compromised. Currently, the compromised node could delete and
151+
recreate itself thereby removing the `compromised` taint.
152+
153+
To prevent this, we will finish the removal of ExternalID which has been
154+
deprecated since 1.1. This will allow us to remove the self delete permission
155+
from the NodeAuthorizer.
156+
157+
### Taints set by central controllers
158+
159+
In many deployment environments, the sensitive attributes of a Node object
160+
discussed above ("labels", "taints") are discoverable by consulting a machine
161+
database (e.g. the GCE API). A centralized controller can register an
162+
initializer for the node object and build the sensitive fields by consulting the
163+
machine database. The `cloud-controller-manager` is an obvious candidate to
164+
house such a controller.

0 commit comments

Comments
 (0)