Корневое разрешение сценария входа в 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, вам, вероятно, придется сначала внести несколько изменений в конфигурацию.