From b9fea361c90be4af4985cda1375c9949cfa02b0b Mon Sep 17 00:00:00 2001
From: Clement Michaud
Date: Sun, 3 Nov 2019 13:07:02 +0100
Subject: [PATCH] Create suite for testing the docker image.
Running this suite is the first advice given by the
bootstrap script to help the user move forward.
This commit also updates the documentation to reflect
changes introduced by the Go rewrite.
---
cmd/authelia-scripts/cmd_bootstrap.go | 3 +-
cmd/authelia-scripts/cmd_docker.go | 13 +-
docs/authelia-scripts.md | 4 +-
docs/build-and-dev.md | 29 +-
docs/deployment-dev.md | 47 ++--
docs/deployment-production.md | 26 +-
docs/getting-started.md | 15 +-
docs/security.md | 7 +-
docs/suites.md | 28 +-
...mpose.dockerhub.yml => docker-compose.yml} | 4 +-
.../nginx/backend/html/home/index.html | 98 ++++---
test/helpers/GetIdentityLink.ts | 7 +-
.../scenarii/TwoFactorAuthentication.ts | 11 +-
test/suites/docker-image/README.md | 13 +
test/suites/docker-image/config.yml | 261 ++++++++++++++++++
test/suites/docker-image/environment.ts | 37 +++
test/suites/docker-image/test.ts | 27 ++
17 files changed, 507 insertions(+), 123 deletions(-)
rename example/compose/authelia/{docker-compose.dockerhub.yml => docker-compose.yml} (56%)
create mode 100644 test/suites/docker-image/README.md
create mode 100644 test/suites/docker-image/config.yml
create mode 100644 test/suites/docker-image/environment.ts
create mode 100644 test/suites/docker-image/test.ts
diff --git a/cmd/authelia-scripts/cmd_bootstrap.go b/cmd/authelia-scripts/cmd_bootstrap.go
index a76d007a8..61f38ae77 100644
--- a/cmd/authelia-scripts/cmd_bootstrap.go
+++ b/cmd/authelia-scripts/cmd_bootstrap.go
@@ -211,6 +211,7 @@ func Bootstrap(cobraCmd *cobra.Command, args []string) {
bootstrapPrintln("Building development Docker images...")
buildDockerImages()
+ DockerBuildOfficialImage()
bootstrapPrintln("Installing Kubernetes dependencies for testing in /tmp... (no junk installed on host)")
installKubernetesDependencies()
@@ -220,6 +221,6 @@ func Bootstrap(cobraCmd *cobra.Command, args []string) {
bootstrapPrintln("Preparing /etc/hosts to serve subdomains of example.com...")
prepareHostsFile()
- bootstrapPrintln("Run 'authelia-scripts suites start basic' to start Authelia and visit https://home.example.com:8080.")
+ bootstrapPrintln("Run 'authelia-scripts suites start docker-image' to start Authelia and visit https://home.example.com:8080.")
bootstrapPrintln("More details at https://github.com/clems4ever/authelia/blob/master/docs/getting-started.md")
}
diff --git a/cmd/authelia-scripts/cmd_docker.go b/cmd/authelia-scripts/cmd_docker.go
index 7e375089a..dce9efcbd 100644
--- a/cmd/authelia-scripts/cmd_docker.go
+++ b/cmd/authelia-scripts/cmd_docker.go
@@ -3,22 +3,29 @@ package main
import (
"errors"
"fmt"
+ "log"
"os"
"github.com/spf13/cobra"
)
+func DockerBuildOfficialImage() error {
+ docker := &Docker{}
+ return docker.Build(IntermediateDockerImageName, ".")
+}
+
// DockerBuildCmd Command for building docker image of Authelia.
var DockerBuildCmd = &cobra.Command{
Use: "build",
Short: "Build the docker image of Authelia",
Run: func(cmd *cobra.Command, args []string) {
- docker := &Docker{}
- err := docker.Build(IntermediateDockerImageName, ".")
+ err := DockerBuildOfficialImage()
+
if err != nil {
- panic(err)
+ log.Fatal(err)
}
+ docker := &Docker{}
err = docker.Tag(IntermediateDockerImageName, DockerImageName)
if err != nil {
diff --git a/docs/authelia-scripts.md b/docs/authelia-scripts.md
index 211ae367a..3b5b94894 100644
--- a/docs/authelia-scripts.md
+++ b/docs/authelia-scripts.md
@@ -16,8 +16,8 @@ For instance, you can build Authelia with:
authelia-scripts build
-Or start the *basic* suite with:
+Or start the *docker-image* suite with:
- authelia-scripts suites start basic
+ authelia-scripts suites start docker-image
You will find more information in the scripts usage helpers.
\ No newline at end of file
diff --git a/docs/build-and-dev.md b/docs/build-and-dev.md
index 61dc56546..4afe8d7bc 100644
--- a/docs/build-and-dev.md
+++ b/docs/build-and-dev.md
@@ -1,23 +1,24 @@
# Build and dev
-**Authelia** is written in Typescript and built with [Authelia scripts](./authelia-scripts.md).
+**Authelia** is written in Go and comes with a dedicated CLI called [authelia-scripts](./authelia-scripts.md)
+which is provided after running `source bootstrap.sh`. This CLI provides many useful tools to help you during
+development.
-In order to build and contribute to **Authelia**, you need to make sure Node with version >= 8 and < 10
-and NPM is installed on your machine.
+In order to build and contribute to **Authelia**, you need to make sure Node with version >= 8 and < 12,
+Go v1.13 and Docker is installed on your machine.
## Build
**Authelia** is made of two parts: the frontend and the backend.
The frontend is a [React](https://reactjs.org/) application written in Typescript and
-the backend is an express application also written in Typescript.
-
+the backend is Go application.
The following command builds **Authelia** under dist/:
authelia-scripts build
-And then you can also build the Docker image with:
+Or you can also build the Alpine-based official Docker image with:
authelia-scripts docker build
@@ -25,8 +26,8 @@ And then you can also build the Docker image with:
In order to ease development, Authelia uses the concept of [suites]. This is
a kind of virutal environment for **Authelia**, it allows you to run **Authelia** in a complete
-environment, develop and test your patches. A hot-reload feature has been implemented so that
-you can test your changes in realtime.
+ecosystem, develop and test your patches. A hot-reload feature has been implemented so that
+you can test your changes right after the file has been saved.
The next command will start the suite called [basic](../test/suites/basic/README.md):
@@ -36,13 +37,13 @@ Then, edit the code and observe how **Authelia** is automatically updated.
### Unit tests
-To run the unit tests written in Mocha, run:
+To run the unit tests written, run:
authelia-scripts unittest
### Integration tests
-Integration tests also run with Mocha and are based on Selenium. They generally
+Integration tests run with Mocha and are based on Selenium. They generally
require a complete environment made of several components like redis, mongo and a LDAP
to run. That's why [suites] have been created. At this point, the *basic* suite should
already be running and you can run the tests related to this suite with the following
@@ -50,5 +51,13 @@ command:
authelia-scripts suites test
+You don't need to start the suite before testing it. Given your environment is not running
+any suite, just use the following command to test the basic suite.
+
+ authelia-scripts suites test basic
+
+The suite will be spawned, tests will be run and then the suite will be teared down
+automatically.
+
[suites]: ./suites.md
diff --git a/docs/deployment-dev.md b/docs/deployment-dev.md
index a7ec9d078..b5c7ba607 100644
--- a/docs/deployment-dev.md
+++ b/docs/deployment-dev.md
@@ -18,17 +18,17 @@ non resilient to failures.*
In some cases, like protecting personal websites, it can be fine to use
**Authelia** in a non highly-available setup. We can
-achieve that in order to reduce the number of components to only two: Authelia
-and nginx.
+achieve that in order to reduce the number of components to only two: a
+reverse proxy such as nginx or Traefik and Authelia as a companion of the
+proxy.
As for a regular deployment in production, you need to install **Authelia**
-either by pulling the Docker image or installing the npm package and run
-it with a configuration file passed as argument.
+either by pulling the Docker image or building distributable version.
-## Deploy with npm
+## Build and deploy the distributable version
- npm install -g authelia
- authelia /path/to/your/config.yml
+ authelia-scripts build
+ PUBLIC_DIR=./dist/public_html ./dist/authelia -config /path/to/your/config.yml
## Deploy with Docker
@@ -40,21 +40,27 @@ it with a configuration file passed as argument.
You also need to install nginx and take [example/compose/nginx/minimal/nginx.conf](./example/compose/nginx/minimal/nginx.conf)
as an example for your configuration.
+## Deploy Traefik
+
+TODO
+
## Discard components
### Discard MongoDB
There is an option in the configuration file to discard MongoDB and use
-your local filesystem to store the database data. This option will therefore
-prevent you from running multiple instances of **Authelia** in parallel.
-Consequently, this option is not meant to be used in production.
+your local filesystem to store data in a sqlite3 database. This option will
+therefore prevent you from running multiple instances of **Authelia** in
+parallel.
+Consequently, this option is not meant to be used in production or at least
+not one that should scale out.
Here is the configuration block you should use:
storage:
- # The directory where the DB files will be saved
+ # The directory where the sqlite3 file will be saved
local:
- path: /var/lib/authelia/store
+ path: /var/lib/authelia/db.sqlite3
### Discard Redis
@@ -62,8 +68,8 @@ There is an option in the configuration file to discard Redis and use the
memory of the server to store the KV data. This option will therefore
prevent you from running multiple instances of **Authelia** in parallel and
will make you lose user sessions if the application restarts. This
-concretely means that all your users will need to authenticate again in
-that case. Hence, this option is not meant to be used in production.
+concretely means that all your users will need to authenticate again after
+a restart of Authelia. Hence, this option is not meant to be used in production.
To use memory instead of a Redis backend, just comment out the Redis
connection details in the following block:
@@ -98,19 +104,22 @@ The content of this file is as follows:
- admins
- dev
-The password is hashed and salted as it is in LDAP servers with salted SHA-512. Here is a one-liner to generate such hashed password:
+The password is hashed and salted as it is in LDAP servers with salted SHA-512
+(more hash algorithms such as Argon2 will be provided in the future).
+Here is a one-liner to generate such hashed password:
- $ npm run hash-password mypassword
+ $ authelia-scripts hash-password mypassword
$6$rounds=50000$BpLnfgDsc2WD8F2q$PumMwig8O0uIe9SgneL8Cm1FvUniOzpqBrH.uQE3aZR4K1dHsQldu5gEjJZsXcO./v3itfz6CXTDTJgeh5e8t.
-Copy this newly hashed password into your `users_database.yml` file, prefixed with `{CRYPT}` as shown in the example file above.
+Copy this newly hashed password into your `users_database.yml` file, prefixed with
+`{CRYPT}` as shown in the example file above.
Once the file is created, edit the configuration file with the following
block (as used in [config.yml](../test/suites/basic/config.yml)):
authentication_backend:
file:
- path: /etc/authelia/users_database.yml
+ path: /path/to/the/users_database.yml
instead of (used in [config.template.yml](../config.template.yml)):
@@ -152,6 +161,6 @@ a production environment. That being said, in some cases it is just fine and
writing an Ansible playbook to automate all this process is ok.
We would really be more than happy to review such a PR.
In the meantime, you can check the *basic* [suite](./suites.md) to see all this
-in real example.
+in a real example.
[Getting Started]: ./getting-started.md
diff --git a/docs/deployment-production.md b/docs/deployment-production.md
index a4e274ab1..e95948b39 100644
--- a/docs/deployment-production.md
+++ b/docs/deployment-production.md
@@ -1,7 +1,8 @@
# Deployment for Production
**Authelia** can be deployed on bare metal or on Kubernetes with two
-different kind of artifacts: an npm package or a Docker image.
+different kind of artifacts: the distributable version (binary and public_html)
+or a Docker image.
**NOTE:** If not done already, we highly recommend you first follow the
[Getting Started] documentation.
@@ -11,21 +12,28 @@ different kind of artifacts: an npm package or a Docker image.
**Authelia** has been designed to be a proxy companion handling the
authentication and authorization requests for your entire infrastructure.
-As **Authelia** will be key in your architecture, it requires several
-components to make it highly-available. Deploying it in production means having an LDAP server for storing the information about the users, a Redis cache to store the user sessions in a distributed manner, a
-MongoDB to persist user configurations and one or more nginx reverse proxies configured to be used with Authelia. With such a setup **Authelia** can easily be scaled to multiple instances to evenly handle the traffic.
+As **Authelia** will be key to your architecture, it requires several
+components to make it highly-available. Deploying it in production means having
+an LDAP server for storing the information about the users, a Redis cache to
+store the user sessions in a distributed manner, a MongoDB to persist user
+configurations and one or more nginx reverse proxies configured to be used with
+Authelia. With such a setup **Authelia** can easily be scaled to multiple instances
+to evenly handle the traffic.
-**NOTE:** If you don't have all those components, don't worry, there is a way to deploy **Authelia** with only nginx. This is described in [Deployment for Devs].
+**NOTE:** If you don't have all those components, don't worry, there is a way to
+deploy **Authelia** with only nginx. This is described in [Deployment for Devs].
Here are the available steps to deploy **Authelia** given
the configuration file is **/path/to/your/config.yml**. Note that you can
create your own configuration file from [config.template.yml] located at
the root of the repo.
-### Deploy With NPM
+### Deploy with the distributable version
- npm install -g authelia
- authelia /path/to/your/config.yml
+ # Build it if not done already
+ authelia-scripts build
+
+ PUBLIC_DIR=./dist/public_html authelia -config /path/to/your/config.yml
### Deploy With Docker
@@ -49,7 +57,7 @@ for more information.
Ansible would be a very good candidate to automate the installation of such
an infrastructure on bare metal. We would be more than happy to review any PR on that matter.
-Regarding Kubernetes, the right way to go would be to write a helm recipe.
+Regarding Kubernetes, the right way to go would be to write a Helm recipe.
Again, we would be glad to review any PR implementing this.
diff --git a/docs/getting-started.md b/docs/getting-started.md
index c524cc1eb..700bd7d29 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -1,18 +1,17 @@
# Getting Started
-**Authelia** can be tested in a matter of seconds with docker-compose based
-on the latest image available on [Dockerhub].
+**Authelia** can be tested in a matter of seconds with Docker and docker-compose.
-In order to deploy the latest release locally, run the following command and
-follow the instructions of bootstrap.sh:
+In order to deploy the current version of Authelia locally, run the following
+command and follow the instructions of bootstrap.sh:
source bootstrap.sh
-Then, start the *dockerhub* [suite].
+Then, start the *docker-image* [suite].
- authelia-scripts suites start dockerhub
+ authelia-scripts suites start docker-image
-A [suite] is kind of a virtual environment for running Authelia.
+A [suite] is kind of a virtual environment for running Authelia in a complete ecosystem.
If you want more details please read the related [documentation](./suites.md).
## Test it!
@@ -43,7 +42,7 @@ Since we're running a test environment, we provide a fake webmail called
*MailCatcher* from which you can checkout the email and confirm
your identity.
The webmail is accessible from
-[http://mail.example.com:8080](http://mail.example.com:8085).
+[http://mail.example.com:8080](http://mail.example.com:8080).
Enjoy!
diff --git a/docs/security.md b/docs/security.md
index b2e1e2c02..884983240 100644
--- a/docs/security.md
+++ b/docs/security.md
@@ -23,7 +23,7 @@ post nginx has written on [HSTS].
## Content-Security-Policy
-Authelia's portal is protected against XSS using the content
+Authelia's portal is protected against some XSS using the content
security policy mechanism that is documented
[here](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP). This protection
will reject untrusted payloads threatening your users during the authentication
@@ -51,10 +51,6 @@ add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
```
-## Helmet
-
-To improve even more the security, [Helmet] has been added to **Authelia**.
-
## Contributing
If you find possible vulnerabilities or threats, do not hesitate to contribute
@@ -62,4 +58,3 @@ either by writing a test case demonstrating the possible attack and if
possible some solutions to prevent it or submit a PR.
[HSTS]: https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
-[Helmet]: https://helmetjs.github.io/
diff --git a/docs/suites.md b/docs/suites.md
index fa1cda372..e34228c99 100644
--- a/docs/suites.md
+++ b/docs/suites.md
@@ -6,7 +6,7 @@ suite which is a kind of virtual environment for Authelia, it allows to create a
components such as nginx, redis or mongo in which Authelia can run and be tested.
This abstraction allows to prepare an environment for manual testing during development and also to
-craft and run integration tests.
+craft and run integration tests efficiently.
## Start a suite.
@@ -28,16 +28,19 @@ and this will run the tests related to the running suite.
### Run tests of non-running suite
-However, if no suite is running and you still want to test a particular suite like *complete*.
+However, if no suite is running and you still want to test a particular suite like *high-availability*.
You can do so with the next command:
- authelia-scripts suites test complete
+ authelia-scripts suites test high-availability
-This command will run the tests for the *complete* suite using the built version of Authelia that
-should be located in *dist*.
+This command will run the tests for the *high-availability* suite. Beware that running tests of a
+non-running suite implies the tests run against the distributable version of Authelia instead of
+the current development version. If you made some patches, you must build the distributable version
+before running the test command:
-WARNING: Authelia must be built with `authelia-scripts build` and possibly
-`authelia-scripts docker build` before running this command.
+ # Build authelia before running the tests against the suite.
+ authelia-scripts build
+ authelia-scripts docker build
### Run all tests of all suites
@@ -45,10 +48,17 @@ Running all tests is easy. Make sure that no suite is already running and run:
authelia-scripts suites test
+Beware that the distributable version of Authelia is tested in that case. Don't
+forget to build Authelia including your patches before running the command.
+
+
+ # Build authelia before running the tests against the suite.
+ authelia-scripts build
+ authelia-scripts docker build
+
### Run tests in headless mode
-In order to run the tests without seeing the windows creating and vanishing, one
-can run the tests in headless mode with:
+In order to run the tests in headless mode, use the following command:
authelia-scripts suites test --headless
diff --git a/example/compose/authelia/docker-compose.dockerhub.yml b/example/compose/authelia/docker-compose.yml
similarity index 56%
rename from example/compose/authelia/docker-compose.dockerhub.yml
rename to example/compose/authelia/docker-compose.yml
index a78db4968..d3e5bb8b5 100644
--- a/example/compose/authelia/docker-compose.dockerhub.yml
+++ b/example/compose/authelia/docker-compose.yml
@@ -1,10 +1,10 @@
version: '2'
services:
authelia:
- image: clems4ever/authelia:latest
+ image: authelia:dist
restart: always
volumes:
- - ./test/suites/dockerhub/config.yml:/etc/authelia/config.yml:ro
+ - ./test/suites/docker-image/config.yml:/etc/authelia/config.yml:ro
environment:
- NODE_TLS_REJECT_UNAUTHORIZED=0
depends_on:
diff --git a/example/compose/nginx/backend/html/home/index.html b/example/compose/nginx/backend/html/home/index.html
index c17a53d62..dc577ce71 100644
--- a/example/compose/nginx/backend/html/home/index.html
+++ b/example/compose/nginx/backend/html/home/index.html
@@ -77,56 +77,54 @@
These rules are extracted from the configuration file
config.template.yml.
- default_policy: deny
-
- rules:
- # Rules applied to everyone
- - domain: public.example.com
- policy: bypass
- - domain: secure.example.com
- policy: two_factor
- - domain: singlefactor.example.com
- policy: one_factor
-
- # Rules applied to 'admin' group
- - domain: 'mx2.mail.example.com'
- subject: 'group:admin'
- policy: deny
- - domain: '*.example.com'
- subject: 'group:admin'
- policy: two_factor
-
- # Rules applied to 'dev' group
- - domain: dev.example.com
- resources:
- - '^/groups/dev/.*$'
- subject: 'group:dev'
- policy: two_factor
-
- # Rules applied to user 'john'
- - domain: dev.example.com
- resources:
- - '^/users/john/.*$'
- subject: 'user:john'
- policy: two_factor
-
-
- # Rules applied to user 'harry'
- - domain: dev.example.com
- resources:
- - '^/users/harry/.*$'
- subject: 'user:harry'
- policy: two_factor
-
- # Rules applied to user 'bob'
- - domain: '*.mail.example.com'
- subject: 'user:bob'
- policy: two_factor
- - domain: 'dev.example.com'
- resources:
- - '^/users/bob/.*$'
- subject: 'user:bob'
- policy: two_factor
+ default_policy: deny
+
+ rules:
+ # Rules applied to everyone
+ - domain: public.example.com
+ policy: two_factor
+ - domain: singlefactor.example.com
+ policy: one_factor
+
+ # Rules applied to 'admin' group
+ - domain: 'mx2.mail.example.com'
+ subject: 'group:admin'
+ policy: deny
+ - domain: '*.example.com'
+ subject: 'group:admin'
+ policy: two_factor
+
+ # Rules applied to 'dev' group
+ - domain: dev.example.com
+ resources:
+ - '^/groups/dev/.*$'
+ subject: 'group:dev'
+ policy: two_factor
+
+ # Rules applied to user 'john'
+ - domain: dev.example.com
+ resources:
+ - '^/users/john/.*$'
+ subject: 'user:john'
+ policy: two_factor
+
+
+ # Rules applied to user 'harry'
+ - domain: dev.example.com
+ resources:
+ - '^/users/harry/.*$'
+ subject: 'user:harry'
+ policy: two_factor
+
+ # Rules applied to user 'bob'
+ - domain: '*.mail.example.com'
+ subject: 'user:bob'
+ policy: two_factor
+ - domain: 'dev.example.com'
+ resources:
+ - '^/users/bob/.*$'
+ subject: 'user:bob'
+ policy: two_factor