Merge branch 'develop'

This commit is contained in:
Diego Lendoiro 2021-02-23 13:35:01 +01:00
commit 802c9f7c84
No known key found for this signature in database
GPG Key ID: 3808AD1A50FF0B59
22 changed files with 617 additions and 131 deletions

2
.gitignore vendored
View File

@ -32,3 +32,5 @@ conf/*.key
src src
.ruby-version .ruby-version
.bundle

13
.gitlab-ci.yml Normal file
View File

@ -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'

View File

@ -0,0 +1,64 @@
.build:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
variables:
COMPONENT: "testing"
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/$DOCKERFILE_PATH \
--destination $CI_REGISTRY_IMAGE:${PASSBOLT_FLAVOUR:-local}-${DOCKER_TAG}-$(date +%s) \
--destination $CI_REGISTRY_IMAGE:${PASSBOLT_FLAVOUR:-local}-${DOCKER_TAG}-latest
build-docker-ce:
extends: .build
variables:
DOCKERFILE_PATH: "debian/Dockerfile"
DOCKER_TAG: "root"
PASSBOLT_FLAVOUR: "ce"
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule" || $CI_COMMIT_BRANCH == "develop"'
when: on_success
build-rootless-ce:
extends: .build
variables:
DOCKERFILE_PATH: "debian/Dockerfile.rootless"
DOCKER_TAG: "rootless"
PASSBOLT_FLAVOUR: "ce"
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule" || $CI_COMMIT_BRANCH == "develop"'
when: on_success
build-docker-pro:
extends: .build
variables:
DOCKERFILE_PATH: "debian/Dockerfile"
DOCKER_TAG: "root"
PASSBOLT_FLAVOUR: "pro"
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule" || $CI_COMMIT_BRANCH == "develop"'
when: on_success
build-rootless-pro:
extends: .build
variables:
DOCKERFILE_PATH: "debian/Dockerfile.rootless"
DOCKER_TAG: "rootless"
PASSBOLT_FLAVOUR: "pro"
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule" || $CI_COMMIT_BRANCH == "develop"'
when: on_success

View File

@ -0,0 +1,61 @@
# 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/
DOCKER_TAG: rootless
# https://hub.docker.com/r/arminc/clair-local-scan/tags
CLAIR_LOCAL_SCAN_VERSION: v2.0.8_fe9b059d930314b54c78f75afe265955faf4fdc1
PASSBOLT_FLAVOUR: pro
allow_failure: true
services:
- docker:18-dind
script:
- export CI_APPLICATION_TAG=${PASSBOLT_FLAVOUR:-local}-${DOCKER_TAG}-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

View File

@ -1,45 +1,45 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
coderay (1.1.2) coderay (1.1.3)
diff-lcs (1.3) diff-lcs (1.4.4)
docker-api (1.34.2) docker-api (2.0.0)
excon (>= 0.47.0) excon (>= 0.47.0)
multi_json multi_json
excon (0.73.0) excon (0.79.0)
method_source (1.0.0) method_source (1.0.0)
multi_json (1.14.1) multi_json (1.15.0)
net-scp (2.0.0) net-scp (3.0.0)
net-ssh (>= 2.6.5, < 6.0.0) net-ssh (>= 2.6.5, < 7.0.0)
net-ssh (5.2.0) net-ssh (6.1.0)
net-telnet (0.1.1) net-telnet (0.1.1)
pry (0.13.1) pry (0.14.0)
coderay (~> 1.1) coderay (~> 1.1)
method_source (~> 1.0) method_source (~> 1.0)
rake (13.0.1) rake (13.0.3)
rspec (3.9.0) rspec (3.10.0)
rspec-core (~> 3.9.0) rspec-core (~> 3.10.0)
rspec-expectations (~> 3.9.0) rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.9.0) rspec-mocks (~> 3.10.0)
rspec-core (3.9.1) rspec-core (3.10.1)
rspec-support (~> 3.9.1) rspec-support (~> 3.10.0)
rspec-expectations (3.9.1) rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0) rspec-support (~> 3.10.0)
rspec-its (1.3.0) rspec-its (1.3.0)
rspec-core (>= 3.0.0) rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0) rspec-expectations (>= 3.0.0)
rspec-mocks (3.9.1) rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0) rspec-support (~> 3.10.0)
rspec-support (3.9.2) rspec-support (3.10.2)
serverspec (2.41.5) serverspec (2.41.5)
multi_json multi_json
rspec (~> 3.0) rspec (~> 3.0)
rspec-its rspec-its
specinfra (~> 2.72) specinfra (~> 2.72)
sfl (2.3) sfl (2.3)
specinfra (2.82.15) specinfra (2.82.23)
net-scp net-scp
net-ssh (>= 2.7) net-ssh (>= 2.7)
net-telnet (= 0.1.1) net-telnet (= 0.1.1)
@ -47,6 +47,7 @@ GEM
PLATFORMS PLATFORMS
ruby ruby
x86_64-linux
DEPENDENCIES DEPENDENCIES
docker-api docker-api
@ -55,4 +56,4 @@ DEPENDENCIES
serverspec serverspec
BUNDLED WITH BUNDLED WITH
1.17.2 2.2.6

View File

@ -1,5 +1,5 @@
[program:cron] [program:cron]
command=cron -f -l command=/usr/local/bin/supercronic /etc/cron.d/passbolt-ce-server
autostart=true autostart=true
priority=20 priority=20
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout

View File

@ -1,5 +1,5 @@
[program:php-fpm] [program:php-fpm]
command=php-fpm -F command=php-fpm7.3 -F
autostart=true autostart=true
priority=5 priority=5
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout

50
debian/Dockerfile vendored Normal file
View File

@ -0,0 +1,50 @@
FROM debian:buster-slim
LABEL maintainer="Passbolt SA <contact@passbolt.com>"
ENV PASSBOLT_PKG_KEY=0xDE8B853FC155581D
ENV PHP_VERSION=7.3
ENV GNUPGHOME=/var/lib/passbolt/.gnupg
ARG PASSBOLT_REPO_URL="https://download.passbolt.com/ce/debian"
ARG PASSBOLT_DISTRO="buster"
ARG PASSBOLT_COMPONENT="stable"
ARG PASSBOLT_PKG=passbolt-ce-server
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 \
curl \
&& 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 '/listen \[\:\:\]\:443 ssl http2;/a listen 443 ssl http2;' /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 \
&& sed -i 's,www-data.*$,www-data exec /bin/bash -c ". /etc/environment \&\& $PASSBOLT_BASE_DIR/bin/cron",' /etc/cron.d/$PASSBOLT_PKG \
&& sed -i 's/# server_tokens/server_tokens/' /etc/nginx/nginx.conf \
&& ln -sf /dev/stdout /var/log/nginx/passbolt-access.log \
&& ln -sf /dev/stderr /var/log/nginx/passbolt-error.log \
&& ln -sf /dev/stderr /var/log/passbolt/error.log \
&& ln -sf /dev/stderr /var/log/php7.3-fpm.log \
&& crontab /etc/cron.d/$PASSBOLT_PKG
COPY conf/supervisor/*.conf /etc/supervisor/conf.d/
COPY debian/bin/docker-entrypoint.sh /docker-entrypoint.sh
COPY scripts/wait-for.sh /usr/bin/wait-for.sh
EXPOSE 80 443
WORKDIR /usr/share/php/passbolt
CMD ["/docker-entrypoint.sh"]

81
debian/Dockerfile.rootless vendored Normal file
View File

@ -0,0 +1,81 @@
FROM debian:buster-slim
LABEL maintainer="Passbolt SA <contact@passbolt.com>"
ARG SUPERCRONIC_ARCH=amd64
ARG PASSBOLT_REPO_URL="https://download.passbolt.com/ce/debian"
ARG PASSBOLT_DISTRO="buster"
ARG PASSBOLT_COMPONENT="stable"
ARG PASSBOLT_PKG=passbolt-ce-server
ENV PASSBOLT_PKG_KEY=0xDE8B853FC155581D
ENV PHP_VERSION=7.3
ENV GNUPGHOME=/var/lib/passbolt/.gnupg
ENV SUPERCRONIC_VERSION=0.1.12
ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v${SUPERCRONIC_VERSION}/supercronic-linux-${SUPERCRONIC_ARCH} \
SUPERCRONIC=supercronic-linux-${SUPERCRONIC_ARCH} \
SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e
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 \
curl \
&& curl -fsSLO "$SUPERCRONIC_URL" \
&& echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \
&& chmod +x "$SUPERCRONIC" \
&& mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
&& ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic
RUN sed -i 's,listen 80;,listen 8080;,' /etc/nginx/sites-enabled/nginx-passbolt.conf \
&& rm /etc/nginx/sites-enabled/default \
&& 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,listen \[\:\:\]\:443 ssl http2;,listen \[\:\:\]\:4443 ssl http2;,' /etc/nginx/snippets/passbolt-ssl.conf \
&& sed -i '/listen \[\:\:\]\:4443 ssl http2;/a listen 4443 ssl http2;' /etc/nginx/snippets/passbolt-ssl.conf \
&& sed -i 's,__CERT_PATH__,/etc/passbolt/certs/certificate.crt;,' /etc/nginx/snippets/passbolt-ssl.conf \
&& sed -i 's,__KEY_PATH__,/etc/passbolt/certs/certificate.key;,' /etc/nginx/snippets/passbolt-ssl.conf \
&& sed -i '/user www-data;/d' /etc/nginx/nginx.conf \
&& sed -i 's,/run/nginx.pid,/tmp/nginx.pid,' /etc/nginx/nginx.conf \
&& sed -i "/^http {/a \ proxy_temp_path /tmp/proxy_temp;\n client_body_temp_path /tmp/client_temp;\n fastcgi_temp_path /tmp/fastcgi_temp;\n uwsgi_temp_path /tmp/uwsgi_temp;\n scgi_temp_path /tmp/scgi_temp;\n" /etc/nginx/nginx.conf \
&& sed -i 's,listen = /run/php/php7.3-fpm.sock,listen = 127.0.0.1:9000,' /etc/php/7.3/fpm/pool.d/www.conf \
&& sed -i 's,unix:/run/php/php7.3-fpm.sock,127.0.0.1:9000,' /etc/nginx/sites-enabled/nginx-passbolt.conf \
&& sed -i 's,pid = /run/php/php7.3-fpm.pid,pid = /tmp/php7.3-fpm.pid,' /etc/php/7.3/fpm/php-fpm.conf \
&& sed -i 's,/var/run/supervisor.sock,/tmp/supervisor.sock,' /etc/supervisor/supervisord.conf \
# nginx user must own the cache and etc directory to write cache and tweak the nginx config
#&& chown -R www-data:0 /var/cache/nginx \
#&& chmod -R g+w /var/cache/nginx \
&& chown -R www-data:0 /etc/nginx \
&& chmod -R g+w /etc/nginx \
&& mkdir /etc/passbolt/certs \
&& chown www-data:0 /etc/passbolt/certs \
&& chown www-data:0 /var/log/supervisor \
&& chown -R www-data:0 /var/log/nginx \
&& ln -sf /dev/stdout /var/log/nginx/passbolt-access.log \
&& ln -sf /dev/stderr /var/log/nginx/passbolt-error.log \
&& ln -sf /dev/stderr /var/log/passbolt/error.log \
&& ln -sf /dev/stderr /var/log/php7.3-fpm.log \
&& chown -R www-data:0 /var/log/supervisor \
&& touch /var/www/.profile \
&& chown www-data:www-data /var/www/.profile \
&& sed -i 's,www-data\s,,' /etc/cron.d/$PASSBOLT_PKG
COPY conf/supervisor/*.conf /etc/supervisor/conf.d/
COPY debian/bin/docker-entrypoint.sh.rootless /docker-entrypoint.sh
COPY scripts/wait-for.sh /usr/bin/wait-for.sh
EXPOSE 8080 4443
WORKDIR /usr/share/php/passbolt
USER www-data
CMD ["/docker-entrypoint.sh"]

141
debian/bin/docker-entrypoint.sh vendored Executable file
View File

@ -0,0 +1,141 @@
#!/usr/bin/env bash
set -eo pipefail
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'
deprecation_message=""
entropy_check() {
local entropy_avail
entropy_avail=$(cat /proc/sys/kernel/random/entropy_avail)
if [ "$entropy_avail" -lt 2000 ]; then
cat <<EOF
==================================================================================
Your entropy pool is low. This situation could lead GnuPG to not
be able to create the gpg serverkey so the container start process will hang
until enough entropy is obtained.
Please consider installing rng-tools and/or virtio-rng on your host as the
preferred method to generate random numbers using a TRNG.
If rngd (rng-tools) does not provide enough or fast enough randomness you could
consider installing haveged as a helper to speed up this process.
Using haveged as a replacement for rngd is not recommended. You can read more
about this topic here: https://lwn.net/Articles/525459/
==================================================================================
EOF
fi
}
gpg_gen_key() {
key_email="${PASSBOLT_KEY_EMAIL:-passbolt@yourdomain.com}"
key_name="${PASSBOLT_KEY_NAME:-Passbolt default user}"
key_length="${PASSBOLT_KEY_LENGTH:-2048}"
subkey_length="${PASSBOLT_SUBKEY_LENGTH:-2048}"
expiration="${PASSBOLT_KEY_EXPIRATION:-0}"
entropy_check
su -c "gpg --homedir $GNUPGHOME --batch --no-tty --gen-key <<EOF
Key-Type: default
Key-Length: $key_length
Subkey-Type: default
Subkey-Length: $subkey_length
Name-Real: $key_name
Name-Email: $key_email
Expire-Date: $expiration
%no-protection
%commit
EOF" -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 --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() {
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
-subj '/C=FR/ST=Denial/L=Springfield/O=Dis/CN=www.passbolt.local' \
-keyout $ssl_key -out $ssl_cert
}
install() {
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 "$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 '/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! ☮"
}
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
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
gpg_import_key
fi
if [ ! -f "$ssl_key" ] && [ ! -L "$ssl_key" ] && \
[ ! -f "$ssl_cert" ] && [ ! -L "$ssl_cert" ]; then
gen_ssl_cert
fi
install
echo -e "$deprecation_message"
exec /usr/bin/supervisord -n

141
debian/bin/docker-entrypoint.sh.rootless vendored Executable file
View File

@ -0,0 +1,141 @@
#!/usr/bin/env bash
set -exo pipefail
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/passbolt/certs/certificate.key'
ssl_cert='/etc/passbolt/certs/certificate.crt'
deprecation_message=""
entropy_check() {
local entropy_avail
entropy_avail=$(cat /proc/sys/kernel/random/entropy_avail)
if [ "$entropy_avail" -lt 2000 ]; then
cat <<EOF
==================================================================================
Your entropy pool is low. This situation could lead GnuPG to not
be able to create the gpg serverkey so the container start process will hang
until enough entropy is obtained.
Please consider installing rng-tools and/or virtio-rng on your host as the
preferred method to generate random numbers using a TRNG.
If rngd (rng-tools) does not provide enough or fast enough randomness you could
consider installing haveged as a helper to speed up this process.
Using haveged as a replacement for rngd is not recommended. You can read more
about this topic here: https://lwn.net/Articles/525459/
==================================================================================
EOF
fi
}
gpg_gen_key() {
key_email="${PASSBOLT_KEY_EMAIL:-passbolt@yourdomain.com}"
key_name="${PASSBOLT_KEY_NAME:-Passbolt default user}"
key_length="${PASSBOLT_KEY_LENGTH:-2048}"
subkey_length="${PASSBOLT_SUBKEY_LENGTH:-2048}"
expiration="${PASSBOLT_KEY_EXPIRATION:-0}"
entropy_check
gpg --homedir $GNUPGHOME --batch --no-tty --gen-key <<EOF
Key-Type: default
Key-Length: $key_length
Subkey-Type: default
Subkey-Length: $subkey_length
Name-Real: $key_name
Name-Email: $key_email
Expire-Date: $expiration
%no-protection
%commit
EOF
gpg --homedir $GNUPGHOME --armor --export-secret-keys $key_email > $gpg_private_key
gpg --homedir $GNUPGHOME --armor --export $key_email > $gpg_public_key
}
gpg_import_key() {
gpg --homedir $GNUPGHOME --batch --import $gpg_public_key
gpg --homedir $GNUPGHOME --batch --import $gpg_private_key
}
gen_ssl_cert() {
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
-subj '/C=FR/ST=Denial/L=Springfield/O=Dis/CN=www.passbolt.local' \
-keyout $ssl_key -out $ssl_cert
}
install() {
if [ ! -f "$passbolt_config/app.php" ]; then
cp $passbolt_config/app.default.php $passbolt_config/app.php
fi
if [ -z "${PASSBOLT_GPG_SERVER_KEY_FINGERPRINT+xxx}" ] && [ ! -f "$passbolt_config/passbolt.php" ]; then
gpg_auto_fingerprint="$(gpg --homedir $GNUPGHOME --list-keys --with-colons ${PASSBOLT_KEY_EMAIL:-passbolt@yourdomain.com} |grep fpr |head -1| cut -f10 -d:)"
export PASSBOLT_GPG_SERVER_KEY_FINGERPRINT=$gpg_auto_fingerprint
fi
/usr/share/php/passbolt/bin/cake passbolt install --no-admin || /usr/share/php/passbolt/bin/cake passbolt migrate && echo "Enjoy! ☮"
}
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
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
gpg_import_key
fi
if [ ! -f "$ssl_key" ] && [ ! -L "$ssl_key" ] && \
[ ! -f "$ssl_cert" ] && [ ! -L "$ssl_cert" ]; then
gen_ssl_cert
fi
install
echo -e "$deprecation_message"
exec /usr/bin/supervisord -n

1
debian/conf vendored Symbolic link
View File

@ -0,0 +1 @@
../conf

1
debian/scripts vendored Symbolic link
View File

@ -0,0 +1 @@
../scripts

View File

@ -76,11 +76,14 @@ RUN apt-get update \
&& rm /usr/local/bin/composer \ && rm /usr/local/bin/composer \
&& echo 'php_flag[expose_php] = off' > /usr/local/etc/php-fpm.d/expose.conf \ && echo 'php_flag[expose_php] = off' > /usr/local/etc/php-fpm.d/expose.conf \
&& sed -i 's/# server_tokens/server_tokens/' /etc/nginx/nginx.conf \ && sed -i 's/# server_tokens/server_tokens/' /etc/nginx/nginx.conf \
&& mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" && mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
&& echo "* * * * * su -c \"source /etc/environment ; /var/www/passbolt/bin/cake EmailQueue.sender\" -s /bin/bash www-data >> /var/log/cron.log 2>&1" >> /etc/cron.d/passbolt_email \
&& crontab /etc/cron.d/passbolt_email \
&& ln -s $(which php-fpm){,7.3}
COPY conf/passbolt.conf /etc/nginx/conf.d/default.conf COPY conf/passbolt.conf /etc/nginx/conf.d/default.conf
COPY conf/supervisor/*.conf /etc/supervisor/conf.d/ COPY conf/supervisor/*.conf /etc/supervisor/conf.d/
COPY bin/docker-entrypoint.sh /docker-entrypoint.sh COPY dev/bin/docker-entrypoint.sh /docker-entrypoint.sh
COPY scripts/wait-for.sh /usr/bin/wait-for.sh COPY scripts/wait-for.sh /usr/bin/wait-for.sh
EXPOSE 80 443 EXPOSE 80 443

View File

@ -84,15 +84,6 @@ install() {
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 '/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! ☮"
} }
email_cron_job() {
cron_task='/etc/cron.d/passbolt_email'
declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /etc/environment
if [ ! -f "$cron_task" ]; then
echo "* * * * * su -c \"source /etc/environment ; /var/www/passbolt/bin/cake EmailQueue.sender\" -s /bin/bash www-data >> /var/log/cron.log 2>&1" >> $cron_task
crontab /etc/cron.d/passbolt_email
fi
}
if [ ! -f "$gpg_private_key" ] && [ ! -L "$gpg_private_key" ] || \ if [ ! -f "$gpg_private_key" ] && [ ! -L "$gpg_private_key" ] || \
[ ! -f "$gpg_public_key" ] && [ ! -L "$gpg_public_key" ]; then [ ! -f "$gpg_public_key" ] && [ ! -L "$gpg_public_key" ]; then
gpg_gen_key gpg_gen_key
@ -107,6 +98,5 @@ if [ ! -f "$ssl_key" ] && [ ! -L "$ssl_key" ] && \
fi fi
install install
email_cron_job
exec /usr/bin/supervisord -n exec /usr/bin/supervisord -n

1
dev/conf Symbolic link
View File

@ -0,0 +1 @@
../conf

1
dev/scripts Symbolic link
View File

@ -0,0 +1 @@
../scripts

View File

@ -10,18 +10,16 @@ services:
- "127.0.0.1:3306:3306" - "127.0.0.1:3306:3306"
passbolt: passbolt:
image: passbolt/passbolt:2.13.5-pro-debian image: passbolt/passbolt:3.0.0-pro
tty: true tty: true
depends_on: depends_on:
- db - db
env_file: env_file:
- env/passbolt.env - env/passbolt.env
volumes: volumes:
- gpg_volume:/var/www/passbolt/config/gpg - gpg_volume:/etc/passbolt/gpg
- images_volume:/var/www/passbolt/webroot/img/public - images_volume:/usr/share/php/passbolt/webroot/img/public
- ./license:/var/www/passbolt/config/license - ./license:/etc/passbolt/license
tmpfs:
- /run
command: ["/usr/bin/wait-for.sh", "-t", "0", "db:3306", "--", "/docker-entrypoint.sh"] command: ["/usr/bin/wait-for.sh", "-t", "0", "db:3306", "--", "/docker-entrypoint.sh"]
ports: ports:
- 80:80 - 80:80

View File

@ -10,17 +10,15 @@ services:
- "127.0.0.1:3306:3306" - "127.0.0.1:3306:3306"
passbolt: passbolt:
image: passbolt/passbolt:2.13.5-debian image: passbolt/passbolt:3.0.0-ce
tty: true tty: true
depends_on: depends_on:
- db - db
env_file: env_file:
- env/passbolt.env - env/passbolt.env
volumes: volumes:
- gpg_volume:/var/www/passbolt/config/gpg - gpg_volume:/etc/passbolt/gpg
- images_volume:/var/www/passbolt/webroot/img/public - images_volume:/usr/share/php/passbolt/webroot/img/public
tmpfs:
- /run
command: ["/usr/bin/wait-for.sh", "-t", "0", "db:3306", "--", "/docker-entrypoint.sh"] command: ["/usr/bin/wait-for.sh", "-t", "0", "db:3306", "--", "/docker-entrypoint.sh"]
ports: ports:
- 80:80 - 80:80

View File

@ -8,30 +8,29 @@ describe 'Dockerfile' do
'DATASOURCES_DEFAULT_PASSWORD' => 'P4ssb0lt', 'DATASOURCES_DEFAULT_PASSWORD' => 'P4ssb0lt',
'DATASOURCES_DEFAULT_USERNAME' => 'passbolt', 'DATASOURCES_DEFAULT_USERNAME' => 'passbolt',
'DATASOURCES_DEFAULT_DATABASE' => 'passbolt', 'DATASOURCES_DEFAULT_DATABASE' => 'passbolt',
'PASSBOLT_GPG_KEYRING' => '/var/lib/nginx/.gnupg' 'PASSBOLT_GPG_KEYRING' => '/var/lib/passbolt/.gnupg'
} }
@image = Docker::Image.build_from_dir(ROOT_DOCKERFILES) @image = Docker::Image.build_from_dir(ROOT_DOCKERFILES, { 'dockerfile' => 'debian/Dockerfile' })
set :docker_image, @image.id set :docker_image, @image.id
set :docker_container_create_options, { 'Cmd' => '/bin/sh' } set :docker_container_create_options, { 'Cmd' => '/bin/sh' }
end end
let(:nginx_conf) { '/etc/nginx/nginx.conf' } let(:nginx_conf) { '/etc/nginx/nginx.conf' }
let(:php_conf) { '/usr/local/etc/php-fpm.d/expose.conf' } let(:php_conf) { '/etc/php/7.3/fpm/php.ini' }
let(:site_conf) { '/etc/nginx/conf.d/default.conf' } let(:site_conf) { '/etc/nginx/sites-enabled/nginx-passbolt.conf' }
let(:supervisor_conf) do let(:supervisor_conf) do
[ '/etc/supervisor/conf.d/nginx.conf', [ '/etc/supervisor/conf.d/nginx.conf',
'/etc/supervisor/conf.d/php.conf', '/etc/supervisor/conf.d/php.conf',
'/etc/supervisor/conf.d/cron.conf' ] '/etc/supervisor/conf.d/cron.conf' ]
end end
let(:passbolt_home) { '/var/www/passbolt' } let(:passbolt_home) { '/usr/share/php/passbolt' }
let(:passbolt_tmp) { '/var/www/passbolt/tmp' } let(:passbolt_tmp) { '/var/lib/passbolt/tmp' }
let(:passbolt_image) { '/var/www/passbolt/webroot/img/public' } let(:passbolt_image) { "#{passbolt_home}/webroot/img/public" }
let(:passbolt_owner) { 'www-data' } let(:passbolt_owner) { 'www-data' }
let(:exposed_ports) { [ '80', '443' ] } let(:exposed_ports) { [ '80', '443' ] }
let(:composer) { '/usr/local/bin/composer'}
let(:php_extensions) { [ let(:php_extensions) { [
'curl', 'gd', 'intl', 'json', 'mcrypt', 'mysqlnd', 'xsl', 'phar', 'gd', 'intl', 'json', 'mysqlnd', 'xsl', 'phar',
'posix', 'xml', 'zlib', 'ctype', 'pdo', 'gnupg', 'pdo_mysql' 'posix', 'xml', 'zlib', 'ctype', 'pdo', 'gnupg', 'pdo_mysql'
] } ] }
let(:wait_for) { '/usr/bin/wait-for.sh' } let(:wait_for) { '/usr/bin/wait-for.sh' }
@ -44,12 +43,6 @@ describe 'Dockerfile' do
end end
end end
describe 'php composer' do
it 'is not installed' do
expect(file(composer)).to_not exist
end
end
describe 'supervisor' do describe 'supervisor' do
it 'is installed' do it 'is installed' do
expect(package('supervisor')).to be_installed expect(package('supervisor')).to be_installed
@ -62,12 +55,6 @@ describe 'Dockerfile' do
end end
end end
describe 'mariadb-client' do
it 'is installed' do
expect(package('mariadb-client')).to be_installed
end
end
describe 'wait-for' do describe 'wait-for' do
it 'is installed' do it 'is installed' do
expect(file(wait_for)).to exist and be_executable expect(file(wait_for)).to exist and be_executable
@ -82,17 +69,17 @@ describe 'Dockerfile' do
end end
it 'must be owned by correct user' do it 'must be owned by correct user' do
expect(file(passbolt_home)).to be_owned_by(passbolt_owner) expect(file(passbolt_home)).to be_owned_by('root')
expect(file(passbolt_tmp)).to be_owned_by(passbolt_owner) expect(file(passbolt_tmp)).to be_owned_by(passbolt_owner)
expect(file(passbolt_image)).to be_owned_by(passbolt_owner) expect(file(passbolt_image)).to be_owned_by(passbolt_owner)
end end
it 'must have the correct permissions on tmp' do it 'must have the correct permissions on tmp' do
expect(file(passbolt_tmp)).to be_mode('775') expect(file(passbolt_tmp)).to be_mode('755')
end end
it 'must have the correct permissions on img' do it 'must have the correct permissions on img' do
expect(file(passbolt_image)).to be_mode('775') expect(file(passbolt_image)).to be_mode('755')
end end
end end
@ -102,7 +89,7 @@ describe 'Dockerfile' do
end end
it 'does not expose php version' do it 'does not expose php version' do
expect(file(php_conf).content).to match(/^php_flag\[expose_php\]\s+=\s+off$/) expect(file(php_conf).content).to match(/^expose_php\s+=\s+Off$/)
end end
end end
@ -126,7 +113,7 @@ describe 'Dockerfile' do
end end
it 'points to the correct root folder' do it 'points to the correct root folder' do
expect(file(site_conf).content).to match 'root /var/www/passbolt/webroot' expect(file(site_conf).content).to match "root #{passbolt_home}/webroot"
end end
it 'has server tokens off' do it 'has server tokens off' do

View File

@ -24,7 +24,7 @@ describe 'passbolt_api service' do
sleep 1 sleep 1
end end
@image = Docker::Image.build_from_dir(ROOT_DOCKERFILES) @image = Docker::Image.build_from_dir(ROOT_DOCKERFILES, { 'dockerfile' => 'debian/Dockerfile' })
@container = Docker::Container.create( @container = Docker::Container.create(
'Env' => [ 'Env' => [
"DATASOURCES_DEFAULT_HOST=#{@mysql.json['NetworkSettings']['IPAddress']}", "DATASOURCES_DEFAULT_HOST=#{@mysql.json['NetworkSettings']['IPAddress']}",
@ -54,10 +54,6 @@ describe 'passbolt_api service' do
it 'is running supervised' do it 'is running supervised' do
expect(service('php-fpm')).to be_running.under('supervisor') expect(service('php-fpm')).to be_running.under('supervisor')
end end
it 'has its port open' do
expect(@container.json['Config']['ExposedPorts']).to have_key('9000/tcp')
end
end end
describe 'email cron' do describe 'email cron' do
@ -86,28 +82,8 @@ describe 'passbolt_api service' do
end end
end end
describe 'passbolt serverkey unaccessible' do describe 'can not access outside webroot' do
let(:uri) { '/config/gpg/serverkey.asc' } let(:uri) { '/vendor/autoload.php' }
it "returns 404" do
expect(command(curl).stdout).to eq '404'
end
end
describe 'passbolt serverkey private unaccessible' do
let(:uri) { '/config/gpg/serverkey_private.asc' }
it 'returns 404' do
expect(command(curl).stdout).to eq '404'
end
end
describe 'passbolt conf unaccessible' do
let(:uri) { '/config/app.php' }
it 'returns 404' do
expect(command(curl).stdout).to eq '404'
end
end
describe 'passbolt tmp folder is unaccessible' do
let(:uri) { '/tmp/cache/database/empty' }
it 'returns 404' do it 'returns 404' do
expect(command(curl).stdout).to eq '404' expect(command(curl).stdout).to eq '404'
end end
@ -120,7 +96,7 @@ describe 'passbolt_api service' do
end end
it 'hides nginx version' do it 'hides nginx version' do
expect(command("#{curl} | grep 'Server:'").stdout.strip).to match(/^Server:\s+nginx$/) expect(command("#{curl} | grep 'server:'").stdout.strip).to match(/^server:\s+nginx$/)
end end
end end

View File

@ -24,13 +24,13 @@ describe 'passbolt_api service' do
sleep 1 sleep 1
end end
@image = Docker::Image.build_from_dir(ROOT_DOCKERFILES) @image = Docker::Image.build_from_dir(ROOT_DOCKERFILES, { 'dockerfile' => 'debian/Dockerfile' })
@container = Docker::Container.create( @container = Docker::Container.create(
'Env' => [ 'Env' => [
"DATASOURCES_DEFAULT_HOST=#{@mysql.json['NetworkSettings']['IPAddress']}", "DATASOURCES_DEFAULT_HOST=#{@mysql.json['NetworkSettings']['IPAddress']}",
], ],
'Binds' => [ "#{FIXTURES_PATH + '/passbolt.php'}:/var/www/passbolt/config/passbolt.php" ], 'Binds' => [ "#{FIXTURES_PATH + '/passbolt.php'}:/etc/passbolt/passbolt.php" ],
'Image' => @image.id) 'Image' => @image.id)
@container.start @container.start
@ -53,10 +53,6 @@ describe 'passbolt_api service' do
it 'is running supervised' do it 'is running supervised' do
expect(service('php-fpm')).to be_running.under('supervisor') expect(service('php-fpm')).to be_running.under('supervisor')
end end
it 'has its port open' do
expect(@container.json['Config']['ExposedPorts']).to have_key('9000/tcp')
end
end end
describe 'email cron' do describe 'email cron' do
@ -85,28 +81,8 @@ describe 'passbolt_api service' do
end end
end end
describe 'passbolt serverkey unaccessible' do describe 'can not access outside webroot' do
let(:uri) { '/config/gpg/serverkey.asc' } let(:uri) { '/vendor/autoload.php' }
it "returns 404" do
expect(command(curl).stdout).to eq '404'
end
end
describe 'passbolt serverkey private unaccessible' do
let(:uri) { '/config/gpg/serverkey_private.asc' }
it 'returns 404' do
expect(command(curl).stdout).to eq '404'
end
end
describe 'passbolt conf unaccessible' do
let(:uri) { '/config/app.php' }
it 'returns 404' do
expect(command(curl).stdout).to eq '404'
end
end
describe 'passbolt tmp folder is unaccessible' do
let(:uri) { '/tmp/cache/database/empty' }
it 'returns 404' do it 'returns 404' do
expect(command(curl).stdout).to eq '404' expect(command(curl).stdout).to eq '404'
end end
@ -119,7 +95,7 @@ describe 'passbolt_api service' do
end end
it 'hides nginx version' do it 'hides nginx version' do
expect(command("#{curl} | grep 'Server:'").stdout.strip).to match(/^Server:\s+nginx$/) expect(command("#{curl} | grep 'server:'").stdout.strip).to match(/^server:\s+nginx$/)
end end
end end