Gitea #143, maintainer's instruction. The HBONE port and the redirected probe source are ISTIO CONSTANTS, not standards, so they move from template literals into values with documented defaults - an operator can then correct them when Istio changes a number, without waiting for a chart release. One object under one "enabled", so the two halves still cannot be set separately; two values could drift apart, which is what this design exists to prevent. Every read is null-safe (#99), so a deleted object or one carrying only "enabled: true" falls back to the defaults declared here rather than dereferencing nil - the defect #136 shipped one value away. Provenance now written on each constant: 15008 is Istio's HBONE port, not IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local (RFC 3927, never routed), its IPv6 counterpart carries the same digits plus 1337, and neither the NetworkPolicy API nor the kubelet knows the address - only Istio's data plane rewrites the probe source onto it. Both read for ztunnel 1.30.6, and a change in either fails silently. The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that test names, and additionally asserts this chart declares the same defaults - never "whatever the value says", which would let a mistyped port in through a configurable field. No version change: nothing is published yet, the default is still off, and the render at defaults is byte-identical - re-diffed against origin/main. No redirectedProbeSources here, in neither values.yaml nor the schema: this chart offers no networkPolicy.probeSources, so its probe rule is never source-restricted and no ipBlock is ever rendered. The key would reach no rule and read as a control that does nothing, which is worse than one that is absent. ci/run-networkpolicy-test.sh asserts that absence rather than tolerating it.
172 lines
8.5 KiB
YAML
172 lines
8.5 KiB
YAML
{{- /*
|
|
NetworkPolicy for samba (Gitea #5).
|
|
|
|
Samba publishes both of its ports as NodePorts and the clients are machines on
|
|
the LAN, so both inbound rules are deliberately open: after NodePort
|
|
masquerading the source address is a cluster node anyway, and a source selector
|
|
could only ever be a list of node IPs - a restriction in appearance and a
|
|
maintenance trap in fact. 445 is additionally the port the probes address.
|
|
|
|
THE NUMBERS HERE ARE 445 AND 139, NOT samba.smbNodePort AND
|
|
samba.netbiosNodePort. That distinction is this chart's easiest mistake, which
|
|
is why it is spelled out: a NetworkPolicy is evaluated at the pod's interface
|
|
after kube-proxy has translated the NodePort, so writing 30445 would match
|
|
nothing while looking strict - and, being the only rule for the port, would
|
|
block every SMB client instead.
|
|
|
|
Egress is DNS only, which is as tight as a file server gets. Note what that
|
|
does NOT cover and why it does not matter: the NetBIOS name-service broadcasts
|
|
on 137 and 138/UDP are not published by this chart's Service at all, and
|
|
Windows clients here reach the share by address rather than by browse list.
|
|
|
|
WHAT THIS OBJECT IS: a ceiling on reachability, not an authentication layer.
|
|
Only the ports declared below are reachable at all - whatever else the process
|
|
binds, now or after the next app update, is blocked without anyone having to
|
|
notice it exists.
|
|
|
|
WHAT IT IS NOT:
|
|
- EGRESS IS COARSE. A NetworkPolicy matches CIDRs and selectors and NEVER
|
|
hostnames, so "only to the database host" cannot be expressed at all. This
|
|
cluster's CNI is Canal (Flannel plus Calico for policy) and has no FQDN
|
|
rule; Calico's GlobalNetworkSet could express one but would bind this chart
|
|
to Calico, the same argument that kept implementation-specific objects out
|
|
of the Gateway-API sweep (#114). Each egress rule therefore permits its
|
|
PORT to any destination.
|
|
- NOT A BOUNDARY WHERE THE CNI DOES NOT ENFORCE ONE. An unenforced policy is
|
|
accepted by the API server and filters nothing, so everything reads as
|
|
configured while nothing is filtered.
|
|
- THE REASONING IS IN TEMPLATE COMMENTS, not in "#" comments: those are part
|
|
of the rendered object, travel into the cluster and appear in every release
|
|
diff. ci/run-networkpolicy-test.sh fails on a rendered "#".
|
|
|
|
THE PORT NUMBERS BELOW ARE POD PORTS, NEVER NODEPORTS. A NetworkPolicy is
|
|
evaluated at the pod's network interface, after kube-proxy has already
|
|
translated a NodePort to the targetPort, so a NodePort number here would match
|
|
nothing while looking strict - and, being the only rule for that port, would
|
|
block every inbound connection instead. ci/run-networkpolicy-test.sh asserts
|
|
every port here against the containerPorts of the pod spec this policy
|
|
selects.
|
|
*/ -}}
|
|
{{- if .Values.networkPolicy.enabled }}
|
|
{{- $np := .Values.networkPolicy }}
|
|
{{- /* networkPolicy.ingress - the policy's INBOUND side, and not the same
|
|
thing as the top-level .Values.ingress (the Ingress object) - both match
|
|
a search for "ingress". */}}
|
|
{{- $npIngress := $np.ingress | default dict }}
|
|
{{- /* NULL-SAFE ON PURPOSE (#99): ambientMesh is an OBJECT, so every read goes
|
|
through a fallback reproducing THIS chart's declared defaults. An
|
|
operator who deletes the object, or writes only "enabled: true", must
|
|
land on the defaults and not in a nil dereference - #136 shipped exactly
|
|
that defect one value away, where the NOTES.txt branch dereferenced
|
|
.networkPolicy.egress directly. */}}
|
|
{{- $ambient := $npIngress.ambientMesh | default dict }}
|
|
{{- $ambientEnabled := $ambient.enabled }}
|
|
{{- $ambientPort := $ambient.port | default 15008 }}
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: NetworkPolicy
|
|
metadata:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-networkpolicy
|
|
labels:
|
|
app: {{ .Release.Name }}-{{ .Chart.Name }}-networkpolicy
|
|
spec:
|
|
{{- /*
|
|
Selects the StatefulSet's pods. ci/run-networkpolicy-test.sh fails if
|
|
this matches no pod spec of the same render - which is the mistake that
|
|
would otherwise leave a policy in the namespace filtering nothing, and
|
|
its usual cause is a label renamed in the workload template.
|
|
*/}}
|
|
podSelector:
|
|
matchLabels:
|
|
app: {{ .Release.Name }}-{{ .Chart.Name }}-sfs
|
|
policyTypes:
|
|
- Ingress
|
|
{{- /*
|
|
Egress is listed because the restriction is nearly total and therefore worth
|
|
having: a standalone file server needs name resolution and nothing else. A
|
|
domain-joined one would need Kerberos and LDAP, which is what extraPorts is
|
|
for.
|
|
*/}}
|
|
- Egress
|
|
ingress:
|
|
{{- /*
|
|
SMB (445) and NetBIOS session service (139), both POD ports, both published as
|
|
NodePorts (samba.smbNodePort and samba.netbiosNodePort) and both deliberately
|
|
open: the clients are machines on the LAN, and after masquerading the source is
|
|
a cluster node. 445 is also the port all three probes open a TCP socket
|
|
against, so it is the probe path as well - justified twice over.
|
|
|
|
Writing the NodePort numbers here instead would match nothing and block every
|
|
client. See the header.
|
|
*/}}
|
|
- ports:
|
|
- protocol: TCP
|
|
port: 445
|
|
- protocol: TCP
|
|
port: 139
|
|
{{- if $ambientEnabled }}
|
|
{{- /* networkPolicy.ingress.ambientMesh (Gitea #143). 15008/TCP is ztunnel's
|
|
HBONE tunnel, the port every inbound connection arrives on once the
|
|
namespace carries istio.io/dataplane-mode - ambient "does not and will
|
|
never bypass Kubernetes NetworkPolicy enforcement", so without it a pod
|
|
in the mesh is unreachable.
|
|
|
|
It is the one port here that is NOT a containerPort of the selected pod
|
|
spec: ztunnel terminates it, not the application. ci/run-networkpolicy-
|
|
test.sh holds a NAMED exception for exactly this number, gated on exactly
|
|
this value, and proves on a second render that it stays the only such
|
|
port and that it is absent while the value is false.
|
|
|
|
THE PORT HALF ONLY, and that is not an omission. Elsewhere this switch
|
|
also adds 169.254.7.127/32 as a probe source, because inside the mesh the
|
|
kubelet's probes are redirected away from the worker node's address.
|
|
This chart offers no networkPolicy.probeSources at all, so the rule
|
|
carrying the probe port is never restricted by source - and an
|
|
unrestricted rule needs no probe address. Measured in the render: three
|
|
tcpSocket probes, so these ARE network probes - they are simply never
|
|
restricted here, and 445 is additionally published as a NodePort.
|
|
WHICH RULE IT JOINS:
|
|
the only rule this policy has, the one carrying 445 and 139.
|
|
AN ISTIO CONSTANT, NOT A STANDARD: 15008 is not registered with
|
|
IANA for this, no protocol prescribes it, and Kubernetes knows
|
|
nothing about it - Istio picked it for HBONE and Istio can change
|
|
it. Hence a VALUE with a documented default rather than a literal
|
|
here, so an operator can correct it without a chart release. Read
|
|
for ztunnel 1.30.6. The exception ci/run-networkpolicy-test.sh
|
|
grants is pinned to the number THAT TEST names, plus a check that
|
|
this chart declares the same default - never to whatever the value
|
|
says, because that would let a mistyped port ride in through a
|
|
configurable field (design A of #143).
|
|
|
|
NOT MEASURED: that 15008 alone suffices comes from Istio's
|
|
documentation. Measured on this cluster is only which listeners ztunnel
|
|
opens. Provable at the first namespace to join the mesh; none has. */}}
|
|
- protocol: TCP
|
|
port: {{ int $ambientPort }}
|
|
{{- end }}
|
|
egress:
|
|
{{- /*
|
|
DNS, unconditionally. There is no value to switch this off, and that is
|
|
deliberate: a knob whose only other setting breaks every name lookup in
|
|
the pod is a trap and not a feature.
|
|
*/}}
|
|
- ports:
|
|
- protocol: UDP
|
|
port: 53
|
|
- protocol: TCP
|
|
port: 53
|
|
{{- with $np.egress }}
|
|
{{- with .extraPorts }}
|
|
{{- /*
|
|
Ports only, to any destination - see the header. This is the operator's
|
|
escape hatch from the egress cap, and the only alternative to switching
|
|
the whole policy off.
|
|
*/}}
|
|
- ports:
|
|
{{- range . }}
|
|
- protocol: TCP
|
|
port: {{ int . }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{- end }}
|