-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tighten up write permissions in Docker image #70635
Changes from 14 commits
9ef552b
000e018
0327e44
6217e57
a1bf983
6b6b847
e13ae49
4a0482d
12e455a
4ed7857
01d3a6b
90b01ff
735a20c
45e7c91
c5675be
c8a617d
53c07d6
ba89e79
31acf7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,7 +47,7 @@ RUN set -eux ; \\ | |
sha256sum -c \${tini_bin}.sha256sum ; \\ | ||
rm \${tini_bin}.sha256sum ; \\ | ||
mv \${tini_bin} /bin/tini ; \\ | ||
chmod +x /bin/tini | ||
chmod 0555 /bin/tini | ||
|
||
<% } else if (docker_base == 'iron_bank') { %> | ||
################################################################################ | ||
|
@@ -62,7 +62,7 @@ FROM ${base_image} AS builder | |
# `tini` is a tiny but valid init for containers. This is used to cleanly | ||
# control how ES and any child processes are shut down. | ||
COPY tini /bin/tini | ||
RUN chmod 0755 /bin/tini | ||
RUN chmod 0555 /bin/tini | ||
|
||
<% } else { %> | ||
|
||
|
@@ -167,7 +167,7 @@ RUN set -e ; \\ | |
sha256sum -c "\${TINI_BIN}.sha256sum" ; \\ | ||
rm "\${TINI_BIN}.sha256sum" ; \\ | ||
mv "\${TINI_BIN}" /rootfs/bin/tini ; \\ | ||
chmod +x /rootfs/bin/tini ; \\ | ||
chmod 0555 /rootfs/bin/tini ; \\ | ||
curl --retry 10 -L -O \\ | ||
# Here we're fetching the same binaries used for the official busybox docker image from their GtiHub repository | ||
"https://github.com/docker-library/busybox/raw/\${BUSYBOX_COMMIT}/stable/musl/busybox.tar.xz" ; \\ | ||
|
@@ -230,26 +230,24 @@ RUN tar -zxf /opt/elasticsearch.tar.gz --strip-components=1 | |
COPY ${config_dir}/elasticsearch.yml config/ | ||
COPY ${config_dir}/log4j2.properties config/log4j2.docker.properties | ||
|
||
# 1. Configure the distribution for Docker | ||
# 2. Ensure directories are created. Most already are, but make sure | ||
# 3. Apply correct permissions | ||
# 4. Move the distribution's default logging config aside | ||
# 5. Move the generated docker logging config so that it is the default | ||
# 6. Apply more correct permissions | ||
# 7. The JDK's directories' permissions don't allow `java` to be executed under a different | ||
# group to the default. Fix this. | ||
# 8. Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks. | ||
# 9. Ensure all files are world-readable by default. It should be possible to | ||
# examine the contents of the image under any UID:GID | ||
# 1. Configure the distribution for Docker | ||
# 2. Create required directory | ||
# 3. Move the distribution's default logging config aside | ||
# 4. Move the generated docker logging config so that it is the default | ||
# 5. Remove write permissions from all directories | ||
# 6. Remove write and exec permissions from all files | ||
# 7. Make tools executable again | ||
# 8. Make some directories writable again | ||
# 9. Make some files writable again | ||
RUN sed -i -e 's/ES_DISTRIBUTION_TYPE=tar/ES_DISTRIBUTION_TYPE=docker/' bin/elasticsearch-env && \\ | ||
mkdir -p config/jvm.options.d data logs plugins && \\ | ||
chmod 0775 config config/jvm.options.d data logs plugins && \\ | ||
mkdir data && \\ | ||
mv config/log4j2.properties config/log4j2.file.properties && \\ | ||
mv config/log4j2.docker.properties config/log4j2.properties && \\ | ||
chmod 0660 config/elasticsearch.yml config/log4j2*.properties && \\ | ||
find ./jdk -type d -exec chmod 0755 {} + && \\ | ||
find . -xdev -perm -4000 -exec chmod ug-s {} + && \\ | ||
find . -type f -exec chmod o+r {} + | ||
find . -type d -exec chmod 0555 {} + && \\ | ||
find . -type f -exec chmod 0444 {} + && \\ | ||
chmod 0555 bin/* jdk/bin/* jdk/lib/jspawnhelper modules/x-pack-ml/platform/linux-\$(arch)/bin/* && \\ | ||
chmod 0775 config config/jvm.options.d data logs plugins && \\ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Including plugins here seems problematic. They are code, and should therefore not be writeable by the user that runs elasticsearch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I remember we discussed the plugins a while ago in #69533. Being able to install a plugin while running Elasticsearch as a non-root user (FWIW: ideally without the need to |
||
find config -type f -exec chmod 0664 {} + | ||
|
||
<% if (docker_base == "ubi" || docker_base == "iron_bank") { %> | ||
|
||
|
@@ -287,8 +285,7 @@ RUN ${package_manager} update --setopt=tsflags=nodocs -y && \\ | |
|
||
RUN groupadd -g 1000 elasticsearch && \\ | ||
adduser -u 1000 -g 1000 -G 0 -d /usr/share/elasticsearch elasticsearch && \\ | ||
chmod 0775 /usr/share/elasticsearch && \\ | ||
chown -R 1000:0 /usr/share/elasticsearch | ||
chown -R 0:0 /usr/share/elasticsearch | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The rpm/deb packages setup ownership so that the group is the elasticsearch user, which is readable but not writable. Can we just keep the original permissions defined in the distribution and fix the ownership? |
||
|
||
<% } else { %> | ||
|
||
|
@@ -304,15 +301,14 @@ COPY --from=rootfs /rootfs / | |
RUN addgroup -g 1000 elasticsearch && \\ | ||
adduser -D -u 1000 -G elasticsearch -g elasticsearch -h /usr/share/elasticsearch elasticsearch && \\ | ||
addgroup elasticsearch root && \\ | ||
chmod 0775 /usr/share/elasticsearch && \\ | ||
chgrp 0 /usr/share/elasticsearch | ||
chown -R 0:0 /usr/share/elasticsearch | ||
|
||
<% } %> | ||
|
||
ENV ELASTIC_CONTAINER true | ||
|
||
WORKDIR /usr/share/elasticsearch | ||
COPY --from=builder --chown=1000:0 /usr/share/elasticsearch /usr/share/elasticsearch | ||
COPY --from=builder --chown=0:0 /usr/share/elasticsearch /usr/share/elasticsearch | ||
|
||
<% if (docker_base == "ubi" || docker_base == "iron_bank") { %> | ||
COPY --from=builder --chown=0:0 /bin/tini /bin/tini | ||
|
@@ -329,10 +325,16 @@ COPY ${bin_dir}/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh | |
# 4. Replace OpenJDK's built-in CA certificate keystore with the one from the OS | ||
# vendor. The latter is superior in several ways. | ||
# REF: https://github.com/elastic/elasticsearch-docker/issues/171 | ||
# 5. Tighten up permissions on the ES home dir (the permissions of the contents are handled earlier) | ||
# 6. You can't install plugins that include configuration when running as `elasticsearch` and the `config` | ||
# dir is owned by `root`, because the installed tries to manipulate the permissions on the plugin's | ||
# config directory. | ||
RUN chmod g=u /etc/passwd && \\ | ||
chmod 0775 /usr/local/bin/docker-entrypoint.sh && \\ | ||
chmod 0555 /usr/local/bin/docker-entrypoint.sh && \\ | ||
find / -xdev -perm -4000 -exec chmod ug-s {} + && \\ | ||
ln -sf /etc/pki/ca-trust/extracted/java/cacerts /usr/share/elasticsearch/jdk/lib/security/cacerts | ||
ln -sf /etc/pki/ca-trust/extracted/java/cacerts /usr/share/elasticsearch/jdk/lib/security/cacerts && \\ | ||
chmod 0775 /usr/share/elasticsearch && \\ | ||
chown elasticsearch /usr/share/elasticsearch/config | ||
|
||
EXPOSE 9200 9300 | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -100,7 +100,7 @@ public void teardownTest() { | |
* Checks that the Docker image can be run, and that it passes various checks. | ||
*/ | ||
public void test010Install() { | ||
verifyContainerInstallation(installation, distribution()); | ||
verifyContainerInstallation(installation); | ||
} | ||
|
||
/** | ||
|
@@ -147,7 +147,7 @@ public void test041AmazonCaCertsAreInTheKeystore() { | |
public void test042KeystorePermissionsAreCorrect() throws Exception { | ||
waitForElasticsearch(installation); | ||
|
||
assertPermissionsAndOwnership(installation.config("elasticsearch.keystore"), p660); | ||
assertPermissionsAndOwnership(installation.config("elasticsearch.keystore"), "elasticsearch", "root", p660); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems backwards. Shouldn't the group be elasticsearch and the owner be root? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The startup process creates this if necessary at startup, so it has to be |
||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,14 +37,16 @@ public enum Fileness { | |
Directory | ||
} | ||
|
||
public static final Set<PosixFilePermission> p775 = fromString("rwxrwxr-x"); | ||
public static final Set<PosixFilePermission> p770 = fromString("rwxrwx---"); | ||
public static final Set<PosixFilePermission> p755 = fromString("rwxr-xr-x"); | ||
public static final Set<PosixFilePermission> p750 = fromString("rwxr-x---"); | ||
public static final Set<PosixFilePermission> p660 = fromString("rw-rw----"); | ||
public static final Set<PosixFilePermission> p444 = fromString("r--r--r--"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is now unused right? |
||
public static final Set<PosixFilePermission> p555 = fromString("r-xr-xr-x"); | ||
public static final Set<PosixFilePermission> p600 = fromString("rw-------"); | ||
public static final Set<PosixFilePermission> p644 = fromString("rw-r--r--"); | ||
public static final Set<PosixFilePermission> p660 = fromString("rw-rw----"); | ||
public static final Set<PosixFilePermission> p664 = fromString("rw-rw-r--"); | ||
public static final Set<PosixFilePermission> p600 = fromString("rw-------"); | ||
public static final Set<PosixFilePermission> p750 = fromString("rwxr-x---"); | ||
public static final Set<PosixFilePermission> p755 = fromString("rwxr-xr-x"); | ||
public static final Set<PosixFilePermission> p770 = fromString("rwxrwx---"); | ||
public static final Set<PosixFilePermission> p775 = fromString("rwxrwxr-x"); | ||
|
||
private final Fileness fileness; | ||
private final String owner; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The correct files already are executable in the original archive that is extracted. Why was the executable bit removed in the first place? Seems like we should just keep it as it was, instead of trying to reform what is executable here.