diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..91fc136 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +spec +.git +.github +.editorconfig +.gitignore +Gemfile +Gemfile.lock +Rakefile +*.md +*.yml +scripts +env diff --git a/.gitignore b/.gitignore index 34d6ef3..21f1ca3 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,8 @@ fabric.properties # Generated docker files conf/*.key + +# src directory used for local development +src + +.ruby-version diff --git a/CHANGELOG.md b/CHANGELOG.md index 4190197..57a6334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased](https://github.com/passbolt/passbolt_docker/compare/v2.0.0...HEAD) + +## [2.0.0](https://github.com/passbolt/passbolt_docker/compare/v2.0.0-rc2...v2.0.0) - 2018-04-09 + +### Changed + +- Base image switched to php:7-fpm (debian based) due performance issues with passbolt and alpine based images +- Web user is now www-data +- Supervisor provides better logging to stdout +- Upload max filesize increased to 5M for avatar uploads +- README documentation updated +- Composer file loads images directory in passbolt container as a docker volume + +### Added + +- Added composer installer signature check according to official composer docs [#91](https://github.com/passbolt/passbolt_docker/pull/91) + ## [Unreleased](https://github.com/passbolt/passbolt_docker/compare/v1.6.10...HEAD) ## [1.6.10](https://github.com/passbolt/passbolt_docker/compare/v1.6.9-1...v1.6.10) - 2018-03-28 @@ -21,6 +38,40 @@ in the structure of the container: - Permissions check on the passbolt base dir has been removed as it was a big performance penalty on startup times. - Docker hub tags will now follow the PASSBOLT_VERSION-debian pattern +## [2.0.0-rc2](https://github.com/passbolt/passbolt_docker/compare/v2.0.0-rc1...v2.0.0-rc2) - 2018-02-20 + +### Changed + +- README documentation updated +- PECL_PASSBOLT_EXTENSIONS, PASSBOLT_VERSION and PASSBOLT_URL are now a docker build arg + +### Added + +- Docker composer files to run passbolt_docker in different environments +- Codacy badges and reports + +### Fixed + +- Minor issues regarding bash syntax shellcheck SC2034 and SC2166 +- Hadolint DL3003 fixed + +## [2.0.0-rc1](https://github.com/passbolt/passbolt_docker/compare/v1.6.9-1...v2.0.0-rc1) - 2018-01-17 + +### Changed + +- Moved away from plain alpine to php:7-fpm-alpine series +- Environment variables interface has been revamped and moved to application domain [default.php](https://github.com/passbolt/passbolt_api/blob/develop/config/default.php) and [app.default.php](https://github.com/passbolt/passbolt_api/blob/develop/config/app.default.php) +- PHP extensions management no longer using alpine packages +- Introduced [supervisord](http://supervisord.org/) for process monitoring +- Introduced testing framework for development purposes based on [rspec](http://rspec.info/) +- Reduced the dependencies installed in Dockerfile +- Default user moved from nginx to www-data +- Slightly changed paths of gpg serverkeys (/app/Config/gpg/serverkey.private.asc -> /config/gpg/serverkey_private.asc) +- Refactor or docker-entrypoint.sh: + - Moved away from bash to sh + - Make it compliant with [shellcheck](https://github.com/koalaman/shellcheck) + - Removed search and replace commands + ## [1.6.9-1](https://github.com/passbolt/passbolt_docker/compare/v1.6.9...v1.6.9-1) - 2018-01-15 ### Fixed diff --git a/Dockerfile b/Dockerfile index 5f345ca..ff7f9f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,28 @@ -FROM php:5-fpm +FROM php:7-fpm LABEL maintainer="diego@passbolt.com" -ENV PASSBOLT_VERSION 1.6.10 -ENV PASSBOLT_URL https://github.com/passbolt/passbolt_api/archive/v${PASSBOLT_VERSION}.tar.gz +ARG PASSBOLT_VERSION="2.0.0" +ARG PASSBOLT_URL="https://github.com/passbolt/passbolt_api/archive/v${PASSBOLT_VERSION}.tar.gz" + +ARG PHP_EXTENSIONS="gd \ + intl \ + pdo_mysql \ + xsl" + ARG PHP_EXTENSIONS="gd \ intl \ pdo_mysql \ - mcrypt \ xsl" ARG PECL_PASSBOLT_EXTENSIONS="gnupg \ - redis" + redis \ + mcrypt" ARG PASSBOLT_DEV_PACKAGES="libgpgme11-dev \ libpng-dev \ + libicu-dev \ libxslt1-dev \ libmcrypt-dev \ unzip \ @@ -31,7 +38,6 @@ RUN apt-get update \ gnupg \ libgpgme11 \ libmcrypt4 \ - libicu-dev \ mysql-client \ supervisor \ netcat \ @@ -60,15 +66,16 @@ RUN apt-get update \ && curl -sSL $PASSBOLT_URL | tar zxf - -C . --strip-components 1 \ && composer install -n --no-dev --optimize-autoloader \ && chown -R www-data:www-data . \ - && chmod 775 $(find /var/www/passbolt/app/tmp -type d) \ - && chmod 664 $(find /var/www/passbolt/app/tmp -type f) \ - && chmod 775 $(find /var/www/passbolt/app/webroot/img/public -type d) \ - && chmod 664 $(find /var/www/passbolt/app/webroot/img/public -type f) \ + && 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) \ && rm /etc/nginx/sites-enabled/default \ && apt-get purge -y --auto-remove $PASSBOLT_DEV_PACKAGES \ && rm -rf /var/lib/apt/lists/* COPY conf/passbolt.conf /etc/nginx/conf.d/default.conf +COPY conf/supervisord.conf /etc/supervisor/supervisord.conf COPY bin/docker-entrypoint.sh /docker-entrypoint.sh EXPOSE 80 443 diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..cc5bf5e --- /dev/null +++ b/Gemfile @@ -0,0 +1,8 @@ +source 'https://rubygems.org' + +group :test do + gem 'docker-api' + gem 'rake' + gem 'serverspec' + gem 'pry' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..49219f5 --- /dev/null +++ b/Gemfile.lock @@ -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 diff --git a/README.md b/README.md index 3449470..0aa11e1 100644 --- a/README.md +++ b/README.md @@ -1,117 +1,116 @@ -# Passbolt docker official image +``` + ____ __ ____ .-. + / __ \____ _____ ____/ /_ ____ / / /_ .--./ / _.---., + / /_/ / __ `/ ___/ ___/ __ \/ __ \/ / __/ '-, (__..-` \ + / ____/ /_/ (__ |__ ) /_/ / /_/ / / /_ \ | + /_/ \__,_/____/____/_,___/\____/_/\__/ `,.__. ^___.-/ + `-./ .'...--` + The open source password manager for teams `' + (c) 2018 Passbolt SARL + https://www.passbolt.com +``` +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/0de4eaf7426944769a70a2d727a9012b)](https://www.codacy.com/app/passbolt/passbolt_docker?utm_source=github.com&utm_medium=referral&utm_content=passbolt/passbolt_docker&utm_campaign=Badge_Grade) +[![Docker Pulls](https://img.shields.io/docker/pulls/passbolt/passbolt.svg?style=flat-square)](https://hub.docker.com/r/passbolt/passbolt/tags/) +[![GitHub release](https://img.shields.io/github/release/passbolt/passbolt_docker.svg?style=flat-square)](https://github.com/passbolt/passbolt_docker/releases) +[![license](https://img.shields.io/github/license/passbolt/passbolt_docker.svg?style=flat-square)](https://github.com/passbolt/passbolt_docker/LICENSE) +[![Twitter Follow](https://img.shields.io/twitter/follow/passbolt.svg?style=social&label=Follow)](https://twitter.com/passbolt) # What is passbolt? Passbolt is a free and open source password manager that allows team members to store and share credentials securely. -# Scope of this repository - -This repository will allow passbolt power users to customize their passbolt image to fit their needs on -specific environments. It is also a community meeting point to exchange feedback, request for new features -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 +# Usage -Inside the repo directory: - -`$ docker build . -t passbolt:local` - -# How to use the local image? +Users are encouraged to use [official docker image from the docker hub](https://hub.docker.com/r/passbolt/passbolt/). ## Start passbolt instance -Passbolt requires mysql to be running. The following example use mysql official docker image -with the default passbolt credentials. +Passbolt requires mysql to be running. The following example use mysql official +docker image with the default passbolt credentials. ```bash -$ docker run -e MYSQL_ROOT_PASSWORD= \ - -e MYSQL_DATABASE=passbolt \ - -e MYSQL_USER=passbolt \ - -e MYSQL_PASSWORD=P4ssb0lt \ +$ docker run -e MYSQL_ROOT_PASSWORD= \ + -e MYSQL_DATABASE= \ + -e MYSQL_USER= \ + -e 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= passbolt:local` +Then you can start passbolt just by providing the database container ip in the +`db_host` environment variable. -Once the process is done, just navigate to the following url in your browser: https://passbolt_container_ip - -### Note on starting passbolt container on MacOS systems +```bash +$ docker run --name passbolt \ + -e DATASOURCES_DEFAULT_HOST= \ + -e DATASOURCES_DEFAULT_PASSWORD= \ + -e DATASOURCES_DEFAULT_USERNAME= \ + -e DATASOURCES_DEFAULT_DATABASE= \ + -e APP_FULL_BASE_URL=https://mydomain.com \ + passbolt/passbolt:develop-debian +``` -Due to the [limitations](https://docs.docker.com/docker-for-mac/networking/#known-limitations-use-cases-and-workarounds) -of docker networking under MacOS users should start the container exposing a port on the host: +Once the container is running create your first admin user: -`$ docker run -p host_port:443 -e DB_HOST= passbolt:local` +```bash +$ docker exec passbolt su -m -c "/var/www/passbolt/bin/cake passbolt register_user -u your@email.com -f yourname -l surname -r admin" -s /bin/sh www-data +``` -And access it using https://localhost:host_port +This registration command will return a single use url required to continue the +web browser setup and finish the registration. Your passbolt instance should be +available browsing `https://yourdomain.com` # 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) - -## Advanced configuration +| Variable name | Description | Default value | +| ----------------------------------- | -------------------------------- | ------------------- | +| APP_FULL_BASE_URL | Passbolt base url | false | +| DATASOURCES_DEFAULT_HOST | Database hostname | localhost | +| DATASOURCES_DEFAULT_PORT | Database port | 3306 | +| DATASOURCES_DEFAULT_USERNAME | Database username | '' | +| DATASOURCES_DEFAULT_PASSWORD | Database password | '' | +| DATASOURCES_DEFAULT_DATABASE | Database name | '' | +| EMAIL_TRANSPORT_DEFAULT_CLASS_NAME | Email classname | Smtp | +| EMAIL_DEFAULT_FROM | From email address | you@localhost | +| EMAIL_DEFAULT_TRANSPORT | Sets transport method | default | +| EMAIL_TRANSPORT_DEFAULT_HOST | Server hostname | localhost | +| EMAIL_TRANSPORT_DEFAULT_PORT | Server port | 25 | +| EMAIL_TRANSPORT_DEFAULT_TIMEOUT | Timeout | 30 | +| EMAIL_TRANSPORT_DEFAULT_USERNAME | Username for email server auth | null | +| EMAIL_TRANSPORT_DEFAULT_PASSWORD | Password for email server auth | null | +| EMAIL_TRANSPORT_DEFAULT_CLIENT | Client | null | +| EMAIL_TRANSPORT_DEFAULT_TLS | Set tls | null | +| EMAIL_TRANSPORT_DEFAULT_URL | Set url | null | +| GNUPGHOME | path to gnupghome directory | /home/www-data/.gnupg | +| PASSBOLT_KEY_LENGTH | Gpg desired key length | 2048 | +| PASSBOLT_SUBKEY_LENGTH | Gpg desired subkey length | 2048 | +| PASSBOLT_KEY_NAME | Key owner name | Passbolt default user | +| PASSBOLT_KEY_EMAIL | Key owner email address | passbolt@yourdomain.com | +| PASSBOLT_KEY_EXPIRATION | Key expiration date | 0, never expires | +| PASSBOLT_GPG_SERVER_KEY_FINGERPRINT | GnuPG fingerprint | null | +| PASSBOLT_GPG_SERVER_KEY_PUBLIC | Path to GnuPG public server key | /var/www/passbolt/config/gpg/serverkey.asc | +| PASSBOLT_GPG_SERVER_KEY_PRIVATE | Path to GnuPG private server key | /var/www/passbolt/config/gpg/serverkey_private.asc | +| PASSBOLT_REGISTRATION_PUBLIC | Defines if users can register | false | +| PASSBOLT_SSL_FORCE | Redirects http to https | true | +| PASSBOLT_SECURITY_SET_HEADERS | Send CSP Headers | true | +| SECURITY_SALT | CakePHP security salt | __SALT__ | + +For more env variables supported please check [default.php](https://github.com/passbolt/passbolt_api/blob/master/config/default.php) +For more env variables supported please check [app.default.php](https://github.com/passbolt/passbolt_api/blob/master/config/app.default.php) + +### Configuration files What if you already have a set of gpg keys and custom configuration files for passbolt? 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/passbolt.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,58 +120,16 @@ 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. +### docker-compose -In the following example passbolt is launched with the defaults enabled usind mysql official docker container to store passbolt data: +Usage: -```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 +$ docker-compose up ``` -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. +* rng-tools or haveged are required on host machine to speed up entropy generation on containers. +This way gpg key creation on passbolt container will be faster. * mysql >= 5.6 diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..11ba867 --- /dev/null +++ b/Rakefile @@ -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 diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index 769c549..8431bcd 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -1,204 +1,98 @@ -#!/bin/bash +#!/usr/bin/env bash -set -eo pipefail +set -euo 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' +export GNUPGHOME="/home/www-data/.gnupg" + gpg_gen_key() { - su -c "$gpg --batch --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 --armor --export-secret-keys $key_email > $gpg_private_key" -ls /bin/bash www-data + su -c "gpg --armor --export $key_email > $gpg_public_key" -ls /bin/bash www-data } gpg_import_key() { - - local key_id=$(su -c "gpg --with-colons $gpg_private_key | grep sec |cut -f5 -d:" -ls /bin/bash www-data) - - su -c "$gpg --batch --import $gpg_public_key" -ls /bin/bash www-data - su -c "gpg -K $key_id" -ls /bin/bash www-data || su -c "$gpg --batch --import $gpg_private_key" -ls /bin/bash www-data -} - -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 auto_fingerprint=$(su -c "$gpg --fingerprint |grep fingerprint| awk '{for(i=4;i<=NF;++i)printf \$i}'" -ls /bin/bash www-data) - - cp $app_config{.default,} - 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,/'client'/s:'client' => $default_client:'client' => '$EMAIL_CLIENT':" $email_config - fi - sed -i "0,/tls/s:false:${EMAIL_TLS:-false}:" $email_config - + 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 } 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) - - if [ $tables -eq 0 ]; then - su -c "/var/www/passbolt/app/Console/cake install --send-anonymous-statistics true --no-admin" -ls /bin/bash www-data + tables=$(mysql \ + -u "${DATASOURCES_DEFAULT_USERNAME:-passbolt}" \ + -h "${DATASOURCES_DEFAULT_HOST:-localhost}" \ + -P "${DATASOURCES_DEFAULT_PORT:-3306}" \ + -BN -e "SHOW TABLES FROM ${DATASOURCES_DEFAULT_DATABASE:-passbolt}" \ + -p"${DATASOURCES_DEFAULT_PASSWORD:-P4ssb0lt}" |wc -l) + 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 + fi + + if [ -z "${PASSBOLT_GPG_SERVER_KEY_FINGERPRINT+xxx}" ]; 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)" + 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/bash www-data else + su -c '/var/www/passbolt/bin/cake migrations migrate' -s /bin/bash www-data echo "Enjoy! ☮" fi } email_cron_job() { + printenv > /etc/environment + sed -i 's/=\(.*\)/="\1"/g' /etc/environment cron_task='/etc/cron.d/passbolt_email' - echo "* * * * * su -c \"/var/www/passbolt/app/Console/cake EmailQueue.sender\" -s /bin/bash www-data >> /var/log/cron.log 2>&1" >> $cron_task + 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 - - cron -f -l & } -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 install - -php-fpm & - email_cron_job -nginx -g "daemon off;" +/usr/bin/supervisord -n diff --git a/conf/passbolt.conf b/conf/passbolt.conf index fb8b961..33ddfb0 100644 --- a/conf/passbolt.conf +++ b/conf/passbolt.conf @@ -2,8 +2,8 @@ server { listen 80; client_body_buffer_size 100K; - client_header_buffer_size 1k; - client_max_body_size 100k; + client_header_buffer_size 1K; + client_max_body_size 5M; client_body_timeout 10; client_header_timeout 10; @@ -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; @@ -36,12 +24,14 @@ server { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SERVER_NAME $http_host; + fastcgi_param PHP_VALUE "upload_max_filesize=5M \n post_max_size=5M"; } - 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; } } @@ -49,28 +39,25 @@ server { server { listen 443; + client_body_buffer_size 100K; + client_header_buffer_size 1K; + client_max_body_size 5M; + + client_body_timeout 10; + client_header_timeout 10; + keepalive_timeout 5 5; + send_timeout 10; + ssl on; ssl_certificate /etc/ssl/certs/certificate.crt; ssl_certificate_key /etc/ssl/certs/certificate.key; - ssl_protocols TLSv1.2; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; - ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; + ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:@STRENGTH"; 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; @@ -83,11 +70,12 @@ server { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SERVER_NAME $http_host; + fastcgi_param PHP_VALUE "upload_max_filesize=5M \n post_max_size=5M"; } 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; } } diff --git a/conf/supervisord.conf b/conf/supervisord.conf new file mode 100644 index 0000000..cb90377 --- /dev/null +++ b/conf/supervisord.conf @@ -0,0 +1,52 @@ +; supervisor config file + +[unix_http_server] +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; sockef file mode (default 0700) + +[supervisord] +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) + +; 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:///var/run/supervisor.sock ; use a unix:// URL for a unix socket + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. + +[program:php-fpm] +command=php-fpm +autostart=true +priority=5 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:nginx] +command=nginx -g "daemon off;" +autostart=true +priority=10 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:cron] +command=cron -f -l +autostart=true +priority=20 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml new file mode 100644 index 0000000..8aa644c --- /dev/null +++ b/docker-compose-dev.yml @@ -0,0 +1,33 @@ +version: '3.4' +services: + db: + image: mysql:latest + env_file: + - env/mysql.env + volumes: + - database_volume:/var/lib/mysql + ports: + - 3306 + + passbolt: + build: + context: . + args: + PECL_PASSBOLT_EXTENSIONS: "redis gnupg xdebug" + depends_on: + - db + env_file: + - env/passbolt.env + volumes: + - gpg_volume:/var/www/passbolt/config/gpg + - images_volume:/var/www/passbolt/webroot/img/public/images + - ./scripts/wait-for.sh:/usr/bin/wait-for.sh + command: ["/usr/bin/wait-for.sh", "db:3306", "--", "/docker-entrypoint.sh"] + ports: + - 80:80 + - 443:443 + +volumes: + database_volume: + gpg_volume: + images_volume: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..abfc99f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +version: '3.4' +services: + db: + image: mysql:latest + env_file: + - env/mysql.env + volumes: + - database_volume:/var/lib/mysql + ports: + - 3306 + + passbolt: + image: passbolt/passbolt:2.0.0-debian + 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 + - ./scripts/wait-for.sh:/usr/bin/wait-for.sh + tmpfs: + - /run + command: ["/usr/bin/wait-for.sh", "db:3306", "--", "/docker-entrypoint.sh"] + ports: + - 80:80 + - 443:443 + +volumes: + database_volume: + gpg_volume: + images_volume: diff --git a/env/mysql.env b/env/mysql.env new file mode 100644 index 0000000..b21fd60 --- /dev/null +++ b/env/mysql.env @@ -0,0 +1,4 @@ +MYSQL_ROOT_PASSWORD=test +MYSQL_DATABASE=passbolt +MYSQL_USER=passbolt +MYSQL_PASSWORD=P4ssb0lt diff --git a/env/passbolt.env b/env/passbolt.env new file mode 100644 index 0000000..1f0ec57 --- /dev/null +++ b/env/passbolt.env @@ -0,0 +1,12 @@ +# URL +APP_FULL_BASE_URL=https://passbolt.local + +# Database settings +DATASOURCES_DEFAULT_HOST=db +DATASOURCES_DEFAULT_USERNAME=passbolt +DATASOURCES_DEFAULT_PASSWORD=P4ssb0lt +DATASOURCES_DEFAULT_DATABASE=passbolt +DATASOURCES_DEFAULT_PORT=3306 + +# Registration +PASSBOLT_REGISTRATION_PUBLIC=true diff --git a/scripts/wait-for.sh b/scripts/wait-for.sh new file mode 100755 index 0000000..2c07ab3 --- /dev/null +++ b/scripts/wait-for.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +TIMEOUT=15 +QUIET=0 + +echoerr() { + if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi +} + +usage() { + exitcode="$1" + cat << USAGE >&2 +Usage: + $0 host:port [-t timeout] [-- command args] + -q | --quiet Do not output any status messages + -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit "$exitcode" +} + +wait_for() { + for _ in $(seq $TIMEOUT) ; do + nc -z "$HOST" "$PORT" > /dev/null 2>&1 + + result=$? + if [ $result -eq 0 ] ; then + if [ $# -gt 0 ] ; then + exec "$@" + fi + exit 0 + fi + sleep 1 + done + echo "Operation timed out" >&2 + exit 1 +} + +while [ $# -gt 0 ] +do + case "$1" in + *:* ) + HOST=$(printf "%s\n" "$1"| cut -d : -f 1) + PORT=$(printf "%s\n" "$1"| cut -d : -f 2) + shift 1 + ;; + -q | --quiet) + QUIET=1 + shift 1 + ;; + -t) + TIMEOUT="$2" + if [ "$TIMEOUT" = "" ]; then break; fi + shift 2 + ;; + --timeout=*) + TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + break + ;; + --help) + usage 0 + ;; + *) + echoerr "Unknown argument: $1" + usage 1 + ;; + esac +done + +if [ "$HOST" = "" ] || [ "$PORT" = "" ]; then + echoerr "Error: you need to provide a host and port to test." + usage 2 +fi + +wait_for "$@" diff --git a/spec/docker_image/image_spec.rb b/spec/docker_image/image_spec.rb new file mode 100644 index 0000000..81288ef --- /dev/null +++ b/spec/docker_image/image_spec.rb @@ -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', '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 diff --git a/spec/docker_runtime/runtime_spec.rb b/spec/docker_runtime/runtime_spec.rb new file mode 100644 index 0000000..0ce9062 --- /dev/null +++ b/spec/docker_runtime/runtime_spec.rb @@ -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(service('php-fpm')).to be_running.under('supervisor') + end + + it 'has its port open' do + expect(@container.json['Config']['ExposedPorts']).to have_key('9000/tcp') + end + end + + describe 'email cron' do + it 'is running supervised' do + expect(service('cron')).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(@container.json['Config']['ExposedPorts']).to have_key('80/tcp') + end + + it 'is listening on port 443' do + expect(@container.json['Config']['ExposedPorts']).to have_key('443/tcp') + end + end + + describe 'passbolt status' do + it 'returns 200' do + expect(command(healthcheck).stdout).to eq '200' + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..9620baa --- /dev/null +++ b/spec/spec_helper.rb @@ -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 +