Корневое разрешение сценария входа в Docker

У меня есть Dockerfile, который имеет 3 ограничения:

1.) Окончательное утверждение USER в Dockerfile должно быть USER tomcat в целях безопасности (он создан на основе tomcat: 8.5.23-jre8-alpine image)

2.) Он не может запустить chmod на /root/ каталог или $JAVA_HOME

3.) Он должен быть в состоянии изменить $JAVA_HOME/lib/security каталог в точке входа, а не в Dockerfile (так как сертификаты передаются при запуске контейнера)

На данный момент у меня есть

FROM tomcat:8.5.23-jre8-alpine

#### OTHER IMAGE COMMANDS ####

COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh

RUN chown root:root /usr/local/bin/entrypoint.sh

RUN chmod 4755 /usr/local/bin/entrypoint.sh

USER tomcat

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["catalina.sh", "run"]

Я полагал, что предоставление права собственности на файл пользователю root и chmod 4755 позволят пользователю tomcat выполнить точку входа, но при этом точка входа будет работать от имени пользователя root, чтобы он мог изменять файловую систему так, как ему хотелось бы. Тем не менее, когда я запускаю эту строку в точке входа

$JAVA_HOME/bin/keytool -import -alias ca_local -keystore $JAVA_HOME/lib/security/cacerts -storepass XXXXX -noprompt -trustcacerts -file /usr/local/tomcat/certificates/ca-local.cer

Я получаю следующую ошибку:

keytool error: java.io.FileNotFoundException: /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts (Permission denied)

Кажется, точка входа на самом деле не работает от имени пользователя root, как подразумевает chown / chmod. Я знаю, что все мои файлы находятся в правильных местах, потому что, когда я удаляю USER tomcat из Dockerfile все отлично работает. Чего мне не хватает при настройке разрешения точки входа?

1 ответ

Решение

На этих двух шагах:

RUN chown root:root /usr/local/bin/entrypoint.sh
RUN chmod 4755 /usr/local/bin/entrypoint.sh

Вы обеспечиваете свой entrypoint.sh Сценарий принадлежит root, а затем вы пытаетесь установить setuid немного. К сожалению, этот второй шаг не сработает: вы не можете пометить скрипт оболочки (или фактически любой интерпретируемый скрипт) как setuid; бит будет просто проигнорирован. Смотрите, например, этот вопрос.

Но если это сработает, у вас будет другая проблема: ваша ENTRYPOINT скрипт отвечает за обработку любой команды, переданной в ваш контейнер, либо docker run командная строка или через CMD директива в Dockerfile. Если это setuid попытка сработала, ваша ENTRYPOINT скрипт будет работать как root... что означает, что вы в конечном итоге запустить catalina.sh run как корень, что означает ваш USER Директива совершенно бессмысленна.

Вы можете добраться до того же места, просто бросив USER директива, позволяющая точке входа работать как root, а затем иметь свой ENTRYPOINT скрипт запуска CMD как tomcat пользователь (например, используя su или же sudo):

FROM tomcat:8.5.23-jre8-alpine

#### OTHER IMAGE COMMANDS ####

COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["sh", "/usr/local/bin/entrypoint.sh"]
CMD ["catalina.sh", "run"]

И в entrypoint.sh:

#!/bin/sh

# Do stuff as root here.
$JAVA_HOME/bin/keytool -import -alias ca_local \
  -keystore $JAVA_HOME/lib/security/cacerts 
  -storepass XXXXX -noprompt -trustcacerts \
  -file /usr/local/tomcat/certificates/ca-local.cer

# Now run everything else as a non-root user
exec su - tomcat -c "$*"

Это очень распространенный механизм для обработки задач начальной настройки, которые должны запускаться от имени пользователя root, а все остальное - от имени пользователя без полномочий root.

Здесь все еще есть ряд проблем: tomcat:8.5.23-jre8-alpine не имеет tomcat пользователь и сценарии в /usr/local/tomcat/bin исполняются только root, Поэтому, если вы хотите, чтобы это конкретное изображение работало с пользователем без полномочий root, вам, вероятно, придется сначала внести несколько изменений в конфигурацию.

Другие вопросы по тегам