Merge branch 'feature/v2.0.0-rc1' into develop

This commit is contained in:
Diego Lendoiro 2018-01-16 18:02:17 +01:00
commit bc3431d88c
12 changed files with 463 additions and 369 deletions

3
.gitignore vendored
View File

@ -27,3 +27,6 @@ fabric.properties
# Generated docker files
conf/*.key
# src directory used for local development
src

View File

@ -1,30 +1,15 @@
FROM alpine:3.6
FROM php:7-fpm-alpine3.7
LABEL maintainer="diego@passbolt.com"
LABEL MAINTAINER diego@passbolt.com
ENV PASSBOLT_VERSION 1.6.9
ENV PASSBOLT_URL https://github.com/passbolt/passbolt_api/archive/v${PASSBOLT_VERSION}.tar.gz
ENV PASSBOLT_URL https://github.com/passbolt/passbolt_api/archive/develop.tar.gz
ARG BASE_PHP_DEPS="php5-curl \
php5-common \
php5-gd \
php5-intl \
php5-json \
php5-mcrypt \
php5-mysql \
php5-xsl \
php5-fpm \
php5-phar \
php5-posix \
php5-xml \
php5-openssl \
php5-zlib \
php5-ctype \
php5-pdo \
php5-pdo_mysql \
php5-pear"
ARG PHP_EXTENSIONS="gd \
intl \
pdo_mysql \
xsl"
ARG PHP_GNUPG_DEPS="php5-dev \
ARG PHP_GNUPG_BUILD_DEPS="php7-dev \
make \
gcc \
g++ \
@ -36,40 +21,35 @@ ARG PHP_GNUPG_DEPS="php5-dev \
zlib-dev \
file"
RUN apk add --no-cache $BASE_PHP_DEPS \
sed \
coreutils \
tar \
bash \
curl \
RUN apk add --no-cache $PHP_GNUPG_BUILD_DEPS \
nginx \
gpgme \
gnupg1 \
recode \
libxml2 \
openssl \
libpcre32 \
mysql-client \
ca-certificates
RUN apk add --no-cache $PHP_GNUPG_DEPS \
&& ln -s /usr/bin/php5 /usr/bin/php \
&& ln -s /usr/bin/phpize5 /usr/bin/phpize \
&& sed -i "s/ -n / /" $(which pecl) \
&& pecl install gnupg \
&& pecl install redis \
&& echo "extension=gnupg.so" > /etc/php5/conf.d/gnupg.ini \
&& echo "extension=redis.so" > /etc/php5/conf.d/redis.ini \
&& apk del $PHP_GNUPG_DEPS \
libpng-dev \
icu-dev \
libxslt-dev \
libmcrypt-dev \
supervisor \
&& pecl install gnupg redis mcrypt-snapshot \
&& docker-php-ext-install -j4 $PHP_EXTENSIONS \
&& docker-php-ext-enable $PHP_EXTENSIONS gnupg redis mcrypt \
&& apk del $PHP_GNUPG_BUILD_DEPS \
&& curl -sS https://getcomposer.org/installer | php \
&& mv composer.phar /usr/local/bin/composer \
&& mkdir /var/www/passbolt \
&& mv composer.phar /usr/local/bin/composer
RUN mkdir -p /var/www/passbolt \
&& curl -sSL $PASSBOLT_URL | tar zxf - -C /var/www/passbolt --strip-components 1 \
&& chown -R nginx:nginx /var/www/passbolt \
&& chmod -R +w /var/www/passbolt/app/tmp \
&& chmod +w /var/www/passbolt/app/webroot/img/public
&& cd /var/www/passbolt \
&& composer install \
&& chown -R www-data:www-data /var/www/passbolt \
&& chmod 775 $(find /var/www/passbolt/tmp -type d) \
&& chmod 664 $(find /var/www/passbolt/tmp -type f) \
&& chmod 775 $(find /var/www/passbolt/webroot/img/public -type d) \
&& chmod 664 $(find /var/www/passbolt/webroot/img/public -type f)
COPY conf/passbolt.conf /etc/nginx/conf.d/default.conf
COPY conf/supervisord.conf /etc/supervisord.conf
COPY bin/docker-entrypoint.sh /docker-entrypoint.sh
EXPOSE 80 443

8
Gemfile Normal file
View File

@ -0,0 +1,8 @@
source 'https://rubygems.org'
group :test do
gem 'docker-api'
gem 'rake'
gem 'serverspec'
gem 'pry'
end

58
Gemfile.lock Normal file
View File

@ -0,0 +1,58 @@
GEM
remote: https://rubygems.org/
specs:
coderay (1.1.2)
diff-lcs (1.3)
docker-api (1.34.0)
excon (>= 0.47.0)
multi_json
excon (0.60.0)
method_source (0.9.0)
multi_json (1.12.2)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (4.2.0)
net-telnet (0.1.1)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
rake (12.3.0)
rspec (3.7.0)
rspec-core (~> 3.7.0)
rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.7.0)
rspec-core (3.7.1)
rspec-support (~> 3.7.0)
rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-its (1.2.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-support (3.7.0)
serverspec (2.41.3)
multi_json
rspec (~> 3.0)
rspec-its
specinfra (~> 2.72)
sfl (2.3)
specinfra (2.73.0)
net-scp
net-ssh (>= 2.7, < 5.0)
net-telnet
sfl
PLATFORMS
ruby
DEPENDENCIES
docker-api
pry
rake
serverspec
BUNDLED WITH
1.16.1

153
README.md
View File

@ -1,5 +1,9 @@
# Passbolt docker official image
# Warning
This is a work in progress branch use at your own risk.
# What is passbolt?
Passbolt is a free and open source password manager that allows team members to
@ -14,8 +18,6 @@ track issues and pull requests.
Users that do not require any special modifications are encouraged to `docker pull` the
[official docker image from the docker hub](https://hub.docker.com/r/passbolt/passbolt/).
There is also a yet unofficial project to use [passbolt along with docker-compose](https://github.com/dlen/passbolt-compose) for easier the setup process.
# Build the image
Inside the repo directory:
@ -30,16 +32,22 @@ Passbolt requires mysql to be running. The following example use mysql official
with the default passbolt credentials.
```bash
$ docker run -e MYSQL_ROOT_PASSWORD=<your_root_password> \
-e MYSQL_DATABASE=passbolt \
-e MYSQL_USER=passbolt \
-e MYSQL_PASSWORD=P4ssb0lt \
$ docker run -e MYSQL_ROOT_PASSWORD=<root_password> \
-e MYSQL_DATABASE=<mysql_database> \
-e MYSQL_USER=<mysql_user> \
-e MYSQL_PASSWORD=<mysql_password> \
mysql
```
Then you can start passbolt just by providing the database container ip in the `db_host` environment variable.
`$ docker run -e DB_HOST=<mysql_container_ip> passbolt:local`
```bash
$ docker run -e DATASOURCES_DEFAULT_HOST=<mysql_container_host> \
-e DATASOURCES_DEFAULT_PASSWORD=<mysql_password> \
-e DATASOURCES_DEFAULT_USERNAME=<mysql_user> \
-e DATASOURCES_DEFAULT_DATABASE=<mysql_database> \
passbolt:local
```
Once the process is done, just navigate to the following url in your browser: https://passbolt_container_ip
@ -54,50 +62,39 @@ And access it using https://localhost:host_port
# Configure passbolt
## Environment variables
## Environment variables reference
Passbolt docker image provides several environment variables to configure different aspects:
### GnuPG key creation related variables
* KEY_LENGTH: gpg desired key length
* SUBKEY_LENGTH: gpg desired subkey length
* KEY_NAME: key owner name
* KEY_EMAIL: key owner email address
* KEY_EXPIRATION: key expiration date
### App file variables
* FINGERPRINT: GnuPG fingerprint
* REGISTRATION: Defines if users can register (defaults to false)
* SSL: Forces passbolt to redirect to SSL any non-SSL request
### Core file variables
* SALT: a random string used by cakephp in security hashing methods
* CIPHERSEED: a random string used by cakephp to encrypt/decrypt strings
* URL: URL of the passbolt installation (defaults to http://passbolt.local)
### Database variables
* DB_HOST: database hostname This param has to be specified either using env var or in database.php (defaults to passbolt.local)
* DB_PORT: database port (defaults to 3306)
* DB_USER: database username (defaults to passbolt)
* DB_PASS: database password (defaults to P4ssb0lt)
* DB_NAME: database name (defaults to passbolt)
### Email variables
* EMAIL_TRANSPORT: transport protocol ( defaults to Smtp)
* EMAIL_FROM: from email address ( defaults to contact@mydomain.local)
* EMAIL_HOST: server hostname ( defaults to localhost)
* EMAIL_PORT: server port ( defaults to 587)
* EMAIL_TIMEOUT: timeout ( defaults to 30s)
* EMAIL_AUTH: disable smtp auth ( defaults to true)
* EMAIL_USERNAME: username for email server auth ( defaults to email_user)
* EMAIL_PASSWORD: password for email server auth ( defaults to email_password)
* EMAIL_CLIENT: hostname to send as smtp helo ( defaults to null)
* EMAIL_TLS: set tls, boolean ( defaults to false)
* APP_FULL_BASE_URL: Defines Passbolt base url (Example https://yourdomain.com)
* DATASOURCES_DEFAULT_HOST: database hostname (defaults to localhost)
* DATASOURCES_DEFAULT_PORT: database port (defaults to 3306)
* DATASOURCES_DEFAULT_USERNAME: database username (defaults to my_app)
* DATASOURCES_DEFAULT_PASSWORD: database password (defaults to secret)
* DATASOURCES_DEFAULT_DATABASE: database name (defaults to my_app)
* EMAIL_DEFAULT_FROM: from email address (defaults to contact@mydomain.local)
* EMAIL_DEFAULT_TRANSPORT: sets transport method (defaults to default)
* EMAIL_TRANSPORT_DEFAULT_HOST: server hostname (defaults to localhost)
* EMAIL_TRANSPORT_DEFAULT_PORT: server port (defaults to 25)
* EMAIL_TRANSPORT_DEFAULT_TIMEOUT: timeout (defaults to 30)
* EMAIL_TRANSPORT_DEFAULT_USERNAME: username for email server auth (defaults to null)
* EMAIL_TRANSPORT_DEFAULT_PASSWORD: password for email server auth (defaults to null)
* EMAIL_TRANSPORT_DEFAULT_CLIENT: client (defaults to null)
* EMAIL_TRANSPORT_DEFAULT_TLS: set tls (defaults to null)
* EMAIL_TRANSPORT_DEFAULT_URL: set url (defaults to null)
* GNUPGHOME: Path to gnupghome directory (defaults to web_user_home_directory/.gnupg )
* PASSBOLT_KEY_LENGTH: gpg desired key length
* PASSBOLT_SUBKEY_LENGTH: gpg desired subkey length
* PASSBOLT_KEY_NAME: key owner name
* PASSBOLT_KEY_EMAIL: key owner email address
* PASSBOLT_KEY_EXPIRATION: key expiration date
* PASSBOLT_GPG_SERVER_KEY_FINGERPRINT: GnuPG fingerprint
* PASSBOLT_GPG_SERVER_KEY_PUBLIC: Path to GnuPG public server key
* PASSBOLT_GPG_SERVER_KEY_PRIVATE: Path to GnuPG private server key
* PASSBOLT_REGISTRATION_PUBLIC: Defines if users can register (defaults to false)
* PASSBOLT_SSL_FORCE: Forces passbolt to redirect to SSL any non-SSL request
* PASSBOLT_SECURITY_SET_HEADERS: Forces passbolt to send CSP Headers (defaults to true)
* SECURITY_SALT: A random number user in security hashing methods.
## Advanced configuration
@ -106,12 +103,9 @@ It it possible to mount the desired configuration files as volumes.
### Configuration files subject to be persisted:
* /var/www/passbolt/app/Config/app.php
* /var/www/passbolt/app/Config/core.php
* /var/www/passbolt/app/Config/database.php
* /var/www/passbolt/app/Config/email.php
* /var/www/passbolt/app/Config/gpg/serverkey.asc
* /var/www/passbolt/app/Config/gpg/serverkey.private.asc
* /var/www/passbolt/config/app.php
* /var/www/passbolt/config/gpg/serverkey.asc
* /var/www/passbolt/config/gpg/serverkey_private.asc
* /var/www/passbolt/app/webroot/img/public/images
### SSL certificate files
@ -121,57 +115,6 @@ It is also possible to mount a ssl certificate on the following paths:
* /etc/ssl/certs/certificate.crt
* /etc/ssl/certs/certificate.key
# Examples
For the following examples it is assumed that passbolt container image has been built from this repo following the instructions
described on the [Build](#build-the-image) section.
In the following example passbolt is launched with the defaults enabled usind mysql official docker container to store passbolt data:
```bash
$ docker run -e MYSQL_ROOT_PASSWORD=c0mplexp4ss \
-e MYSQL_DATABASE=passbolt \
-e MYSQL_USER=passbolt \
-e MYSQL_PASSWORD=P4ssb0lt \
mysql
```
Once mysql container is running we should extract its ip address. Let's assume 172.17.0.2 for this example
`$ docker run -e DB_HOST=172.17.0.2 passbolt:local`
Point your browser to the passbolt container ip or localhost:exposed_port.
## Advanced configuration
In the following example passbolt is launched with a customized setup mounting and persisting configuration files. We also make use of
mysql official docker container to store passbolt data.
```bash
$ docker run -e MYSQL_ROOT_PASSWORD=c0mplexp4ss \
-e MYSQL_DATABASE=passbolt \
-e MYSQL_USER=passbolt \
-e MYSQL_PASSWORD=P4ssb0lt \
mysql
```
Using docker inspect or any other method you can get the ip address of the mysql container. This example uses 172.17.0.2.
Once this container is running and you have the mysql ip address we run passbolt container mounting all configuration files stored
under a example conf directory in $PWD
```bash
$ docker run -v $PWD/conf/app.php:/var/www/passbolt/app/Config/app.php \
-v $PWD/conf/core.php:/var/www/passbolt/app/Config/core.php \
-v $PWD/conf/database.php:/var/www/passbolt/app/Config/database.php \
-v $PWD/conf/email.php:/var/www/passbolt/app/Config/email.php \
-v $PWD/conf/private.asc:/var/www/passbolt/app/Config/gpg/serverkey.private.asc \
-v $PWD/conf/public.asc:/var/www/passbolt/app/Config/gpg/serverkey.asc \
passbolt:local
```
Navigate with the browser to the passbolt container ip or localhost:exposed_port
# Requirements:
* rng-tools are required on host machine to speed up entropy generation on containers. This way gpg key creation on passbolt container will be faster.

27
Rakefile Normal file
View File

@ -0,0 +1,27 @@
require 'rake'
require 'rspec/core/rake_task'
task :spec => 'spec:all'
task :default => :spec
namespace :spec do
targets = []
Dir.glob('./spec/*').each do |dir|
next unless File.directory?(dir)
target = File.basename(dir)
target = "_#{target}" if target == "default"
targets << target
end
task :all => targets
task :default => :all
targets.each do |target|
original_target = target == "_default" ? target[1..-1] : target
desc "Run serverspec tests to #{original_target}"
RSpec::Core::RakeTask.new(target.to_sym) do |t|
ENV['TARGET_HOST'] = original_target
t.pattern = "spec/#{original_target}/*_spec.rb"
end
end
end

View File

@ -1,232 +1,99 @@
#!/bin/bash
#!/usr/bin/env sh
set -eo pipefail
gpg_private_key=/var/www/passbolt/app/Config/gpg/serverkey.private.asc
gpg_public_key=/var/www/passbolt/app/Config/gpg/serverkey.asc
gpg=$(which gpg)
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}"
core_config='/var/www/passbolt/app/Config/core.php'
db_config='/var/www/passbolt/app/Config/database.php'
app_config='/var/www/passbolt/app/Config/app.php'
email_config='/var/www/passbolt/app/Config/email.php'
ssl_key='/etc/ssl/certs/certificate.key'
ssl_cert='/etc/ssl/certs/certificate.crt'
gpg_gen_key() {
su -m -c "$gpg --batch --gen-key <<EOF
Key-Type: 1
Key-Length: ${KEY_LENGTH:-2048}
Subkey-Type: 1
Subkey-Length: ${SUBKEY_LENGTH:-2048}
Name-Real: ${KEY_NAME:-Passbolt default user}
Name-Email: ${KEY_EMAIL:-passbolt@yourdomain.com}
Expire-Date: ${KEY_EXPIRATION:-0}
%commit
EOF" -ls /bin/bash nginx
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}"
su -m -c "$gpg --armor --export-secret-keys $KEY_EMAIL > $gpg_private_key" -ls /bin/bash nginx
su -m -c "$gpg --armor --export $KEY_EMAIL > $gpg_public_key" -ls /bin/bash nginx
su -m -c "gpg --batch --gen-key <<EOF
Key-Type: 1
Key-Length: $key_length
Subkey-Type: 1
Subkey-Length: $subkey_length
Name-Real: $key_name
Name-Email: $key_email
Expire-Date: $expiration
%commit
EOF" -ls /bin/sh www-data
su -c "gpg --armor --export-secret-keys $key_email > $gpg_private_key" -ls /bin/sh www-data
su -c "gpg --armor --export $key_email > $gpg_public_key" -ls /bin/sh www-data
}
gpg_import_key() {
local key_id=$(su -m -c "gpg --with-colons $gpg_private_key | grep sec |cut -f5 -d:" -ls /bin/bash nginx)
su -m -c "$gpg --batch --import $gpg_public_key" -ls /bin/bash nginx
su -m -c "gpg -K $key_id" -ls /bin/bash nginx || su -m -c "$gpg --batch --import $gpg_private_key" -ls /bin/bash nginx
}
core_setup() {
#Env vars:
# SALT
# CIPHERSEED
# URL
local default_salt='DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi'
local default_seed='76859309657453542496749683645'
local default_url='http://passbolt.local'
cp $core_config{.default,}
sed -i s:$default_salt:${SALT:-$default_salt}:g $core_config
sed -i s:$default_seed:${CIPHERSEED:-$default_seed}:g $core_config
sed -i "/example.com/ s:\/\/::" $core_config
sed -i "s|http://example.com|${URL:-$default_url}|g" $core_config
}
db_setup() {
#Env vars:
# DB_HOST
# DB_USER
# DB_PASS
# DB_NAME
local default_host='localhost'
local default_user='user'
local default_pass='password'
local default_db='database_name'
cp $db_config{.default,}
sed -i "/$default_host/a\ \t\t'port' => '${DB_PORT:-3306}'," $db_config
sed -i s:$default_host:${DB_HOST:-db}:g $db_config
sed -i s:$default_user:${DB_USER:-passbolt}:g $db_config
sed -i s:$default_pass\',:${DB_PASS:-P4ssb0lt}\',:g $db_config
sed -i s:$default_db:${DB_NAME:-passbolt}:g $db_config
}
app_setup() {
#Env vars:
# FINGERPRINT
# REGISTRATION
# SSL
local default_home='/home/www-data/.gnupg'
local default_public_key='unsecure.key'
local default_private_key='unsecure_private.key'
local default_fingerprint='2FC8945833C51946E937F9FED47B0811573EE67E'
local gpg_home='/var/lib/nginx/.gnupg'
local auto_fingerprint=$(su -m -c "$gpg --fingerprint |grep fingerprint| awk '{for(i=4;i<=NF;++i)printf \$i}'" -ls /bin/bash nginx)
cp $app_config{.default,}
sed -i s:$default_home:$gpg_home:g $app_config
sed -i s:$default_public_key:serverkey.asc:g $app_config
sed -i s:$default_private_key:serverkey.private.asc:g $app_config
sed -i s:$default_fingerprint:${FINGERPRINT:-$auto_fingerprint}:g $app_config
sed -i "/force/ s:true:${SSL:-true}:" $app_config
sed -i "/'registration'/{n; s:false:${REGISTRATION:-false}:}" $app_config
}
email_setup() {
#Env vars:
# EMAIL_TRANSPORT
# EMAIL_FROM
# EMAIL_HOST
# EMAIL_PORT
# EMAIL_TIMEOUT
# EMAIL_AUTH
# EMAIL_USERNAME
# EMAIL_PASSWORD
# EMAIL_CLIENT
# EMAIL_TLS
local default_transport='Smtp'
local default_from='contact@passbolt.com'
local default_host='smtp.mandrillapp.com'
local default_port='587'
local default_timeout='30'
local default_username="''"
local default_password="''"
local default_client=null
cp $email_config{.default,}
sed -i s:$default_transport:${EMAIL_TRANSPORT:-Smtp}:g $email_config
sed -i s:$default_from:${EMAIL_FROM:-contact@mydomain.local}:g $email_config
sed -i s:$default_host:${EMAIL_HOST:-localhost}:g $email_config
sed -i s:$default_port:${EMAIL_PORT:-587}:g $email_config
sed -i s:$default_timeout:${EMAIL_TIMEOUT:-30}:g $email_config
if [ "$EMAIL_AUTH" = "false" ] ; then
sed -i "0,/"$default_username"/s:"$default_username":null:" $email_config
sed -i "0,/"$default_password"/s:"$default_password":null:" $email_config
else
sed -i "0,/"$default_username"/s:"$default_username":'${EMAIL_USERNAME:-email_user}':" $email_config
sed -i "0,/"$default_password"/s:"$default_password":'${EMAIL_PASSWORD:-email_password}':" $email_config
fi
if [ -n "$EMAIL_CLIENT" ] ; then
sed -i "0,/"$default_client"/s:"$default_client":'$EMAIL_CLIENT':" $email_config
fi
sed -i "0,/tls/s:false:${EMAIL_TLS:-false}:" $email_config
key_id=$(su -m -c "gpg --with-colons $gpg_private_key | grep sec |cut -f5 -d:" -ls /bin/sh www-data)
su -c "gpg --batch --import $gpg_public_key" -ls /bin/sh www-data
su -c "gpg -K $key_id" -ls /bin/sh www-data || su -m -c "gpg --batch --import $gpg_private_key" -ls /bin/sh 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" \
-subj '/C=FR/ST=Denial/L=Springfield/O=Dis/CN=www.passbolt.local' \
-keyout $ssl_key -out $ssl_cert
}
install() {
local database_host=${DB_HOST:-$(cat $db_config | grep -m1 "'host'" | sed -r "s/\s*'host' => '(.*)',/\1/")}
local database_port=${DB_PORT:-$(cat $db_config | grep -m1 "'port' => '\d" | sed -r "s/\s*'port' => '(.*)',/\1/")}
local database_user=${DB_USER:-$(cat $db_config | grep -m1 "'login'" | sed -r "s/\s*'login' => '(.*)',/\1/")}
local database_pass=${DB_PASS:-$(cat $db_config | grep -m1 "'password'" | sed -r "s/\s*'password' => '(.*)',/\1/")}
local database_name=${DB_NAME:-$(cat $db_config | grep -m1 "'database'" | sed -r "s/\s*'database' => '(.*)',/\1/")}
tables=$(mysql -u ${database_user:-passbolt} -h $database_host -P ${database_port:-3306} -p -BN -e "SHOW TABLES FROM ${database_name:-passbolt}" -p${database_pass:-P4ssb0lt} |wc -l)
tables=$(mysql \
-u "$DATASOURCES_DEFAULT_USERNAME" \
-h "$DATASOURCES_DEFAULT_HOST" \
-P "$DATASOURCES_DEFAULT_PORT" \
-BN -e "SHOW TABLES FROM $DATASOURCES_DEFAULT_DATABASE" \
-p"$DATASOURCES_DEFAULT_PASSWORD" |wc -l)
app_config="/var/www/passbolt/config/app.php"
if [ $tables -eq 0 ]; then
su -c "/var/www/passbolt/app/Console/cake install --send-anonymous-statistics true --no-admin" -ls /bin/bash nginx
if [ ! -f "$app_config" ]; then
su -c 'cp /var/www/passbolt/config/app.default.php /var/www/passbolt/config/app.php' -s /bin/sh www-data
fi
if [ -z "$PASSBOLT_GPG_SERVER_KEY_FINGERPRINT" ]; then
gpg_auto_fingerprint="$(su -c "gpg --with-fingerprint $gpg_public_key | grep fingerprint | awk '{for(i=4;i<=NF;++i)printf \$i}'" -ls /bin/sh www-data)"
export PASSBOLT_GPG_SERVER_KEY_FINGERPRINT=$gpg_auto_fingerprint
fi
if [ "$tables" -eq 0 ]; then
su -c '/var/www/passbolt/bin/cake passbolt install --no-admin --force' -s /bin/sh www-data
else
echo "Enjoy! ☮"
fi
}
php_fpm_setup() {
sed -i '/^user\s/ s:nobody:nginx:g' /etc/php5/php-fpm.conf
sed -i '/^group\s/ s:nobody:nginx:g' /etc/php5/php-fpm.conf
cp /etc/php5/php-fpm.conf /etc/php5/fpm.d/www.conf
sed -i '/^include\s/ s:^:#:' /etc/php5/fpm.d/www.conf
}
check_permissions() {
chown -R nginx:nginx /var/www/passbolt
chmod -R +w /var/www/passbolt/app/tmp
chmod +w /var/www/passbolt/app/webroot/img/public
}
email_cron_job() {
local root_crontab='/etc/crontabs/root'
local cron_task_dir='/etc/periodic/1min'
local cron_task='/etc/periodic/1min/email_queue_processing'
local process_email="/var/www/passbolt/app/Console/cake EmailQueue.sender --quiet"
root_crontab='/etc/crontabs/root'
cron_task_dir='/etc/periodic/1min'
cron_task='/etc/periodic/1min/email_queue_processing'
process_email="/var/www/passbolt/bin/cake EmailQueue.sender --quiet"
mkdir -p $cron_task_dir
if ! grep $cron_task_dir $root_crontab > /dev/null; then
echo "* * * * * run-parts $cron_task_dir" >> $root_crontab
fi
echo "* * * * * run-parts $cron_task_dir" >> $root_crontab
echo "#!/bin/sh" > $cron_task
chmod +x $cron_task
echo "su -c \"$process_email\" -ls /bin/bash nginx" >> $cron_task
crond -f -c /etc/crontabs &
echo "su -c \"$process_email\" -s /bin/sh www-data" >> $cron_task
}
if [ ! -f $gpg_private_key ] && [ ! -L $gpg_private_key ] || \
[ ! -f $gpg_public_key ] && [ ! -L $gpg_public_key ]; then
if [ ! -f "$gpg_private_key" ] && [ ! -L "$gpg_private_key" ] || \
[ ! -f "$gpg_public_key" ] && [ ! -L "$gpg_public_key" ]; then
gpg_gen_key
gpg_import_key
else
gpg_import_key
fi
if [ ! -f $core_config ] && [ ! -L $core_config ]; then
core_setup
fi
if [ ! -f $db_config ] && [ ! -L $db_config ]; then
db_setup
fi
if [ ! -f $app_config ] && [ ! -L $app_config ]; then
app_setup
fi
if [ ! -f $email_config ] && [ ! -L $email_config ]; then
email_setup
fi
if [ ! -f $ssl_key ] && [ ! -L $ssl_key ] && \
[ ! -f $ssl_cert ] && [ ! -L $ssl_cert ]; then
if [ ! -f "$ssl_key" ] && [ ! -L "$ssl_key" ] && \
[ ! -f "$ssl_cert" ] && [ ! -L "$ssl_cert" ]; then
gen_ssl_cert
fi
check_permissions
php_fpm_setup
install
php-fpm5
email_cron_job
nginx -g "pid /tmp/nginx.pid; daemon off;"
/usr/bin/supervisord -n -c /etc/supervisord.conf

View File

@ -12,18 +12,6 @@ server {
root /var/www/passbolt;
# X-Frame-Options is to prevent from clickJacking attack
add_header X-Frame-Options SAMEORIGIN;
# disable content-type sniffing on some browsers.
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter
add_header X-XSS-Protection "1; mode=block";
# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
location / {
try_files $uri $uri/ /index.php?$args;
index index.php;
@ -38,10 +26,11 @@ server {
fastcgi_param SERVER_NAME $http_host;
}
location ~* \.(jpe?g|woff|woff2|ttf|gif|png|bmp|ico|css|js|json|pdf|zip|htm|html|docx?|xlsx?|pptx?|txt|wav|swf|svg|avi|mp\d)$ {
location ~* \.(jpe?g|woff|woff2|ttf|gif|png|bmp|ico|css|js|ejs|json|pdf|zip|htm|html|docx?|xlsx?|pptx?|txt|wav|swf|svg|avi|mp\d)$ {
access_log off;
log_not_found off;
try_files $uri /app/webroot/$uri /index.php?$args;
try_files $uri /webroot/$uri /index.php?$args;
#try_files $uri /app/webroot/$uri /index.php?$args;
}
}
@ -56,21 +45,9 @@ server {
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
root /var/www/passbolt;
# X-Frame-Options is to prevent from clickJacking attack
add_header X-Frame-Options SAMEORIGIN;
# disable content-type sniffing on some browsers.
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter
add_header X-XSS-Protection "1; mode=block";
location / {
try_files $uri $uri/ /index.php?$args;
index index.php;
@ -88,6 +65,6 @@ server {
location ~* \.(jpe?g|woff|woff2|ttf|gif|png|bmp|ico|css|js|json|pdf|zip|htm|html|docx?|xlsx?|pptx?|txt|wav|swf|svg|avi|mp\d)$ {
access_log off;
log_not_found off;
try_files $uri /app/webroot/$uri /index.php?$args;
try_files $uri /webroot/$uri /index.php?$args;
}
}

36
conf/supervisord.conf Normal file
View File

@ -0,0 +1,36 @@
[unix_http_server]
file=/tmp/supervisor.sock ; (the path to the socket file)
[supervisord]
logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false ; (start in foreground if true;default false)
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
[program:php-fpm]
command=php-fpm
autostart=true
priority=5
[program:nginx]
command=nginx -g "pid /tmp/nginx.pid; daemon off;"
autostart=true
priority=10
[program:crond]
command=crond -f -c /etc/crontabs
autostart=true
priority=20

View File

@ -0,0 +1,101 @@
require 'spec_helper'
describe 'Dockerfile' do
before(:all) do
set :env, {
'DATASOURCES_DEFAULT_HOST' => '172.17.0.2',
'DATASOURCES_DEFAULT_PASSWORD' => 'P4ssb0lt',
'DATASOURCES_DEFAULT_USERNAME' => 'passbolt',
'DATASOURCES_DEFAULT_DATABASE' => 'passbolt',
'PASSBOLT_GPG_KEYRING' => '/var/lib/nginx/.gnupg'
}
@image = Docker::Image.build_from_dir(ROOT_DOCKERFILES)
set :docker_image, @image.id
set :docker_container_create_options, { 'Cmd' => '/bin/sh' }
end
let(:nginx_conf) { '/etc/nginx/nginx.conf' }
let(:site_conf) { '/etc/nginx/conf.d/default.conf' }
let(:passbolt_home) { '/var/www/passbolt' }
let(:passbolt_tmp) { '/var/www/passbolt/tmp' }
let(:passbolt_image) { '/var/www/passbolt/webroot/img/public' }
let(:passbolt_owner) { 'www-data' }
let(:exposed_ports) { [ '80', '443' ] }
let(:composer) { '/usr/local/bin/composer'}
let(:php_extensions) { [
'curl', 'gd', 'intl', 'json', 'mcrypt', 'mysqlnd', 'xsl', 'phar',
'posix', 'xml', 'xsl', 'zlib', 'ctype', 'pdo', 'gnupg', 'pdo_mysql'
] }
describe 'passbolt required php extensions' do
it 'has php extensions installed' do
php_extensions.each do |ext|
expect(command("php --ri #{ext}").exit_status).to eq 0
end
end
end
describe 'php composer' do
it 'is installed' do
expect(file(composer)).to be_executable
end
end
describe 'supervisor' do
it 'is installed' do
expect(package('supervisor')).to be_installed
end
end
describe 'passbolt directory structure' do
it 'must exist and be directories' do
expect(file(passbolt_home)).to be_a_directory
expect(file(passbolt_tmp)).to be_a_directory
expect(file(passbolt_image)).to be_a_directory
end
it 'must be owned by correct user' do
expect(file(passbolt_home)).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)
end
it 'must have the correct permissions on tmp' do
expect(file(passbolt_tmp)).to be_mode('775')
end
it 'must have the correct permissions on img' do
expect(file(passbolt_image)).to be_mode('775')
end
end
describe 'nginx configuration' do
it 'is installed correctly' do
expect(file(nginx_conf)).to exist
end
it 'has the correct permissions' do
expect(file(nginx_conf)).to be_owned_by 'root'
end
end
describe 'nginx site configuration' do
it 'is installed correctly' do
expect(file(site_conf)).to exist
end
it 'has the correct permissions' do
expect(file(site_conf)).to be_owned_by 'root'
end
end
describe 'ports exposed' do
it 'exposes port' do
exposed_ports.each do |port|
expect(@image.json['ContainerConfig']['ExposedPorts']).to include("#{port}/tcp")
end
end
end
end

View File

@ -0,0 +1,85 @@
require 'spec_helper'
describe 'passbolt_api service' do
before(:all) do
@mysql = Docker::Container.create(
'Env' => [
'MYSQL_ROOT_PASSWORD=test',
'MYSQL_DATABASE=passbolt',
'MYSQL_USER=passbolt',
'MYSQL_PASSWORD=P4ssb0lt'
],
"Healthcheck" => {
"Test": [
"CMD-SHELL",
"mysqladmin ping --silent"
]
},
'Image' => 'mysql')
@mysql.start
while @mysql.json['State']['Health']['Status'] != 'healthy'
sleep 1
end
@image = Docker::Image.build_from_dir(ROOT_DOCKERFILES)
@container = Docker::Container.create(
'Env' => [
"DATASOURCES_DEFAULT_HOST=#{@mysql.json['NetworkSettings']['IPAddress']}",
'DATASOURCES_DEFAULT_PASSWORD=P4ssb0lt',
'DATASOURCES_DEFAULT_USERNAME=passbolt',
'DATASOURCES_DEFAULT_DATABASE=passbolt',
],
'Image' => @image.id)
@container.start
@container.logs(stdout: true)
set :docker_container, @container.id
sleep 17
end
after(:all) do
@mysql.kill
@container.kill
end
let(:http_path) { "/healthcheck/status.json" }
let(:healthcheck) { 'curl -s -o /dev/null -w "%{http_code}" http://localhost/healthcheck/status.json' }
describe 'php service' do
it 'is running supervised' do
expect(process('php-fpm')).to be_running.under('supervisor')
end
it 'has its port open' do
expect(port(9000)).to be_listening.with('tcp')
end
end
describe 'email cron' do
it 'is running supervised' do
expect(service('crond')).to be_running.under('supervisor')
end
end
describe 'web service' do
it 'is running supervised' do
expect(service('nginx')).to be_running.under('supervisor')
end
it 'is listening on port 80' do
expect(port(80)).to be_listening.with('tcp')
end
it 'is listening on port 443' do
expect(port(443)).to be_listening.with('tcp')
end
end
describe 'passbolt status' do
it 'returns 200' do
expect(command(healthcheck).stdout).to eq '200'
end
end
end

9
spec/spec_helper.rb Normal file
View File

@ -0,0 +1,9 @@
require 'serverspec'
require 'docker'
ROOT_DOCKERFILES = File.expand_path('../../', __FILE__)
set :backend, :docker
Docker.options[:read_timeout] = 3600
Docker.options[:write_timeout] = 3600