Skip to content

Commit 8be0144

Browse files
authored
Rework port binding logic without privileges (#3573)
This is a breaking change! To start Nginx Ingress Controller with this commit applied, you must use an updated image. Historically, the Ingress Controller entrypoint launched with restricted capabilities. Then Nginx process escalated privileges (NET_BIND_SERVICE) to bind ports 80 and 443 as non-root user. Allowing privilege escalation is generally frowned upon in various policies. The Nginx binary in old images was adding NET_BIND_SERVICE to its Permitted capability set and also setting the Effective bit, to enforce the Permitted capability during launch. (That's the escalation there.) With this change, privilege escalation is no longer allowed and the NET_BIND_SERVICE capability is removed. To allow the binary to start, the capabilities are no longer being adjusted on the binary file. This works because Kubernetes v1.22+ allows Pods to independently lower unprivileged port range to start with zero without affecting other ports (namespaced/"safe" sysctls). OBS! An old image may be used if the binary's Effective bit is removed: FROM nginx/nginx-ingress:3.0.2 USER root RUN setcap 'cap_net_bind_service=-e' /usr/sbin/nginx 'cap_net_bind_service=-e' /usr/sbin/nginx-debug \ && setcap -v 'cap_net_bind_service=-e' /usr/sbin/nginx 'cap_net_bind_service=-e' /usr/sbin/nginx-debug # 101 is nginx USER 101
1 parent 332f227 commit 8be0144

File tree

12 files changed

+37
-26
lines changed

12 files changed

+37
-26
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ jobs:
296296
{\"image\": \"debian-plus-nap\", \"marker\": \"appprotect\"}], \
297297
\"k8s\": [\"${{ needs.checks.outputs.k8s_latest }}\"]}" >> $GITHUB_OUTPUT
298298
else
299-
echo "matrix={\"k8s\": [\"1.21.14\", \"1.22.15\", \"1.23.13\", \"1.24.7\", \"1.25.3\", \"${{ needs.checks.outputs.k8s_latest }}\"], \
299+
echo "matrix={\"k8s\": [\"1.22.15\", \"1.23.13\", \"1.24.7\", \"1.25.3\", \"${{ needs.checks.outputs.k8s_latest }}\"], \
300300
\"images\": [{\"image\": \"debian\"}, {\"image\": \"debian-plus\"}]}" >> $GITHUB_OUTPUT
301301
fi
302302

build/Dockerfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
186186
# RUN update-ca-trust extract
187187

188188

189-
############################################# Create common files, permissions and setcap #############################################
189+
############################################# Create common files and permissions #############################################
190190
FROM ${BUILD_OS} as common
191191

192192
ARG BUILD_OS
@@ -209,8 +209,6 @@ RUN [ -n "${NAP_MODULES##*dos*}" ] && exit 0; mkdir -p /root/app_protect_dos /et
209209
&& chmod 777 /shared/cores /var/log/adm /var/run/adm /etc/app_protect_dos
210210

211211
RUN --mount=type=bind,target=/tmp mkdir -p /var/lib/nginx /etc/nginx/secrets /etc/nginx/stream-conf.d \
212-
&& setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx 'cap_net_bind_service=+ep' /usr/sbin/nginx-debug \
213-
&& setcap -v 'cap_net_bind_service=+ep' /usr/sbin/nginx 'cap_net_bind_service=+ep' /usr/sbin/nginx-debug \
214212
&& [ -z "${BUILD_OS##*plus*}" ] && PLUS=-plus; cp -a /tmp/internal/configs/version1/nginx$PLUS.ingress.tmpl /tmp/internal/configs/version1/nginx$PLUS.tmpl \
215213
/tmp/internal/configs/version2/nginx$PLUS.virtualserver.tmpl /tmp/internal/configs/version2/nginx$PLUS.transportserver.tmpl / \
216214
&& chown -R 101:0 /etc/nginx /var/cache/nginx /var/lib/nginx /*.tmpl \

cmd/nginx-ingress/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ func kubernetesVersionInfo(kubeClient kubernetes.Interface) {
233233
}
234234
glog.Infof("Kubernetes version: %v", k8sVersion)
235235

236-
minK8sVersion, err := util_version.ParseGeneric("1.21.0")
236+
minK8sVersion, err := util_version.ParseGeneric("1.22.0")
237237
if err != nil {
238238
glog.Fatalf("unexpected error parsing minimum supported version: %v", err)
239239
}

deployments/daemon-set/nginx-ingress.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ spec:
1919
spec:
2020
serviceAccountName: nginx-ingress
2121
automountServiceAccountToken: true
22+
securityContext:
23+
sysctls:
24+
- name: "net.ipv4.ip_unprivileged_port_start"
25+
value: "0"
2226
containers:
2327
- image: nginx/nginx-ingress:3.0.2
2428
imagePullPolicy: IfNotPresent
@@ -47,13 +51,11 @@ spec:
4751
# cpu: "1"
4852
# memory: "1Gi"
4953
securityContext:
50-
allowPrivilegeEscalation: true
54+
allowPrivilegeEscalation: false
5155
runAsUser: 101 #nginx
5256
capabilities:
5357
drop:
5458
- ALL
55-
add:
56-
- NET_BIND_SERVICE
5759
env:
5860
- name: POD_NAMESPACE
5961
valueFrom:

deployments/daemon-set/nginx-plus-ingress.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ spec:
1919
spec:
2020
serviceAccountName: nginx-ingress
2121
automountServiceAccountToken: true
22+
securityContext:
23+
sysctls:
24+
- name: "net.ipv4.ip_unprivileged_port_start"
25+
value: "0"
2226
containers:
2327
- image: nginx-plus-ingress:3.0.2
2428
imagePullPolicy: IfNotPresent
@@ -47,13 +51,11 @@ spec:
4751
# cpu: "1"
4852
# memory: "1Gi"
4953
securityContext:
50-
allowPrivilegeEscalation: true
54+
allowPrivilegeEscalation: false
5155
runAsUser: 101 #nginx
5256
capabilities:
5357
drop:
5458
- ALL
55-
add:
56-
- NET_BIND_SERVICE
5759
env:
5860
- name: POD_NAMESPACE
5961
valueFrom:

deployments/deployment/nginx-ingress.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ spec:
2020
spec:
2121
serviceAccountName: nginx-ingress
2222
automountServiceAccountToken: true
23+
securityContext:
24+
sysctls:
25+
- name: "net.ipv4.ip_unprivileged_port_start"
26+
value: "0"
2327
containers:
2428
- image: nginx/nginx-ingress:3.0.2
2529
imagePullPolicy: IfNotPresent
@@ -46,14 +50,12 @@ spec:
4650
# cpu: "1"
4751
# memory: "1Gi"
4852
securityContext:
49-
allowPrivilegeEscalation: true
53+
allowPrivilegeEscalation: false
5054
runAsUser: 101 #nginx
5155
runAsNonRoot: true
5256
capabilities:
5357
drop:
5458
- ALL
55-
add:
56-
- NET_BIND_SERVICE
5759
env:
5860
- name: POD_NAMESPACE
5961
valueFrom:

deployments/deployment/nginx-plus-ingress.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ spec:
2020
spec:
2121
serviceAccountName: nginx-ingress
2222
automountServiceAccountToken: true
23+
securityContext:
24+
sysctls:
25+
- name: "net.ipv4.ip_unprivileged_port_start"
26+
value: "0"
2327
containers:
2428
- image: nginx-plus-ingress:3.0.2
2529
imagePullPolicy: IfNotPresent
@@ -48,14 +52,12 @@ spec:
4852
# cpu: "1"
4953
# memory: "1Gi"
5054
securityContext:
51-
allowPrivilegeEscalation: true
55+
allowPrivilegeEscalation: false
5256
runAsUser: 101 #nginx
5357
runAsNonRoot: true
5458
capabilities:
5559
drop:
5660
- ALL
57-
add:
58-
- NET_BIND_SERVICE
5961
env:
6062
- name: POD_NAMESPACE
6163
valueFrom:

deployments/helm-chart-dos-arbitrator/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: nginx-appprotect-dos-arbitrator
22
version: 0.1.0
33
appVersion: 1.1.0
44
apiVersion: v1
5-
kubeVersion: ">= 1.21.0-0"
5+
kubeVersion: ">= 1.22.0-0"
66
description: NGINX App Protect Dos arbitrator
77
icon: https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v3.0.2/deployments/helm-chart-dos-arbitrator/chart-icon.png
88
home: https://github.com/nginxinc/kubernetes-ingress

deployments/helm-chart/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apiVersion: v2
22
name: nginx-ingress
33
version: 0.16.2
44
appVersion: 3.0.2
5-
kubeVersion: ">= 1.21.0-0"
5+
kubeVersion: ">= 1.22.0-0"
66
type: application
77
description: NGINX Ingress Controller
88
icon: https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v3.0.2/deployments/helm-chart/chart-icon.png

deployments/helm-chart/templates/controller-daemonset.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ spec:
4343
spec:
4444
serviceAccountName: {{ include "nginx-ingress.serviceAccountName" . }}
4545
automountServiceAccountToken: true
46+
securityContext:
47+
sysctls:
48+
- name: "net.ipv4.ip_unprivileged_port_start"
49+
value: "0"
4650
terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }}
4751
{{- if .Values.controller.nodeSelector }}
4852
nodeSelector:
@@ -110,14 +114,12 @@ spec:
110114
initialDelaySeconds: {{ .Values.controller.readyStatus.initialDelaySeconds }}
111115
{{- end }}
112116
securityContext:
113-
allowPrivilegeEscalation: true
117+
allowPrivilegeEscalation: false
114118
runAsUser: 101 #nginx
115119
runAsNonRoot: true
116120
capabilities:
117121
drop:
118122
- ALL
119-
add:
120-
- NET_BIND_SERVICE
121123
{{- if or .Values.controller.volumeMounts .Values.nginxServiceMesh.enable }}
122124
volumeMounts:
123125
{{- end }}

0 commit comments

Comments
 (0)