#postgresql #docker #ssl #permissions
#postgresql #docker #ssl #разрешения
Вопрос:
Я пытаюсь развернуть контейнер postgresql. Я пытаюсь поместить ssl-сертификат и ключ в контейнер, используя тома, но я не могу получить правильные разрешения. Файлы должны быть доступны для чтения postgres
пользователю контейнера, но также иметь ограниченные разрешения ( 600
).
Возможно ли это с использованием томов, или мне придется переопределить Dockerfile для этого?
Спасибо.
Ответ №1:
Можно смонтировать ключ и сертификат в контейнер postgres, и postgres сможет использовать их оттуда. Но вам придется столкнуться с проблемой с владельцем и разрешениями server.key
.
Из документации PostgreSQL по этому вопросу:
В системах Unix разрешения для server.key должны запрещать любой доступ к миру или группе; добейтесь этого с помощью команды chmod 0600 server.key. В качестве альтернативы файл может принадлежать root и иметь групповой доступ на чтение (то есть разрешения 0640).
Это означает, что вы должны:
- Задайте владельцу
server.key
файла значениеroot
илиpostgres
. - В зависимости от владельца файла server.key вам придется установить для него соответствующие
600
или640
разрешения. (Обновление: здесь подразумевается, что владельцем группы файла является группа, которая содержитpostgres
пользователя, как группа по умолчаниюpostgres
)
Если вы работаете с хоста Windows, вам будет нелегко с этим справиться. Потому что разрешения для любого файла в томе, который вы сопоставляете в контейнер, будут -rwxr-xr-x
( 755
), а владельцем будет root
. И вы не сможете изменить это, пока файл монтируется с ваших томов Windows. Если вы попытаетесь использовать chmod
для файла, он просто завершится с ошибкой.
С другой стороны, если вы находитесь на хосте Linux, это можно сделать с минимальными усилиями. Разрешения от хост-системы будут сохранены в образе. И право собственности тоже будет, в буквальном смысле. Под этим я подразумеваю, что числовой владелец и владелец группы server.key
будут сохранены, когда они будут сопоставлены с томом в контейнере. Между хостом и контейнером они совместно используют ACL Linux, поэтому они просто соблюдают одни и те же свойства файлов. (Владелец, владелец группы, разрешения). Итак, если у вашего локального пользователя Linux на хост-компьютере есть UID:GID
1000:1000
, и вы создаете server.key
файл, то для UID:GID
файла также будет установлено значение 1000:1000
. Если вы затем сопоставите файл с контейнером и понаблюдаете за ним изнутри — он также просто увидит 1000:1000
. Это означает, что мы можем управлять UID:GID
как изнутри, так и снаружи контейнера, при отображении с хоста Linux.
Примечание. Необязательно, чтобы пользователь с UID
именем, которое вы назначаете в качестве владельца для файла, разрешалось устанавливать несуществующих UID:GID
владельцев файлов.
В alpine
производном образе postgres postgres
пользователь / группа имеет UID:GID
70:70
. На debian
производной postgres UID:GID
является 999:999
. И не подавляя, root имеет 0:0
на них обоих.
Это означает, что либо необходимо:
- Измените
UID:GID
содержимое файлаserver.key
после запуска контейнера, когда том уже смонтирован. - Измените
UID:GID
содержимое файлаserver.key
перед запуском контейнера
Поскольку установка этого параметра после запуска контейнера означала бы вмешательство в сценарии запуска образа postgres — давайте установим их перед запуском контейнера. В локальной файловой системе, из которой вы их монтируете.
Настройка 600
разрешений и postgres
в качестве владельца server.key
В случае, если вы используете alpine
производную, вам необходимо изменить владельца / группу на 70:70
. Если вы используете debian
производную, то 999:999
.
На вашем хостинге может не быть пользователя с помощью, например, UID
: 70
, но это не проблема.
Пример:
chown 70:70 server.key # 70:70 for alpine, 999:999 for debian
chmod 600 server.key
Настройка 640
разрешений и root
в качестве владельца server.key
Этот пример также предназначен для alpine image
Пример:
chown 0:70 server.key
chmod 640 server.key
На этом этапе все готово. Вам просто нужно сопоставить ключ и сертификат с контейнером и запустить postgres, как обычно.
Решение (linux / unix / macOS)
Я включу сюда фрагмент сценария, который сделает все это за вас для производной alpine. В этом примере будет задан корневой владелец 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
Я надеюсь, это все прояснит?
В этом суть источника ключа, генерирующего ключ, и сертификата.
Создание образа самостоятельно (решение для Windows)
Я включу небольшое руководство о том, как вы можете создать изображение самостоятельно, чтобы у вас был контейнер базы данных postgres с ssl. Это также будет работать в 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
Создайте образ с:
docker build -t mypg:01 .
И запуск с:
docker run -d --name postgres mypg:01
-c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt
-c ssl_key_file=/var/lib/postgresql/server.key
Комментарии:
1. Я не могу заставить его работать, используя root в качестве владельца и 0640 в качестве разрешений. Сбой базы данных с «ФАТАЛЬНЫМ: не удалось загрузить файл закрытого ключа «/etc/postgresql /server.key»: отказано в разрешении`.
2. спасибо за очень подробный ответ @AndreasLorenzen! Я пробовал оба подхода (
chown 70:70 amp;amp; chmod 0600
иchown 0:70 amp;amp; chmod 640
), и при первом подходе я получаюcould not load private key file "/var/lib/postgresql/server.key": Permission denied
, и при втором подходе я получаюprivate key file "/var/lib/postgresql/server.key" has group or world access
3. похоже, что это решение не работает в osx, по-видимому, файл не смонтирован с правильным владельцем.
4. Есть решение для mac os x?
5. Что ж, в этом случае решение «Windows» по созданию образа самостоятельно сработало бы. Я обновлю ответ, если вы сможете подтвердить, что это работает именно так. Я добавил macos, потому что прочитал, что docker не будет вести себя таким образом, когда где-то отображаются файлы сопоставления томов, но, похоже, это не так. Однако у меня нет Mac, чтобы протестировать это на себе.
Ответ №2:
В моем конкретном случае меня интересовало включение SSL при использовании стандартного образа postgres через docker-compose. Это решение позволяет 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/
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';
Это будет работать для любой конфигурации. Для SSL вы также захотите сгенерировать сертификаты (взятые из a 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 amp;amp; chown 999 server.key
Комментарии:
1. Этот ответ предоставляет сертификат сервера / ключ, как получить сертификат клиента / ключ для подключения к postgres с использованием ssl = verify-full?
2. Боюсь, здесь я не смогу вам помочь @steve . Это было сделано только в целях разработки.
Ответ №3:
Правильное решение для macOS
В macOS из-за поведения драйвера osxfs любой uid / gid, запущенный в контейнере, также является uid / gid, которому принадлежат подключенные файлы (поэтому владелец файлов в контейнере не будет совпадать с владельцем файла хоста).
В macOS, когда мы меняем владельца файла в контейнере, он записывает данные владельца в com.docker.owner
расширенный атрибут file (вместо обновления реального владельца файла).
итак, мы должны установить com.docker.owner
атрибут, чтобы указать владельца файла для контейнеров в docker (только на macOS).
Примечание: Если образ вашей Postgres DB основан на alpine, измените 0:999:999
на 0:70:70
chmod 600 server.key
xattr -w com.docker.owner 0:999:999 server.key # 0:70:70 for alpine-based image