diff --git a/images/qgis-server/Dockerfile b/images/qgis-server/Dockerfile new file mode 100644 index 0000000..3c71009 --- /dev/null +++ b/images/qgis-server/Dockerfile @@ -0,0 +1,52 @@ +FROM debian:bookworm-slim + +ENV LANG=en_EN.UTF-8 + +ENV TINI_VERSION v0.19.0 + +RUN apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + gnupg \ + ca-certificates \ + wget \ + locales \ + crudini \ + && localedef -i en_US -f UTF-8 en_US.UTF-8 \ + # Add the current key for package downloading + # Please refer to QGIS install documentation (https://www.qgis.org/fr/site/forusers/alldownloads.html#debian-ubuntu) + && mkdir -m755 -p /etc/apt/keyrings \ + && wget -O /etc/apt/keyrings/qgis-archive-keyring.gpg https://download.qgis.org/downloads/qgis-archive-keyring.gpg \ + # Add repository for latest version of qgis-server + # Please refer to QGIS repositories documentation if you want other version (https://qgis.org/en/site/forusers/alldownloads.html#repositories) + && echo "deb [signed-by=/etc/apt/keyrings/qgis-archive-keyring.gpg] https://qgis.org/debian bookworm main" | tee /etc/apt/sources.list.d/qgis.list \ + && apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + qgis-server \ + spawn-fcgi \ + xauth \ + xvfb \ + && wget -O /tini https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini \ + && chmod +x /tini \ + && apt-get remove --purge -y \ + gnupg \ + wget \ + && rm -rf /var/lib/apt/lists/* + +RUN useradd -m qgis + +ENV QGIS_PREFIX_PATH /usr +ENV QGIS_SERVER_LOG_STDERR 1 +ENV QGIS_SERVER_LOG_LEVEL 2 +ENV QGIS_PLUGINPATH /plugins + +COPY validmap/ /plugins/validmap/ + +COPY cmd.sh /home/qgis/cmd.sh +RUN mkdir /etc/postgresql-common/ && chmod 777 /etc/postgresql-common/ + +USER qgis +WORKDIR /home/qgis + +ENTRYPOINT ["/tini", "--"] + +CMD ["/home/qgis/cmd.sh"] diff --git a/images/qgis-server/cmd.sh b/images/qgis-server/cmd.sh new file mode 100755 index 0000000..11457e0 --- /dev/null +++ b/images/qgis-server/cmd.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -eu -o pipefail + +# distribution-specific +PGSERVICE_FILE=/etc/postgresql-common/pg_service.conf + +# simple configuration / built-in database +for i in host user password dbname +do + envvar=MAIN_SERVICE_${i^^} + crudini --set $PGSERVICE_FILE main-service $i "${!envvar}" +done + +# overrides / further services +for var in VALUES SECRET +do + envvar=PGSERVICE_$var + if [[ -v $envvar ]] + then + crudini --merge $PGSERVICE_FILE <<<${!envvar} + fi +done + +# until https://github.com/pixelb/crudini/commit/65ace170964aa75f36bfeb18cadd995dcd332622 is available +sed 's/ = /=/' -i $PGSERVICE_FILE + +exec /usr/bin/xvfb-run --auto-servernum --server-num=1 /usr/bin/spawn-fcgi -p 5555 -n -d /home/qgis -- /usr/lib/cgi-bin/qgis_mapserv.fcgi diff --git a/images/qgis-server/validmap/__init__.py b/images/qgis-server/validmap/__init__.py new file mode 100644 index 0000000..1cea02f --- /dev/null +++ b/images/qgis-server/validmap/__init__.py @@ -0,0 +1,33 @@ +from qgis.server import QgsServerFilter +import re +import os + +PARAMETER = "MAP" +SUFFIX = ".qgs" +VALID_PATTERN = r"[-_a-z0-9]+" + +PREFIX = os.environ.get("PROJECT_PREFIX", "") + + +class ValidmapFilter(QgsServerFilter): + def __init__(self, serverIface): + super().__init__(serverIface) + serverIface.registerFilter(self, 100) + + def onRequestReady(self) -> bool: + req = self.serverInterface().requestHandler() + project_file = req.parameterMap().get(PARAMETER, "") + + if re.fullmatch(VALID_PATTERN, project_file): + # use good value with prefix and suffix + req.setParameter(PARAMETER, + f"{PREFIX}{project_file}/{project_file}{SUFFIX}") + else: + # reject bad value by removing it + req.removeParameter(PARAMETER) + + return True + + +def serverClassFactory(serverIface): + return ValidmapFilter(serverIface) diff --git a/images/qgis-server/validmap/metadata.txt b/images/qgis-server/validmap/metadata.txt new file mode 100644 index 0000000..c28574f --- /dev/null +++ b/images/qgis-server/validmap/metadata.txt @@ -0,0 +1,10 @@ +[general] +name=validmap +server=True +description=Ensure that the MAP parameter is restricted to safe values. +about=This QGIS server plugin ensures that the MAP=... parameter always matches `[-_a-z0-9]+`, suffixes it with `.qgs` and prefixes it with PROJECT_PREFIX and the value itself as a directory name. Invalid values are removed to mitigate malicious requests. +repository=https://gitlab.com/urban-data-hub/gdi +qgisMinimumVersion=3 +version=0.0.1 +author=git +email=git@example.com