1 - Email Configuration

Configure email

TBD

2 - SMS Configuration

Configure SMS

TBD

3 - Reverse-Proxy and TLS/SSL

Add a Reverse-Proxy and offload SSL/TLS

You should setup a TLS/SSL reverse-proxy in front of your Cavaliba docker deployment.

A reverse-proxy would perform the following tasks:

  • offload (terminate) HTTPS SSL/TLS user connections and handle certificate configuration and renewal
  • filter user source IP addresses if restricted network exposure is needed
  • perform HTTP Basic/Digest user authentication if this auth mode is selected for Cavaliba
  • produce log and audit-trail
  • on large / fault-tolerant setups, perfom user trafic load-balancing accross multiple Cavaliba nodes
  • display a Maintenance/Sorry page if it detects that cavalliba stack is down

You may use an enterprise wide / netork managed load-balancer and reverse-proxy. You can also deploy a small NGINX or HA-PROXY component on your Cavaliba host virtual machine.

Node Healthcheck / status

An external reverse-proxy or load-balancer should remove a failed node from its server pool and stop sending user traffic to failed nodes.

Additionally, a monitoring tool should check the availability of services.

Basic healthcheck can be implemented by verifying a simple TCP on http endpoint (TCP can connect). you can also check an HTTP 200 response.

Better, you may implement a deeper healthcheck on the /status/ page and check for an “OK” answer from Cavaliba. This check confirms that the application node is alive and healthy.

curl http://cavaliba/status/
OK

Example : minimal NGINX / Let’s Encrypt SSL/TLS reverse-proxy

Setup

$ sudo apt install nginx apache2-utils certbot python3-certbot-nginx
$ sudo certbot -n --agree-tos --email mycontact@mydomain.com --nginx -d mycavaliba.mydomain.com
$ sudo systemctl enable nginx

Configuration

$ sudo cat /etc/nginx/sites-enabled/default

	upstream cavaliba {
	  keepalive 60;
	  server 127.0.0.1:8000;
	}
	server
	{
	    if ($host = mycavaliba.mydomain.com ) {
	        return 301 https://$host$request_uri;
	    } # managed by Certbot
	    listen 80 default_server;
	    server_name mycavaliba.mydomain.com;
	    return 404; # managed by Certbot
	}
	server
	{
	    server_name mycavaliba.mydomain.com;
	    listen 443 ssl; # managed by Certbot
	    ssl_certificate /etc/letsencrypt/live/mycavaliba.mydomain.com/fullchain.pem; # managed by Certbot
	    ssl_certificate_key /etc/letsencrypt/live/mycavaliba.mydomain.com/privkey.pem; # managed by Certbot
	    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
	    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

	    # -------------
	    location /
	    {
	        proxy_set_header Host $http_host;
	        proxy_set_header X-Forwarded-Host $host;
	        proxy_set_header X-Forwarded-Server $host;
	        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	        #rewrite ^/cavaliba/(.*)$  /$1  break;
	        proxy_pass http://cavaliba;
	        proxy_http_version 1.1;
	        proxy_set_header Connection "";
	    }
	}

4 - Local Authentication

Configure Local Authentication

This is the default mode, which is enabled after a fresh install.

This mode is suitable for small deployment with a limited number of users, and little to no need for advanced features such as multi-factor authentication, registration/sign-up forms, password loss/change self-service, etc.

User accounts (login/password) are configured manually and directly inside in Cavaliba by an administrator.

Sign-in/Sign-out Web forms are provided by Cavaliba.

Steps to configure this mode

  • remove/comment OAUTH configuration blocs in nginx.conf and docker-compose.yml
  • in .env configure CAVALIBA_AUTH_MODE=local
  • restart docker containers
  • login with admin or other provisionned account in Cavaliba

How does-it work

In Local Authentication mode, users are authenticated ny the Django App Framework. They must exist in the Django auth structure, which is basically a specific DB table. Login, Password are the sole mandatory attributes for the purpose of authenticating a user.

Then, the user must also in the Cavaliba Data Model, with the same login. This model is common to all authentication modes. It defines who is the user (extended attributes, group membership, directory pages), if and what he can do when logged-in, what notifications he will receive, etc.

Add a user

Manually from Cavaliba :

  • open the DB Admin tool from Cavaliba main menu
  • select the django user table
  • clic the “add user” top-right button and fill-in the form : login, password
  • get back to cavaliba
  • go to the Cavaliba User module
  • add the user (same login) with extended informations, group membership, etc.

CLI / Shell:

 $ cd cavaliba/
 $ docker exec -it cavaliba_app python manage.py shell
  >>> from django.contrib.auth.models import User
  >>> user = User.objects.create_user("john", "lennon@thebeatles.com", "johnpassword")

Suspend / Remove a user

  • open the DB Admin tool from Cavaliba main menu
  • select the django user table
  • select the appropriate user
  • edit the form, disable / remove and save

As this point, the user can’t sign-in to cavaliba. But he still exists in the Data Model and can receive notifications (Sirene).

  • go to the Cavaliba User module
  • select the user (same login) and disable/remove

Change a user’s password

Web interface :

  • open the DB Admin tool from Cavaliba main menu
  • select the django user table
  • select the appropriate user
  • use the change password tool

CLI / Shell

 $ cd cavaliba/
 $ docker exec -it cavaliba_app python manage.py changepassword LOGIN

5 - Basic Authentication

Configure Basic Authentication

Basic Authentication is an external authentication mode. It is not performed by the Cavaliba application itself. A front Web server is in charge of this authentication and will set standard HTTP Authentication headers, passed to Cavaliba.

This mode, like the Local Authentication mode, is suitable for small deployment, with no advanced authentication and access management features. User management is to be performed both externally and inside Cavaliba to map external users to Cavaliba users.

Internal Cavaliba Web Server (NGINX)

Basic Authentication can be configured at the Cavaliba container with the NGINX Web server.

Steps:

  • edit the nginx.conf file next to the docker-compose.yml, to uncomment basic authentication lines
  • create a standard htpassword file (htpasswd)
  • edit the docker-compose.yml to uncomment the line mounting this htpassword file inside the nginx container
  • in .env configure CAVALIBA_AUTH_MODE=basic
  • restart docker containers
  • populate / manage the htpasswd file on the server

You may then edit and update dynamically the htpasswd file, to add or remove users, change their password, etc.

External Web-Server / Reverse-PRoxy

Basic Authentication can also be configured at any upstream Web server / Reverse-Proxy which may be set up before reaching Cavaliba Application.

This Reverse-Proxy must set the HTTP Authentication Header to let Cavaliba obtain the user’s login value.

Cavaliba users

Don’t forget to always map external users (in the htpasswd), to users objects in the Cavaliba User model with the same login value. Add group membership, roles, permissions, etc.

6 - SAML/OIDC Authentication

Configure SAML/OIDC Authentication

SAML/OIDC Authentication is an external authentication mode. It is called OAUTH2 in Cavaliba.

It is performed by a companion component, namely oauth2_proxy, which is included in Cavaliba as an additional container, ready to be started and configured.

This model is suitable for modern/large scale deployment. It offloads all the access / authentication process to an external Authentication server (IdP, Identity Provider). It may provide Multi-factor strong authentication, and many user self-service to manage their account and credentials depending on the IDP.

Identity Providers are external services such as Keycloak, OKTA, Microsoft Azure AD and numerous other providers.

steps to configure

Identity Provider

  • Register your Cavaliba deployement to your IDP (identity provider)

Provision users in advance

  • if coming from other AUTH MODE such as local, create users matching users in your IDP, with appropriate permissions

System & Docker

  • in the .env docker file, configure the IDP parameters (client id, secret, URLs)
  • in the .env docker file, configure CAVALIBA_AUTH_MODE=oauth2
  • in docker-compose.yaml, uncomment the oauth2_proxy container bloc
  • in nginx.conf, uncomment the oauth2 configuration blocs ; comment basic authentication if any
  • restart docker containers

Setup a local Keycloak IDP

TBD - start a local Keycloak container, configure User directory, authentication workflows. Register Cavaliba as a a new Service Provider for this IDP.

Bonus : LDAP Authentication

LDAP authentication is a mean to authenticate users against a central Directory like Openldap, Lemonldap or Active Directory.

Although not immediately available in Cavaliba it can be set up with the OAUTH2 mode requesting a local Identity Provider (like Keycloak) which in turn, queries an LDAP Directory.

7 - LDAP Authentication

Configure LDAP Authentication

Cavaliba doesn’t provide out of the box LDAP authentication.

See SAML/OIDC for indirect LDAP Authentication through an ODIC/SAML local Identity Provider such as Keycloak.

8 - Forced Authentication

Configure Forced Authentication

Forced authentication means no authentication. No authentication is performed and all connections are mapped to a single internal Cavaliba user. It is indented for developpment purpose, or Robinson Crusoe on a desert island.

Don’t use in production, or even in QUA / Tests, on a shared network.

9 - CLI tools

Command Line tools

Cavaliba comes with various command-line tools.

First, create alias for easy access :

$ alias cavaliba="docker exec -it cavaliba_app python manage.py cavaliba"
$ alias cavmanage="docker exec -it cavaliba_app python manage.py"

Add them to your ~/.basrc for persistence.

The cavmanagecommand will launch the integrated management framework.

You can now type :

$ cavmanage
$ cavaliba --help

You’ll see all available commands.

version

new: 3.15.12

$ cavaliba version
3.17.1

Load schema and data

$ cavaliba load /files/demo/
$ cavaliba load /files/demo/100_site.yaml --pass 2

Note: absolute folder for /files, inside containers ; local folder is files/ on host.

Load CSV data file

$ cavaliba load /files/import/user.csv --pipeline user_import_csv

multipass

--pass 2

The --pass option is recommanded for schema, because cross-references between schemas requires some schemas to be created before others. Multiple pass resolve dependencies.

progress

Display progression for large files :

--progress 

File: /files/import/user.csv ...
Found: 55456 objects
Pipeline: user_import_csv
Loading to DB...
100 done
200 done
(...)

first/last

Choose quantity (first/last lines to process) ; 0 for last is unlimited.

--first 1 
--last 0

log view

$ cavaliba log
$ cavaliba log --first 0 --last 1000

log purge

apply automatic log purge:

$ cavaliba log --log_purge
log entries: 203718
log deleted (old) : 48 entries
log done

purge all logs (!):

$ cavaliba log --log_purge_all
log entries: 203676
log deleted (all) : 203676 entries
log done

conf view

$ cavaliba conf
$ cavaliba conf --text
$ cavaliba conf --json
$ cavaliba conf --yaml
$ cavaliba conf --yaml --key LOG_KEEP_DAYS_ERROR

conf sync

Creates default entries / purge orphan. Run automatically during startup.

$ cavaliba conf --confsync --verbose

conf backup/restore

Backup conf:

$ cavaliba conf > files/export/conf_backup.json

Reload conf (from container accessible folder)

$ cavaliba conf --conf_file /files/export/conf_backup.json --verbose

data query/export

Get available schemas:

$ cavaliba schema

Query a schema:

$ cavaliba schema --schema user 
- login: admin
  displayname: Built-in Global Admin user
  is_enabled: true
  want_notifications: true
  want_24: true
  want_email: true
  classname: _user

- login: i.trento
  displayname: Izongua Trento
  is_enabled: true
  want_notifications: true
  want_24: true
  want_email: true
  classname: _user

  (...)

Query a schema and a specific object:

$ cavaliba cavaliba_export --schema user --key testuser01
- login: testuser01
  email: testuser01@test.com
  mobile: 0123456789
  displayname: Test User 01
  description: Test User 01
  is_enabled: true
  want_notifications: true
  want_24: true
  want_sms: true
  want_email: true
  classname: _user

Specify an output format:

$ cavaliba cavaliba_export --schema site --key testsite01 --json
[
    {
        "classname": "site",
        "keyname": "testsite01",
        "handle": "testsite01",
        "displayname": "Test Site 01",
        "p_read": null,
        "p_update": null,
        "p_delete": null,
        "is_enabled": true,
        "sirene_group": [
            "testgroup01"
        ]
    }
]

Run the integrated test suite

First, either create an empty test database in your database server or use the root DµB user in your docker .env file for variable CAVALIBA_DB_USER. Alternatively you may prefer to grant create database privileges to your current CAVALIBA_DB_USER.

Then,

$ cavmanage test

Options exists such as:

$ cavmanage test --keepdb
$ cavmanage test -v 2
$ cavmanage test --keepdb app_home.tests.test_home.ConfTest

You may need to create a test database manually in MariaDB. Example:

docker exec -it cavaliba_db mysql -u root -p
create database test_cavaliba;
show grants for 'cavaliba';
GRANT ALL PRIVILEGES ON `test_cavaliba`.* TO `cavaliba`@`%`;
flush privileges;

10 - Docker configuration

Docker ENV entries for docker-compose and Cavaliba

Thoe .envdocker file holds several important options.

CAVALIBA_DOCKER_IMAGE

CAVALIBA_DOCKER_IMAGE=cavaliba/cavaliba:3.10

Name of the docker registry, docker image and version for the Cavaliba Application. The default value displayed above queries Docker Hub, for the cavaliba repository, cavaliba image object, with a version 3.10. You can use any public/private image repository that can be accessed from your docker host.

Cavaliba Authentication and built-in Admin account

# local, basic, oauth2, forced
CAVALIBA_AUTH_MODE=local
# if forced mode
CAVALIBA_FORCE_LOGIN=admin
# admin built-in account
CAVALIBA_ADMIN_PASSWORD=change_again
CAVALIBA_ADMIN_EMAIL=admin@mydomain.com

# UI session duration max (default 3600 seconds)
CAVALIBA_SESSION_DURATION=36000

Internal Built-in account used to access Cavaliba Web Application and DB web admin tool. It is created during the first launch of Cavaliba, and re-creation is attempted at every new launch.

The login is admin.

To change the password, use the DB web admin tool. You can also use the django manage tool with the createsuperuser command.

CAVALIBA_PORT

CAVALIBA_PORT=8000

Network port the cavaliba nginx container will expose and listen to on the Host.

CAVALIBA_CSRF_TRUSTED_ORIGINS

CAVALIBA_CSRF_TRUSTED_ORIGINS="http://127.0.0.1:8000 https://mycavaliba.mydomain.com"

String and blank separated list of schema, FQDN and port for hosts hosting the Cavaliba Application. CSRF protection will be valid only for the listed entries.

You must set this entry according to your environment.

CAVALIBA_ALLOWED_HOSTS

CAVALIBA_ALLOWED_HOSTS="localhost 127.0.0.1 *"

From Django documentation: A list of strings representing the host/domain names that this Django site can serve. This is a security measure to prevent HTTP Host header attacks, which are possible even under many seemingly-safe web server configurations.

CAVALIBA_SECRET_KEY

CAVALIBA_SECRET_KEY=changeme_with_a_long_string

Set a random long string to protect session cookies used by Cavaliba. If you change the value and restart Cavaliba, all users will be signed-out of the application.

CAVALIBA_CIPHER_KEY

 CAVALIBA_CIPHER_KEY="a_very_secret_string"

The secret key to encrypt sensitive information in the Cavaliba Database. If you lose or change this value, previous content from the database will be lost.

Use case: SMS content for the SMS_Send feature in Sirene App.

CAVALIBA_TENANT

CAVALIBA_TENANT=cavaliba

The name/prefix of the docker objects (container name, docker network) created whden starting cavaliba. Use one value per docker-compose.yml file to start several simultaneous Cavaliba instance on a same host. Don’t forget to also select a different network listening port for each. Each instance is isolated on a different docker bridge.

Change this value if you plan to host several Cavaliba isolated deployment on the same Host/VM.

DB options

CAVALIBA_DB_ENGINE=django.db.backends.mysql
CAVALIBA_DB_HOST=cavaliba_db
CAVALIBA_DB_PORT=3306
CAVALIBA_DB_DATABASE=cavaliba
CAVALIBA_DB_USER=cavaliba
CAVALIBA_DB_PASSWORD=changeme_please
CAVALIBA_DB_ROOT_PASSWORD=changeme_please_also

By default, Cavaliba is provided with an internal MariaDB database instance (container), dedicated to the Cavaliba application. This parameters define the important values to create the DB and connect the Application.

The CAVALIBA_DB_HOST is the docker DNS name of the database server. If you decide to use an external DB server (either physical/VM or cloud service) you need to replace with the exact hostname / FQDN. For single or multiple Cavaliba instance in docker mode, you don’t need to change this value.

If the MariaDB is dedicated to Cavaliba (as with the the provided configuration), there is no issue to having identical values for PASSWORD and ROOT_PASSWORD.

For the moment, only MariaDB/MySQL is supported. PostGreSQL may be added later.

Identity Federation options

OAUTH2_PROXY_PROVIDER="oidc"
OAUTH2_PROXY_PROVIDER_DISPLAY_NAME=""
OAUTH2_PROXY_OIDC_ISSUER_URL=""
OAUTH2_PROXY_CLIENT_ID=""
OAUTH2_PROXY_CLIENT_SECRET=""
OAUTH2_PROXY_COOKIE_SECRET=""
OAUTH2_PROXY_REDIRECT_URL=""

Email/SMTP configurations

CAVALIBA_EMAIL_HOST=localhost
CAVALIBA_EMAIL_PORT=25
# uncomment if authentication needed
#CAVALIBA_EMAIL_USER=noreply
#CAVALIBA_EMAIL_PASSWORD=changeme

SMS configurations

CAVALIBA_SMS_URL="https://my.sms.provider.com/api/"
CAVALIBA_SMS_LOGIN="my_sms_account"
CAVALIBA_SMS_PASSWORD="changeme"

Cache

CAVALIBA_CACHE_DEFAULT_URL="redis://cavaliba_redis:6379"
CAVALIBA_CACHE_SESSION_URL="redis://cavaliba_redis:6379"
CAVALIBA_CELERY_BROKER_URL="redis://cavaliba_redis:6379"
CAVALIBA_CELERY_RESULT_BACKEND="redis://cavaliba_redis:6379"

Other

# keep 0 in PRODUCTION
CAVALIBA_DEBUG=0
CAVALIBA_DEBUG_IP="127.0.0.1 172.19.0.1"