我试图让 Nginx 以最小的权限运行,同时能够充当端口 80 上的代理。换句话说,这是我正在使用的 securityContext:
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 12321
runAsGroup: 12321
privileged: false
capabilities:
drop:
- all
add: ["NET_BIND_SERVICE"]
据我收集到的有关该主题的大多数 stackoverflow 问题,设置为
allowPrivilegeEscalation
至 true
。除此之外,我发现 Bridcrew 的这个博客将其设置为 false
但我无法在我这边重现他们的示例。
我也尝试使用
nginxinc/nginx-unprivileged
基础图像,但也没有成功。
这是我的 Dockerfile。它由大量
chown
和 chmod
ing 组成,但我还安装了 libcap2,这样我就可以设置 NET_BIND_SERVICE
功能并移动一些文件以获得自定义入口点。
FROM nginx
ENV NGINX_USER="proxy-user" \
NGINXR_UID="12321" \
NGINX_GROUP="proxy-group" \
NGINX_GID="12321"
RUN set -ex; \
groupadd -r --gid "$NGINX_GID" "$NGINX_GROUP"; \
useradd -r --uid "$NGINXR_UID" --gid "$NGINX_GID" "$NGINX_USER"
# Create empty pid file and assign it to the proxy user
RUN touch /var/run/nginx.pid && \
chown -R proxy-user:proxy-group /var/run/nginx.pid
# Change permissions of other nginx files
RUN chmod +x /usr/sbin/nginx && \
chown -R proxy-user:proxy-group /usr/share/nginx/html && \
chown -R proxy-user:proxy-group /var/cache/nginx && \
chown -R proxy-user:proxy-group /var/log/nginx && \
chown -R proxy-user:proxy-group /etc/nginx/conf.d
# Install libcap and set the NET_BIND_SERVICE capability to the Nginx binary
RUN apt-get -qq update && \
apt-get -qq install --no-install-recommends libcap2-bin -y && \
setcap CAP_NET_BIND_SERVICE=ep /usr/sbin/nginx
COPY nginx.conf /etc/nginx/nginx.conf
COPY nginx.conf.template /etc/nginx/templates/
# Move all nginx files to another directory. We will later mount a writable directory under /etc/nginx/ and copy these files back before launching Nginx
RUN mv /etc/nginx /etc/nginx-defaults
# This file does the copying and launches nginx (via docker-entrypoint.sh)
COPY entrypoint.sh .
RUN chmod +x ./entrypoint.sh
USER proxy-user
ENTRYPOINT ./entrypoint.sh
正如评论中提到的,我们将安装几个 Nginx 可以使用的可写空目录:
volumeMounts:
- name: nginx-etc
mountPath: /etc/nginx
- name: nginx-cache
mountPath: /var/cache/nginx
- name: nginx-tmp
mountPath: /tmp/nginx
- name: nginx-pid
mountPath: /var/run
在 nginx.conf 中,有几个路径指向这些目录,以防它们还不是默认值:
http {
proxy_temp_path /tmp/nginx/proxy_temp;
client_body_temp_path /tmp/nginx/client_temp;
fastcgi_temp_path /tmp/nginx/fastcgi_temp;
uwsgi_temp_path /tmp/nginx/uwsgi_temp;
scgi_temp_path /tmp/nginx/scgi_temp;
...
}
这是自定义入口点
#!/bin/sh
echo "Running from custom entrypoint"
# Move the nginx files back to the default directory
cp -a /etc/nginx-defaults/. /etc/nginx/
# Launch nginx through the docker entrypoint
./docker-entrypoint.sh nginx
我收到的错误是由于权限被拒绝,它无法绑定到端口 80:
2023/03/31 12:31:03 [emerg] 11#11: bind() to 0.0.0.0:80 failed (13: Permission denied)
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
将
allowPrivilegeEscalation
设置为 true
可解决此问题。以及绑定到非特权端口(>1024),但是有没有一种方法可以解决特权升级问题,而无需绑定到更高的端口?
根据要求编辑要使用的整个 pod 的 yaml。此示例使用未修改的 nginx 映像,该映像也尝试绑定到端口 80 并显示绑定错误。
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
- name: proxy
image: nginx
imagePullPolicy: Always
volumeMounts:
- name: nginx-cache
mountPath: /var/cache/nginx
- name: nginx-tmp
mountPath: /tmp/nginx
- name: nginx-pid
mountPath: /var/run
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 12321
runAsGroup: 12321
privileged: false
capabilities:
drop:
- all
add: ["NET_BIND_SERVICE"]
volumes:
- name: nginx-cache
emptyDir:
sizeLimit: 1Mi
- name: nginx-tmp
emptyDir:
sizeLimit: 1Mi
- name: nginx-pid
emptyDir:
sizeLimit: 1Mi
如果没有特权访问,您无法找到特权端口(小于 1024)。 https://medium.com/@natrajrams4/binding-to-low-ports-as-non-root-user-in-kubernetes-79666f52c6ae有一些技巧。但我建议你使用更高数量的端口