From 8cedbaa67998c57ca79875325f4d07bc67cf2777 Mon Sep 17 00:00:00 2001 From: Diego Lendoiro Date: Mon, 25 Jan 2021 17:55:23 +0000 Subject: [PATCH] Changed: fix SSL nginx configs * variable renaming on entrypoint * php version --- .gitlab-ci.yml | 13 ++++ .gitlab-ci/Jobs/build_image.yml | 30 ++++++++ .gitlab-ci/Jobs/container_security_scan.yml | 59 ++++++++++++++++ bin/docker-entrypoint.sh | 77 ++++++++++++++++----- conf/supervisor/php.conf | 2 +- debian/Dockerfile | 39 +++++++++++ Dockerfile => dev/Dockerfile | 0 docker-compose.yml | 8 +-- 8 files changed, 205 insertions(+), 23 deletions(-) create mode 100644 .gitlab-ci.yml create mode 100644 .gitlab-ci/Jobs/build_image.yml create mode 100644 .gitlab-ci/Jobs/container_security_scan.yml create mode 100644 debian/Dockerfile rename Dockerfile => dev/Dockerfile (100%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..716a2a5 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,13 @@ +image: alpine:latest + +variables: + DOCKER_DRIVER: overlay2 + DOCKER_HOST: tcp://localhost:2375/ + +stages: + - build + - test + +include: + - local: '/.gitlab-ci/Jobs/build_image.yml' + - local: '/.gitlab-ci/Jobs/container_security_scan.yml' diff --git a/.gitlab-ci/Jobs/build_image.yml b/.gitlab-ci/Jobs/build_image.yml new file mode 100644 index 0000000..6af2da0 --- /dev/null +++ b/.gitlab-ci/Jobs/build_image.yml @@ -0,0 +1,30 @@ +.passbolt-prerelease: + stage: build + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + - | + echo "********************************************" + echo "Build details" + echo "============================================" + echo "Flavour ${PASSBOLT_FLAVOUR:-local}" + echo "Commit ${UPSTREAM_COMMIT_SHA:-latest}" + echo "********************************************" + - | + /kaniko/executor --context $CI_PROJECT_DIR \ + --build-arg PASSBOLT_PKG="passbolt-$PASSBOLT_FLAVOUR-server" \ + --build-arg PASSBOLT_REPO_URL="https://download.passbolt.com/$PASSBOLT_FLAVOUR/debian" \ + --build-arg PASSBOLT_COMPONENT="$COMPONENT" \ + --dockerfile $CI_PROJECT_DIR/debian/Dockerfile \ + --destination $CI_REGISTRY_IMAGE:${PASSBOLT_FLAVOUR:-local}-$(date +%s) + +prerelease-pro: + extends: .passbolt-prerelease + variables: + PASSBOLT_URL: "https://gitlab.com/api/v4/projects/$UPSTREAM_PROJECT_ID/repository/archive.tar.gz?sha=$UPSTREAM_COMMIT_SHA" + PASSBOLT_CURL_HEADERS: "PRIVATE-TOKEN: $PRIVATE_TOKEN" + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_BRANCH == "develop"' + when: on_success diff --git a/.gitlab-ci/Jobs/container_security_scan.yml b/.gitlab-ci/Jobs/container_security_scan.yml new file mode 100644 index 0000000..00afead --- /dev/null +++ b/.gitlab-ci/Jobs/container_security_scan.yml @@ -0,0 +1,59 @@ +# Read more about this feature here: https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html + +container_scanning: + stage: test + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + # Defining two new variables based on GitLab's CI/CD predefined variables + # https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables + CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE + # Prior to this, you need to have the Container Registry running for your project and setup a build job + # with at least the following steps: + # + # docker build -t $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG . + # docker push $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + # + # Container Scanning deals with Docker images only so no need to import the project's Git repository: + GIT_STRATEGY: none + # Services and containers running in the same Kubernetes pod are all sharing the same localhost address + # https://docs.gitlab.com/runner/executors/kubernetes.html + DOCKER_SERVICE: localhost + DOCKER_HOST: tcp://${DOCKER_SERVICE}:2375/ + # https://hub.docker.com/r/arminc/clair-local-scan/tags + CLAIR_LOCAL_SCAN_VERSION: v2.0.8_fe9b059d930314b54c78f75afe265955faf4fdc1 + allow_failure: true + services: + - docker:18-dind + script: + - export CI_APPLICATION_TAG=${PASSBOLT_FLAVOUR:-local}-${UPSTREAM_COMMIT_SHA:-latest} + - echo "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" + - if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then { export DOCKER_SERVICE="localhost" ; export DOCKER_HOST="tcp://${DOCKER_SERVICE}:2375" ; } fi + - | + if [[ -n "$CI_REGISTRY_USER" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY" + echo "" + fi + - docker run -d --name db arminc/clair-db:latest + - docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:${CLAIR_LOCAL_SCAN_VERSION} + - apk add -U wget ca-certificates + - docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} + - wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64 + - mv clair-scanner_linux_amd64 clair-scanner + - chmod +x clair-scanner + - touch clair-whitelist.yml + - retries=0 + - echo "Waiting for clair daemon to start" + - while( ! wget -T 10 -q -O /dev/null http://${DOCKER_SERVICE}:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done + - ./clair-scanner -c http://${DOCKER_SERVICE}:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml -t Medium ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true + artifacts: + reports: + container_scanning: gl-container-scanning-report.json + dependencies: [] + only: + refs: + - branches + except: + variables: + - $CONTAINER_SCANNING_DISABLED diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index 7bcef9c..872c290 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -1,14 +1,17 @@ #!/usr/bin/env bash -set -euo pipefail +set -eo pipefail -gpg_private_key="${PASSBOLT_GPG_SERVER_KEY_PRIVATE:-/var/www/passbolt/config/gpg/serverkey_private.asc}" -gpg_public_key="${PASSBOLT_GPG_SERVER_KEY_PUBLIC:-/var/www/passbolt/config/gpg/serverkey.asc}" +passbolt_config="/etc/passbolt" +gpg_private_key="${PASSBOLT_GPG_SERVER_KEY_PRIVATE:-$passbolt_config/gpg/serverkey_private.asc}" +gpg_public_key="${PASSBOLT_GPG_SERVER_KEY_PUBLIC:-$passbolt_config/gpg/serverkey.asc}" ssl_key='/etc/ssl/certs/certificate.key' ssl_cert='/etc/ssl/certs/certificate.crt' -export GNUPGHOME="/home/www-data/.gnupg" +deprecation_message="" + +export GNUPGHOME="/var/lib/passbolt/.gnupg" entropy_check() { local entropy_avail @@ -42,7 +45,7 @@ gpg_gen_key() { entropy_check - su -c "gpg --batch --no-tty --gen-key < $gpg_private_key" -ls /bin/bash www-data - su -c "gpg --armor --export $key_email > $gpg_public_key" -ls /bin/bash www-data + su -c "gpg --homedir $GNUPGHOME --armor --export-secret-keys $key_email > $gpg_private_key" -ls /bin/bash www-data + su -c "gpg --homedir $GNUPGHOME --armor --export $key_email > $gpg_public_key" -ls /bin/bash www-data } gpg_import_key() { - su -c "gpg --batch --import $gpg_public_key" -ls /bin/bash www-data - su -c "gpg --batch --import $gpg_private_key" -ls /bin/bash www-data + su -c "gpg --homedir $GNUPGHOME --batch --import $gpg_public_key" -ls /bin/bash www-data + su -c "gpg --homedir $GNUPGHOME --batch --import $gpg_private_key" -ls /bin/bash www-data } gen_ssl_cert() { @@ -70,18 +73,17 @@ gen_ssl_cert() { } install() { - local app_config="/var/www/passbolt/config/app.php" - if [ ! -f "$app_config" ]; then - su -c 'cp /var/www/passbolt/config/app.default.php /var/www/passbolt/config/app.php' -s /bin/bash www-data + if [ ! -f "$passbolt_config/app.php" ]; then + su -c "cp $passbolt_config/app.default.php $passbolt_config/app.php" -s /bin/bash www-data fi - if [ -z "${PASSBOLT_GPG_SERVER_KEY_FINGERPRINT+xxx}" ] && [ ! -f '/var/www/passbolt/config/passbolt.php' ]; then - gpg_auto_fingerprint="$(su -c "gpg --list-keys --with-colons ${PASSBOLT_KEY_EMAIL:-passbolt@yourdomain.com} |grep fpr |head -1| cut -f10 -d:" -ls /bin/bash www-data)" + if [ -z "${PASSBOLT_GPG_SERVER_KEY_FINGERPRINT+xxx}" ] && [ ! -f "$passbolt_config/passbolt.php" ]; then + gpg_auto_fingerprint="$(su -c "gpg --homedir $GNUPGHOME --list-keys --with-colons ${PASSBOLT_KEY_EMAIL:-passbolt@yourdomain.com} |grep fpr |head -1| cut -f10 -d:" -ls /bin/bash www-data)" export PASSBOLT_GPG_SERVER_KEY_FINGERPRINT=$gpg_auto_fingerprint fi - su -c '/var/www/passbolt/bin/cake passbolt install --no-admin' -s /bin/bash www-data || su -c '/var/www/passbolt/bin/cake passbolt migrate' -s /bin/bash www-data && echo "Enjoy! ☮" + su -c '/usr/share/php/passbolt/bin/cake passbolt install --no-admin' -s /bin/bash www-data || su -c '/usr/share/php/passbolt/bin/cake passbolt migrate' -s /bin/bash www-data && echo "Enjoy! ☮" } email_cron_job() { @@ -93,8 +95,47 @@ email_cron_job() { fi } -if [ ! -f "$gpg_private_key" ] && [ ! -L "$gpg_private_key" ] || \ - [ ! -f "$gpg_public_key" ] && [ ! -L "$gpg_public_key" ]; then +create_deprecation_message() { + deprecation_message+="\033[33;5;7mWARNING: $1 is deprecated, point your docker volume to $2\033[0m\n" +} + +check_deprecated_paths() { + declare -A deprecated_paths + local deprecated_avatar_path="/var/www/passbolt/webroot/img/public/Avatar" + local avatar_path="/usr/share/php/passbolt/webroot/img/public/Avatar" + local deprecated_subscription_path="/var/www/passbolt/webroot/img/public/Avatar" + local subscription_path="/etc/passbolt/license" + deprecated_paths=( + ['/var/www/passbolt/config/gpg/serverkey.asc']='/etc/passbolt/gpg/serverkey.asc' + ['/var/www/passbolt/config/gpg/serverkey_private.asc']='/etc/passbolt/gpg/serverkey_private.asc' + ) + + if [ -z "$PASSBOLT_GPG_SERVER_KEY_PUBLIC" ] || [ -z "$PASSBOLT_GPG_SERVER_KEY_PRIVATE" ]; then + for path in "${!deprecated_paths[@]}" + do + echo "VOLTA" + if [ -f "$path" ] && [ ! -f "${deprecated_paths[$path]}" ]; then + ln -s "$path" "${deprecated_paths[$path]}" + create_deprecation_message "$path" "${deprecated_paths[$path]}" + fi + done + fi + + if [ -d "$deprecated_avatar_path" ] && [ ! -d "$avatar_path" ]; then + ln -s "$deprecated_avatar_path" "$avatar_path" + create_deprecation_message "$deprecated_avatar_path" "$avatar_path" + fi + + if [ -f "$deprecated_subscription_path" ] && [ ! -f "$subscription_path" ]; then + ln -s "$deprecated_subscription_path" "$subscription_path" + create_deprecation_message "$deprecated_subscription_path" "$subscription_path" + fi +} + +check_deprecated_paths + +if [ ! -f "$gpg_private_key" ] || \ + [ ! -f "$gpg_public_key" ]; then gpg_gen_key gpg_import_key else @@ -109,4 +150,6 @@ fi install email_cron_job +echo -e "$deprecation_message" + exec /usr/bin/supervisord -n diff --git a/conf/supervisor/php.conf b/conf/supervisor/php.conf index c008c6b..a98b80c 100644 --- a/conf/supervisor/php.conf +++ b/conf/supervisor/php.conf @@ -1,5 +1,5 @@ [program:php-fpm] -command=php-fpm -F +command=php-fpm7.3 -F autostart=true priority=5 stdout_logfile=/dev/stdout diff --git a/debian/Dockerfile b/debian/Dockerfile new file mode 100644 index 0000000..38fe0aa --- /dev/null +++ b/debian/Dockerfile @@ -0,0 +1,39 @@ +FROM debian:buster-slim + +LABEL maintainer="Passbolt SA " + +ENV PASSBOLT_PKG_KEY=0xDE8B853FC155581D +ENV PASSBOLT_PKG=passbolt-ce-server +ENV PHP_VERSION=7.3 + +ARG PASSBOLT_REPO_URL="https://download.passbolt.com/ce/debian" +ARG PASSBOLT_DISTRO="buster" +ARG PASSBOLT_COMPONENT="stable" + +RUN apt-get update \ + && DEBIAN_FRONTEND=non-interactive apt-get -y install \ + ca-certificates \ + gnupg \ + && apt-key adv --keyserver keys.gnupg.net --recv-keys $PASSBOLT_PKG_KEY \ + && echo "deb $PASSBOLT_REPO_URL $PASSBOLT_DISTRO $PASSBOLT_COMPONENT" > /etc/apt/sources.list.d/passbolt.list \ + && apt-get update \ + && DEBIAN_FRONTEND=non-interactive apt-get -y install --no-install-recommends \ + nginx \ + $PASSBOLT_PKG \ + supervisor \ + && rm /etc/nginx/sites-enabled/default \ + && mkdir /run/php \ + && cp /usr/share/passbolt/examples/nginx-passbolt-ssl.conf /etc/nginx/snippets/passbolt-ssl.conf \ + && sed -i 's,;clear_env = no,clear_env = no,' /etc/php/$PHP_VERSION/fpm/pool.d/www.conf \ + && sed -i 's,# include __PASSBOLT_SSL__,include /etc/nginx/snippets/passbolt-ssl.conf;,' /etc/nginx/sites-enabled/nginx-passbolt.conf \ + && sed -i 's,ssl on;,listen 443 ssl;,' /etc/nginx/snippets/passbolt-ssl.conf \ + && sed -i 's,__CERT_PATH__,/etc/ssl/certs/certificate.crt;,' /etc/nginx/snippets/passbolt-ssl.conf \ + && sed -i 's,__KEY_PATH__,/etc/ssl/certs/certificate.key;,' /etc/nginx/snippets/passbolt-ssl.conf + +COPY conf/supervisor/*.conf /etc/supervisor/conf.d/ +COPY bin/docker-entrypoint.sh /docker-entrypoint.sh +COPY scripts/wait-for.sh /usr/bin/wait-for.sh + +EXPOSE 80 443 + +CMD ["/docker-entrypoint.sh"] diff --git a/Dockerfile b/dev/Dockerfile similarity index 100% rename from Dockerfile rename to dev/Dockerfile diff --git a/docker-compose.yml b/docker-compose.yml index b735821..868cce8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,17 +10,15 @@ services: - "127.0.0.1:3306:3306" passbolt: - image: passbolt/passbolt:2.12.0-debian + image: localpassbolt tty: true depends_on: - db env_file: - env/passbolt.env volumes: - - gpg_volume:/var/www/passbolt/config/gpg - - images_volume:/var/www/passbolt/webroot/img/public - tmpfs: - - /run + - gpg_volume:/var/lib/passbolt/.gnupg + - images_volume:/usr/share/php/passbolt/webroot/img/public command: ["/usr/bin/wait-for.sh", "-t", "0", "db:3306", "--", "/docker-entrypoint.sh"] ports: - 80:80