Open mac-chaffee opened 3 years ago
For the node (daemonset) pods, they are privileged, and you can't apply a network policy to them. They have root on the node and access to the host's network namespace. If you wanted to protect them you'd need a host-level firewall which would operate at the level below Kubernetes. Fortunately they don't listen on the network and there is no network attack surface to worry about.
I'm more worried about having a NetworkPolicy to protect the trident controller API. It is protected by client TLS by default, but having a NetworkPolicy would be a nice defense-in-depth layer. Because if the client cert is leaked, someone with access to that API could wreak havoc: https://github.com/NetApp/trident/blob/a86d4ae04a29c66be0c24cf38d805fec27096f4e/frontend/rest/controller_routes.go
Although the fact that the daemonset pods use host networking does complicate the NetworkPolicy, since we'd have to know the node CIDR.
The following NetworkPolicy works in my cluster to restrict other pods from accessing the controller:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-node-ips
spec:
ingress:
# Allow all intra-namespace traffic
- from:
- podSelector: {}
# Allow all traffic from node IPs
- from:
- ipBlock:
cidr: <CIDR that contains all your node IPs>
podSelector:
matchLabels:
app: controller.csi.trident.netapp.io
policyTypes:
- Ingress
(the rule allowing inter-namespace traffic might not even be necessary) So maybe this network policy could be documented somewhere rather than included in the helm chart.
I also noticed that if the host has access to IP addresses/LIFs on the SVM, then user pods also have access. So users could curl <managementLIF>
, or even read/write to arbitrary NFS volumes (even in non-privileged pods if they use a user-space NFS client). This is probably worth a mention in the documentation.
If you're using Calico as your CNI, you can apply the following GlobalNetworkPolicy to only allow pods in the trident
namespace to access LIFs:
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: block-storage-access
spec:
namespaceSelector: "kubernetes.io/metadata.name != 'trident'"
selector: "all()"
types:
- Egress
egress:
- action: Allow
destination:
notNets:
- <managmentLIF>/32
- <dataLIF>/32
- ...
Describe the solution you'd like NetworkPolicies are recommended by the CIS Benchmarks for Kubernetes (login required), as well as NSA/CISA (page 14)
They can restrict other pods from sending traffic to pods in the trident namespace, which I think might be a good secure default.
Describe alternatives you've considered I've tried installing my own networkpolicy separately:
But that doesn't work properly since the DaemonSet pods use host networking, and with the above policy applied, they fail to register themselves:
Even allowing that 34571 port, or 8443, or the whole node subnet don't seem to work. So it seems crafting a good networkpolicy for Trident requires a bit of domain-specific knowledge. So maybe including one in the helm chart (could be disabled by default) would be a good idea.
Additional context Here's an example of another helm chart that ships with a NetworkPolicy: https://github.com/elastic/helm-charts/blob/13c7014a25f2894673f0c272def1422720453f9f/elasticsearch/values.yaml#L283