{{- /* NetworkPolicy for satisfactory (Gitea #5). INGRESS ONLY, AND THE MISSING EGRESS SECTION IS THE DECISION IN THIS FILE. Two reasons, and they compound. First, what this server needs outbound is Steam's content delivery, and that is not a port list anyone can pin down: the dedicated server downloads and UPDATES the game through SteamCMD over TCP 80 and 443 plus the 27015-27050 range, and talks to the Steam master servers over UDP 27000-27100 and 4380. Valve changes that set, the server re-downloads on every update, and a cap that is wrong leaves a server that cannot start - or worse, one that starts and never appears in the server browser. Second, AND THIS IS WHY THE DECISION GOES THIS WAY RATHER THAN THE OTHER: satisfactory is the ONE chart in this repository with no install-test at all. It is in ci/excluded-charts.txt, because the image is multiple GB and the first start pulls over 10GB of game files - impractical on a runner. So an egress cap here would be the only policy in the sweep with no empirical check whatsoever behind it, on the chart whose correct port set is least knowable. Review is the only net this chart has, and a review cannot verify a Steam port range. So valkey's rule applies: policyTypes names only what there is something to restrict. A deployment that wants an egress cap should write one at release level, where the Steam behaviour can actually be observed. What the Ingress half still buys is real: only the three declared game ports are reachable, so anything else the image binds is not. 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 }} 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 ingress: {{- /* THE GAME PORTS, all three published as NodePorts and all deliberately open: the clients are players on the internet and, after NodePort masquerading, the source address is a cluster node anyway. The game port appears TWICE, once for each protocol, because the server binds it as both - and a policy that named only TCP would be accepted, would look complete, and would drop the UDP half of the game traffic. The TCP side is additionally what the readiness probe opens a socket against. The numbers go through satisfactory.formatNumber for the same reason they do in the Service and the StatefulSet: a port read from values as a float64 renders in exponential notation above a certain size, and a NetworkPolicy with "3.0777e +04" in it is not valid. */}} - ports: - protocol: TCP port: {{ include "satisfactory.formatNumber" .Values.server.gamePort }} - protocol: UDP port: {{ include "satisfactory.formatNumber" .Values.server.gamePort }} - protocol: TCP port: {{ include "satisfactory.formatNumber" .Values.server.messagingPort }} {{- end }}