使用ssl证书和带有卷的密钥部署postgresql docker

Cha*_*ois 3 postgresql permissions ssl docker

我正在尝试部署一个postgresql容器。我正在尝试使用卷将ssl证书和密钥放入容器中,但是我无法获得正确的权限。文件需要容器的postgres用户可读,但也具有有限的权限(600)。

是否可以使用卷,还是为此必须覆盖Dockerfile?

谢谢。

And*_*zen 7

可以将密钥和证书安装到postgres容器中,并让postgres从那里使用它们。但是您将不得不面对的所有者和权限问题server.key

PostgreSQL文档中可以找到

在Unix系统上,对server.key的许可必须禁止对world或group的任何访问。通过命令chmod 0600 server.key来实现。或者,该文件可以由root拥有,并具有组读取访问权限(即0640权限)。

这意味着您必须:

  1. server.key文件的所有者设置为rootpostgres
  2. 根据server.key文件的所有者,您将不得不分别设置它600或对其进行640许可。(更新:此处暗示文件的组所有者是包含postgres用户的组,如默认postgres组)

如果使用Windows主机,则将很难。因为您映射到容器中的卷中的任何文件的权限均为-rwxr-xr-x755),所有者为root。只要从Windows卷上挂载文件,您将无法更改此设置。如果您尝试chmod在文件上使用它,它将仅以静默方式失败。

另一方面,如果您在linux主机上,则可以轻松完成此操作。来自主机系统的权限将保留在映像中。所有权也将日渐减少。我的意思是,server.key当将它们的体积所有者映射到容器中时,将保留它们的数字所有者和组所有者。它们在主机和容器之间共享linux ACL,因此它们只是观察文件的相同属性。(所有者,组所有者,权限)。因此,如果主机上的本地linux用户具有UID:GID 1000:1000,并且您创建了server.key文件,则UID:GID文件的也会设置为1000:1000。如果您随后将文件映射到容器中,并从内部进行观察-它也只会看到1000:1000。这意味着,我们可以控制UID:GID 从linux主机映射时,可以从容器的内部和外部进行。

注意。不必具有UID您指定为文件所有者的用户,可以设置不存在UID:GID的文件所有者。

在postgres alpine派生图像中,postgres用户/组具有UID:GID 70:70。在debian导数上,postgres UID:GID999:999。并不奇怪,root都存在0:0于这两个方面。

这意味着必须:

  1. 启动容器后,已经安装了卷后,请更改UID:GID文件的。server.key
  2. 启动容器之前更改UID:GID文件的server.key

由于在容器启动后进行设置,将暗示篡改postgres映像的启动脚本-让我们选择在启动容器之前进行设置。在要从中挂载它们的本地文件系统中。

设置600权限并postgres作为所有者server.key

如果您要使用alpine衍生工具,则需要将所有者/组更改为70:70。如果您使用debian导数,则999:999

例如,您的主机上可能没有用户UID70,但这不是问题。

例:

chown 70:70 server.key # 70:70 for alpine, 999:999 for debian
chmod 600 server.key
Run Code Online (Sandbox Code Playgroud)

设置640权限并root作为所有者server.key

这个例子也适用于高山图像

例:

chown 0:70 server.key
chmod 640 server.key
Run Code Online (Sandbox Code Playgroud)

此时,您可以开始了。您只需要将密钥和证书映射到容器中,然后像往常一样启动postgres。

解决方案(linux / unix / macOS)

我将在此处包括一个脚本片段,该片段将为您完成所有高山衍生产品。本示例将设置server.key的根所有者和postgres组所有者。

# generate the server.key and server.crt
openssl req -new -text -passout pass:abcd -subj /CN=localhost -out server.req
openssl rsa -in privkey.pem -passin pass:abcd -out server.key
openssl req -x509 -in server.req -text -key server.key -out server.crt

# set postgres (alpine) user as owner of the server.key and permissions to 600
chown 0:70 server.key
chmod 640 server.key

# start a postgres docker container, mapping the .key and .crt into the image.
docker run -d --name postgres \ 
  -v "$PWD/server.crt:/var/lib/postgresql/server.crt:ro" \
  -v "$PWD/server.key:/var/lib/postgresql/server.key:ro" \
  postgres:11-alpine \
  -c ssl=on \
  -c ssl_cert_file=/var/lib/postgresql/server.crt \
  -c ssl_key_file=/var/lib/postgresql/server.key
Run Code Online (Sandbox Code Playgroud)

我希望这可以清除一切吗?

这个要点是生成密钥和证书的密钥的来源。

自己构建映像(Windows解决方案)

我将提供有关如何自己构建映像的小型指南,以便您可以使用带有ssl的postgres数据库容器。这同样适用于Windows。

这是将为您完成的Dockerfile:

Dockerfile

FROM postgres:11-alpine

# On Windows root will own the files, and they will have permissions 755
COPY server.key /var/lib/postgresql/server.key
COPY server.crt /var/lib/postgresql/server.crt

# update the privileges on the .key, no need to touch the .crt  
RUN chmod 600 /var/lib/postgresql/server.key
RUN chown postgres:postgres /var/lib/postgresql/server.key
Run Code Online (Sandbox Code Playgroud)

使用以下方法生成图像:

FROM postgres:11-alpine

# On Windows root will own the files, and they will have permissions 755
COPY server.key /var/lib/postgresql/server.key
COPY server.crt /var/lib/postgresql/server.crt

# update the privileges on the .key, no need to touch the .crt  
RUN chmod 600 /var/lib/postgresql/server.key
RUN chown postgres:postgres /var/lib/postgresql/server.key
Run Code Online (Sandbox Code Playgroud)

并运行:

docker build -t mypg:01 .
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案似乎在 osx 中不起作用,显然该文件没有以正确的所有者安装。 (4认同)
  • 我无法使用 root 作为所有者和 0640 作为权限来工作。数据库失败,并显示“致命:无法加载私钥文件“/etc/postgresql/server.key”:权限被拒绝”。 (2认同)
  • 感谢@AndreasLorenzen 非常详细的回答!我已经尝试了两种方法(`chown 70:70 && chmod 0600` 和 `chown 0:70 && chmod 640`),第一种方法我得到`无法加载私钥文件“/var/lib/postgresql/server .key": Permission denied` 和第二种方法我得到`private key file "/var/lib/postgresql/server.key" has group or world access` (2认同)
  • mac os x 有什么解决方案吗? (2认同)

Bre*_*ire 6

在我的特定情况下,我有兴趣在通过 docker-compose 使用标准 postgres 映像时启用 SSL。该解决方案允许initdb照常运行,这对于设置数据库和用户很有用。

docker-compose.yaml

version: '3'
services:
  postgres:
    image: postgres:12.2
    environment:
      - POSTGRES_PASSWORD=password
      - POSTGRES_USER=myuser
      - POSTGRES_HOST_AUTH_METHOD=trust
    volumes:
      - ./postgres-initdb:/docker-entrypoint-initdb.d/
      - ./postgres-certs/:/var/lib/postgresql/certs/
Run Code Online (Sandbox Code Playgroud)

postgres-initdb/config.sql

ALTER SYSTEM SET ssl_cert_file TO '/var/lib/postgresql/certs/server.crt';
ALTER SYSTEM SET ssl_key_file TO '/var/lib/postgresql/certs/server.key';
ALTER SYSTEM SET ssl TO 'ON';
Run Code Online (Sandbox Code Playgroud)

这适用于任何配置。对于 SSL,您还需要生成证书(取自Gist):

set -euo pipefail

mkdir postgres-certs
cd postgres-certs

openssl req -new -text -passout pass:abcd -subj /CN=localhost -out server.req -keyout privkey.pem
openssl rsa -in privkey.pem -passin pass:abcd -out server.key
openssl req -x509 -in server.req -text -key server.key -out server.crt
chmod 600 server.key
test $(uname -s) == Linux && chown 999 server.key
Run Code Online (Sandbox Code Playgroud)