From 4bc82ce2ba7a1a459510d71bf8aafcc2693ae561 Mon Sep 17 00:00:00 2001 From: Andre Henn Date: Tue, 12 Dec 2023 14:24:03 +0100 Subject: [PATCH 1/8] Apply some CIS Apache Tomcat benchmark recommendations --- Dockerfile | 49 +++++++----- config/context.xml | 2 +- config/server.xml | 187 +++++++++++++++++++++++++++++++++++++++++++++ startup.sh | 11 ++- 4 files changed, 230 insertions(+), 19 deletions(-) create mode 100644 config/server.xml diff --git a/Dockerfile b/Dockerfile index 4bd8921..31a6fed 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,25 +30,28 @@ ENV CATALINA_OPTS="\$EXTRA_JAVA_OPTS \ # init RUN apt update \ -&& apt -y upgrade \ -&& apt install -y --no-install-recommends openssl unzip gdal-bin wget curl openjdk-11-jdk gettext \ -&& apt clean \ -&& rm -rf /var/cache/apt/* \ -&& rm -rf /var/lib/apt/lists/* + && apt -y upgrade \ + && apt install -y --no-install-recommends openssl unzip gdal-bin wget curl openjdk-11-jdk gettext \ + && apt clean \ + && rm -rf /var/cache/apt/* \ + && rm -rf /var/lib/apt/lists/* WORKDIR /opt/ RUN wget -q https://archive.apache.org/dist/tomcat/tomcat-9/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz \ -&& tar xf apache-tomcat-${TOMCAT_VERSION}.tar.gz \ -&& rm apache-tomcat-${TOMCAT_VERSION}.tar.gz \ -&& rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/ROOT \ -&& rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/docs \ -&& rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/examples + && tar xf apache-tomcat-${TOMCAT_VERSION}.tar.gz \ + && rm apache-tomcat-${TOMCAT_VERSION}.tar.gz \ + && rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/ROOT \ + && rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/docs \ + && rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/examples \ + && rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/host-manager \ + && rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/manager # cleanup RUN apt purge -y \ -&& apt autoremove --purge -y \ -&& rm -rf /tmp/* + && apt autoremove --purge -y \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/* FROM tomcat as download @@ -61,10 +64,10 @@ ENV GEOSERVER_BUILD=$GS_BUILD WORKDIR /tmp RUN echo "Downloading GeoServer ${GS_VERSION} ${GS_BUILD}" \ -&& wget -q -O /tmp/geoserver.zip $WAR_ZIP_URL \ -&& unzip geoserver.zip geoserver.war -d /tmp/ \ -&& unzip -q /tmp/geoserver.war -d /tmp/geoserver \ -&& rm /tmp/geoserver.war + && wget -q -O /tmp/geoserver.zip $WAR_ZIP_URL \ + && unzip geoserver.zip geoserver.war -d /tmp/ \ + && unzip -q /tmp/geoserver.war -d /tmp/geoserver \ + && rm /tmp/geoserver.war FROM tomcat as install @@ -117,7 +120,19 @@ COPY $ADDITIONAL_FONTS_PATH /usr/share/fonts/truetype/ RUN rm -rf /tmp/* # Add default configs -ADD config $CONFIG_DIR +COPY config $CONFIG_DIR + +COPY config/server.xml $CATALINA_HOME/conf/server.xml + +# Apply CIS Apache tomcat recommendations regarding server information +# * Alter the advertised server.info String (2.1 - 2.3) +RUN cd $CATALINA_HOME/lib \ + && jar xf catalina.jar org/apache/catalina/util/ServerInfo.properties \ + && sed -i 's/Apache Tomcat\/'"${TOMCAT_VERSION}"'/i_am_a_teapot/g' org/apache/catalina/util/ServerInfo.properties \ + && sed -i 's/'"${TOMCAT_VERSION}"'/x.y.z/g' org/apache/catalina/util/ServerInfo.properties \ + && sed -i 's/^server.built=.*/server.built=/g' org/apache/catalina/util/ServerInfo.properties \ + && jar uf catalina.jar org/apache/catalina/util/ServerInfo.properties \ + && rm -rf org/apache/catalina/util/ServerInfo.properties # copy scripts COPY *.sh /opt/ diff --git a/config/context.xml b/config/context.xml index c38276b..157fb73 100644 --- a/config/context.xml +++ b/config/context.xml @@ -17,4 +17,4 @@ validationQuery="SELECT 1" rollbackOnReturn="true" /> - \ No newline at end of file + diff --git a/config/server.xml b/config/server.xml new file mode 100644 index 0000000..5ade9f9 --- /dev/null +++ b/config/server.xml @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/startup.sh b/startup.sh index 9195d26..d148115 100755 --- a/startup.sh +++ b/startup.sh @@ -112,4 +112,13 @@ if [ "${POSTGRES_JNDI_ENABLED}" = "true" ]; then fi # start the tomcat -exec $CATALINA_HOME/bin/catalina.sh run +# CIS - Tomcat Benchmark recommendations: +# * Turn off session facade recycling +# * Set a nondeterministic Shutdown command value +if [ ! "${ENABLE_DEFAULT_SHUTDOWN}" = "true" ]; then + REPLACEMENT="$(echo $RANDOM | md5sum | head -c 10)" + sed -i 's/SHUTDOWN/'"$REPLACEMENT"'/g' "$CATALINA_HOME/conf/server.xml" + REPLACEMENT= +fi + +exec $CATALINA_HOME/bin/catalina.sh run -Dorg.apache.catalina.connector.RECYCLE_FACADES=true From b108b4be0662d3d4bad4bd038756184841d4fd11 Mon Sep 17 00:00:00 2001 From: Andre Henn Date: Tue, 12 Dec 2023 14:28:16 +0100 Subject: [PATCH 2/8] introduce geoserver user as docker user --- Dockerfile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 31a6fed..8a91cb1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -136,7 +136,17 @@ RUN cd $CATALINA_HOME/lib \ # copy scripts COPY *.sh /opt/ -RUN chmod +x /opt/*.sh +# GeoServer user => restrict access to $CATALINA_HOME and GeoServer directories +# See also CIS Docker benchmark and docker best practices +RUN chmod +x /opt/*.sh \ + && groupadd geoserver \ + && useradd --no-log-init -r -g geoserver geoserver \ + && chown -R geoserver:geoserver $CATALINA_HOME \ + && chmod g-w,o-rwx $CATALINA_HOME \ + && chown -R geoserver:geoserver $GEOSERVER_DATA_DIR \ + && chown -R geoserver:geoserver $GEOSERVER_LIB_DIR + +USER geoserver ENTRYPOINT ["/opt/startup.sh"] From 626b4775ba99bb90ce2c9a6318d6d7cabd433e91 Mon Sep 17 00:00:00 2001 From: Andre Henn Date: Tue, 12 Dec 2023 14:42:59 +0100 Subject: [PATCH 3/8] Remove setuid and setgid permissions in the images to prevent privilege escalation attacks within containers --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index 8a91cb1..a17538a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -136,6 +136,10 @@ RUN cd $CATALINA_HOME/lib \ # copy scripts COPY *.sh /opt/ + +# CIS Docker benchmark: Remove setuid and setgid permissions in the images to prevent privilege escalation attacks within containers. +RUN find / -perm /6000 -type f -exec chmod a-s {} \; || true + # GeoServer user => restrict access to $CATALINA_HOME and GeoServer directories # See also CIS Docker benchmark and docker best practices RUN chmod +x /opt/*.sh \ From 733dde3e77e1673f8d402baa27570a4e2a59f1d6 Mon Sep 17 00:00:00 2001 From: Andre Henn Date: Wed, 7 Feb 2024 12:44:37 +0100 Subject: [PATCH 4/8] fix: set user id of geoserver user to 2000 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a17538a..73f4bcd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -144,7 +144,7 @@ RUN find / -perm /6000 -type f -exec chmod a-s {} \; || true # See also CIS Docker benchmark and docker best practices RUN chmod +x /opt/*.sh \ && groupadd geoserver \ - && useradd --no-log-init -r -g geoserver geoserver \ + && useradd --no-log-init -u 2000 -r -g geoserver geoserver \ && chown -R geoserver:geoserver $CATALINA_HOME \ && chmod g-w,o-rwx $CATALINA_HOME \ && chown -R geoserver:geoserver $GEOSERVER_DATA_DIR \ From 9ff2eb405e170cc15d9328f9c2f2145abadaae44 Mon Sep 17 00:00:00 2001 From: Andre Henn Date: Wed, 7 Feb 2024 12:59:21 +0100 Subject: [PATCH 5/8] adds documentation for usage of custom server.xml --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 00fb04a..c846993 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,14 @@ The following values cannot really be safely changed (as they are used to downlo | GEOSERVER_VERSION | Geoserver version (used internally) | `2.24-SNAPSHOT`| | GEOSERVER_BUILD | Geosever build (used internally) | `1628` | +## Custom `server.xml` +The `server.xml` file in GeoServer docker image (originally located in `config/`) contains some specific configurations regarding security hardening. +In order to include custom configurations you can either overwrite this in build phase or mount a custom server xml to `$CATALINA_HOME/conf/server.xml` e.g. by using +```shell +docker run -it -p 80:8080 \ + --mount src="/path/to/my/server.xml",target=/opt/apache-tomcat-9.0.83/conf/server.xml,type=bind \ + docker.osgeo.org/geoserver:2.24.1 +``` ## Troubleshooting From 4a687441138218eafbdcbc3fe8863610267e8110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20B=C3=BChner?= Date: Wed, 7 Feb 2024 14:29:46 +0100 Subject: [PATCH 6/8] feat: allow use of custom server.xml --- Dockerfile | 2 -- startup.sh | 10 ++++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 73f4bcd..029493c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -122,8 +122,6 @@ RUN rm -rf /tmp/* # Add default configs COPY config $CONFIG_DIR -COPY config/server.xml $CATALINA_HOME/conf/server.xml - # Apply CIS Apache tomcat recommendations regarding server information # * Alter the advertised server.info String (2.1 - 2.3) RUN cd $CATALINA_HOME/lib \ diff --git a/startup.sh b/startup.sh index d148115..79f951b 100755 --- a/startup.sh +++ b/startup.sh @@ -111,6 +111,16 @@ if [ "${POSTGRES_JNDI_ENABLED}" = "true" ]; then fi fi +# Use a custom "server.xml" if the user mounted one into the container +if [ -d "${CONFIG_OVERRIDES_DIR}" ] && [ -f "${CONFIG_OVERRIDES_DIR}/server.xml" ]; then + echo "Installing configuration override for server.xml with substituted environment variables" + envsubst < "${CONFIG_OVERRIDES_DIR}"/server.xml > "${CATALINA_HOME}/conf/server.xml" +else + # Otherwise use the default + echo "Installing default server.xml with substituted environment variables" + envsubst < "${CONFIG_DIR}"/server.xml > "${CATALINA_HOME}/conf/server.xml" +fi + # start the tomcat # CIS - Tomcat Benchmark recommendations: # * Turn off session facade recycling From 09f1dfec0c1f10ccf9fded264f6e93003179278d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20B=C3=BChner?= Date: Wed, 7 Feb 2024 14:49:03 +0100 Subject: [PATCH 7/8] refactor: use function to avoid duplicate code --- startup.sh | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/startup.sh b/startup.sh index 79f951b..182e9c0 100755 --- a/startup.sh +++ b/startup.sh @@ -1,6 +1,20 @@ -#!/bin/sh +#!/bin/bash echo "Welcome to GeoServer $GEOSERVER_VERSION" +# function that can be used to copy a custom config file to the catalina conf dir +function copy_custom_config() { + CONFIG_FILE=$1 + # Use a custom "${CONFIG_FILE}" if the user mounted one into the container + if [ -d "${CONFIG_OVERRIDES_DIR}" ] && [ -f "${CONFIG_OVERRIDES_DIR}/${CONFIG_FILE}" ]; then + echo "Installing configuration override for ${CONFIG_FILE} with substituted environment variables" + envsubst < "${CONFIG_OVERRIDES_DIR}"/"${CONFIG_FILE}" > "${CATALINA_HOME}/conf/${CONFIG_FILE}" + else + # Otherwise use the default + echo "Installing default ${CONFIG_FILE} with substituted environment variables" + envsubst < "${CONFIG_DIR}"/"${CONFIG_FILE}" > "${CATALINA_HOME}/conf/${CONFIG_FILE}" + fi +} + ## Skip demo data if [ "${SKIP_DEMO_DATA}" = "true" ]; then unset GEOSERVER_REQUIRE_FILE @@ -101,25 +115,11 @@ if [ "${POSTGRES_JNDI_ENABLED}" = "true" ]; then fi # Use a custom "context.xml" if the user mounted one into the container - if [ -d "${CONFIG_OVERRIDES_DIR}" ] && [ -f "${CONFIG_OVERRIDES_DIR}/context.xml" ]; then - echo "Installing configuration override for context.xml with substituted environment variables" - envsubst < "${CONFIG_OVERRIDES_DIR}"/context.xml > "${CATALINA_HOME}/conf/context.xml" - else - # Otherwise use the default - echo "Installing default context.xml with substituted environment variables" - envsubst < "${CONFIG_DIR}"/context.xml > "${CATALINA_HOME}/conf/context.xml" - fi + copy_custom_config context.xml fi # Use a custom "server.xml" if the user mounted one into the container -if [ -d "${CONFIG_OVERRIDES_DIR}" ] && [ -f "${CONFIG_OVERRIDES_DIR}/server.xml" ]; then - echo "Installing configuration override for server.xml with substituted environment variables" - envsubst < "${CONFIG_OVERRIDES_DIR}"/server.xml > "${CATALINA_HOME}/conf/server.xml" -else - # Otherwise use the default - echo "Installing default server.xml with substituted environment variables" - envsubst < "${CONFIG_DIR}"/server.xml > "${CATALINA_HOME}/conf/server.xml" -fi +copy_custom_config server.xml # start the tomcat # CIS - Tomcat Benchmark recommendations: From 2490a96a8cbf0ece3b4f17a16242c04b0c2e6145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20B=C3=BChner?= Date: Wed, 7 Feb 2024 15:04:19 +0100 Subject: [PATCH 8/8] docs: update readme regarding config overwrite --- README.md | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c846993..ed38aa5 100644 --- a/README.md +++ b/README.md @@ -144,8 +144,23 @@ To enable a PostgreSQL JNDI resource, provide the following environment variable In geoserver, you can then reference this JNDI resource using the name `java:comp/env/jdbc/postgres` (if using default). -For advanced customization of the connection pool, you can provide your own customized "context.xml" -file to Apache Tomcat by mounting it to the container at ``/opt/config_overrides/context.xml``. +## How to use custom (tomcat) configuration files + +This image provides default (tomcat) configurations that are located in the `./config/` subdir. + +* `context.xml` (see/compare JNDI feature from above) +* `server.xml` (security hardened version by default) + +In case you want to fully overwrite such a config file, you can do so by mounting it to the `/opt/config_overrides/` directory of a container. +The `startup.sh` script will then copy (and overwrite) these files to the catalina conf directory before starting tomcat. + +Example: + +```shell +docker run -it -p 80:8080 \ + --mount src="/path/to/my/server.xml",target=/opt/config_overrides/server.xml,type=bind \ + docker.osgeo.org/geoserver:2.24.1 +``` ## How to use the docker-compose demo? @@ -191,15 +206,6 @@ The following values cannot really be safely changed (as they are used to downlo | GEOSERVER_VERSION | Geoserver version (used internally) | `2.24-SNAPSHOT`| | GEOSERVER_BUILD | Geosever build (used internally) | `1628` | -## Custom `server.xml` -The `server.xml` file in GeoServer docker image (originally located in `config/`) contains some specific configurations regarding security hardening. -In order to include custom configurations you can either overwrite this in build phase or mount a custom server xml to `$CATALINA_HOME/conf/server.xml` e.g. by using -```shell -docker run -it -p 80:8080 \ - --mount src="/path/to/my/server.xml",target=/opt/apache-tomcat-9.0.83/conf/server.xml,type=bind \ - docker.osgeo.org/geoserver:2.24.1 -``` - ## Troubleshooting ### How to watch geoserver.log from host?