diff --git a/Dockerfile b/Dockerfile index e41e0d1..50cb2b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,25 +31,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 @@ -62,10 +65,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 @@ -119,11 +122,35 @@ COPY $ADDITIONAL_FONTS_PATH /usr/share/fonts/truetype/ RUN rm -rf /tmp/* # Add default configs -ADD config $CONFIG_DIR +COPY config $CONFIG_DIR + +# 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/ -RUN chmod +x /opt/*.sh + +# 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 \ + && groupadd 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 \ + && chown -R geoserver:geoserver $GEOSERVER_LIB_DIR + +USER geoserver ENTRYPOINT ["/opt/startup.sh"] diff --git a/README.md b/README.md index 8c17d2c..01a809e 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? @@ -192,7 +207,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` | - ## Troubleshooting ### How to watch geoserver.log from host? 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 99d7874..8bbaeeb 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 @@ -100,15 +114,20 @@ 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 +copy_custom_config server.xml + # 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