1 - Quickstart

Initial instructions to get started fast

Ultra quick recap

  1. prepare docker
  2. git clone https://www.github.com/cavaliba/cavaliba.git
  3. cp env.template .env
  4. vi .env to customize URL, DB and admin passwords
  5. docker compose up
  6. open browser to root URL , sign-in with configured admin account

Prerequisite : setup docker

You need a docker available environment. You can skip this part if your docker environment is already setup.

You don’t have to provide other middleware such as a web server, database server, etc. They are provided as docker containers with cavaliba.

For example, on a Linux Debian/Ubuntu fresh install such as a Virtual Machine or a Desktop you may have to perform the following actions:

$ sudo apt-get update
$ sudo apt-get install ca-certificates curl
$ sudo install -m 0755 -d /etc/apt/keyrings
$ sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
$ sudo chmod a+r /etc/apt/keyrings/docker.asc
$ echo   "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
       $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |   sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

$ sudo groupadd docker
$ sudo usermod -aG docker $USER
$ newgrp docker

Then, perform a quick docker confirmation test, by running a minimal hello world public docker image:

$ docker version
$ docker run hello-world

If you see dcoker versions, and a Docker Hello world message, everything is fine. The Hello-World image was downloded and started successfully on your host.

Get Cavaliba from Github

In your working directory, enter the following command to download cavaliba from its github public repository:

$ cd myworkdir/
$ git clone --depth=1  https://www.github.com/cavaliba/cavaliba.git

You should see a new cavaliba/ directory with startup files, source code, and empty data folders.

To check downloaded content:

$ cd cavaliba

$ tree -L 1
├── LICENSE
├── README.md
├── files/                       <= files in/out with Cavaliba (import, mail, ...)
├── django/                      <= source code
├── docker-compose.yml.template  <= docker starter
├── env.template                 <= cavaliba configuration template
└── nginx.conf.template          <= logo/ and custom web templates

$ tree files
files
├── dev
├── export
├── import
├── logo
│   ├── logo_cavaliba.png
│   └── logo.png
├── mail
├── sms
└── templates
    └── app_sirene
        ├── _footer.html.OFF
        ├── _navbar.html.OFF
        ├── _pub_critical.html.OFF
        ├── _pub_info.html.OFF
        ├── _pub_major.html.OFF
        ├── _pub_minor.html.OFF
        ├── _pub_ok.html.OFF
        └── _pub_other.html.OFF

alternative to git

If you don’t want or have git tools you can proceed like this:

$ cd myworkdir/

$ curl -L -o cavaliba.zip https://github.com/cavaliba/cavaliba/archive/refs/heads/main.zip
$ unzip cavaliba.zip
$ cd cavaliba-main

# or
$ wget https://github.com/cavaliba/cavaliba/archive/refs/heads/main.zip
$ unzip main.zip

Prepare files from templates

$ cp nginx.conf.template nginx.conf
$ cp docker-compose.yml.template docker-compose.yml
$ cp env.template .env

Don’t forget the dot at the beginning of the .env filename.

Customize .env

This is the only file you need to customize to get started quickly.

The .envfile contains important parameters such as passwords and security items needed to start the application.

Edit the relevant part in this newly created .env file like this:

$ vi .env


# HERE, important security configuration : set allowed hostnames (FQDN, URL and port) 
DJANGO_CSRF_TRUSTED_ORIGINS="http://localhost:8000 http://myhost.mydomain.com:8000 http://192.168.0.1"

CAVALIBA_TENANT=cavaliba                        <= HERE, change if you run multiple cavaliba instance on your host
CAVALIBA_PORT=8000                              <= HERE, set an available "http like" port on your host ; 80, 8000, 8080
CAVALIBA_DOCKER_IMAGE=cavaliba/cavaliba:3.10    

CAVALIBA_DB_ENGINE=django.db.backends.mysql
CAVALIBA_DB_HOST=cavaliba_db                    <= don't change, this is the container name
CAVALIBA_DB_PORT=3306
CAVALIBA_DB_DATABASE=cavaliba
CAVALIBA_DB_USER=cavaliba                       
CAVALIBA_DB_PASSWORD=changeme_please            <= HERE, set a password for the internal cavaliba Database
CAVALIBA_DB_ROOT_PASSWORD=changeme_please_also  <= HERE, set a different password for the DB root account

CAVALIBA_ADMIN_PASSWORD=change_again            <= HERE, set a cavaliba app 'admin' built-in account inital password
CAVALIBA_ADMIN_EMAIL=admin@mydomain.com         <= Later, after cavaliba email advanced configuration

# sensitive fields encryption in DB
CAVALIBA_CIPHER_KEY="Change me. Please..."               <= HERE, set an encryption key for sensistive DB content. Keep it safe.

# cookie protection
DJANGO_SECRET_KEY=changeme_with_a_long_string   <= HERE, set a long random string for cookie protection

Start the application

Once the .env file is ready you may start cavaliba as follow:

$ docker compose up

You may later add a -d option to run docker in the background.

You may observe the different startup steps:

  • download of various docker images : nginx, mariadb, redis, and cavaliba (from Docker Hub)
  • mariadb database initial creation and startup
  • redis cache server startup
  • cavaliba async tasks container startup (celery)
  • cavaliba app container startup (init app, translations, admin account update, DB migrations, etc.)
  • web server startup (nginx)

Inspect the result like this (truncated) :

$ docker ps
IMAGE                  (...) STATUS                    PORTS                      NAMES
nginx:1.25.2                Up 10 seconds             0.0.0.0:8000->80/tcp       cavaliba_nginx
cavaliba/cavaliba:3.10      Up 10 seconds             8001/tcp                   cavaliba_app
cavaliba/cavaliba:3.10      Up 10 seconds                                        cavaliba_celery
redis:7.0.2-alpine3.16      Up 13 seconds (healthy)   6379/tcp                   cavaliba_redis
mariadb:10.10               Up 13 seconds (healthy)   3306/tcp                   cavaliba_db

You’ll notice a new db folder in your cavaliba/ main folder. It contains the (persistent) database content.

Connect and sign-in with admin account

Open your browser to your host / port combination :

firefox http://myhost:8000/home/private/

You’ll presented with the sign-in screen. Use the adminbuilt-in account, with the password you provided in the .env file.

If anything went wrong

Check running containers:

docker ps -a

Check logs for error messages:

 docker logs -f cavaliba_nginx
 docker logs -f cavaliba_app
 docker logs -f cavaliba_celery
 docker logs -f cavaliba_db
 docker logs -f cavaliba_redis

CSRF error message in the app ?

 verify the .env file and the DJANGO CSRF_ALLOWED_HOSTS value

Error in sign-in Web form

 double-check your admin password in the .env file

What to do next ?

You may :

  • have a quick tour of the application including importing demo data

  • go to additional setup : configuration, authentication, TLS/SSL, permissions, backups, emails, sms, etc.

2 - Configuration

Configuration

Configuration

2.1 - 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 "";
	    }
	}

2.2 - 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

  • connect to Cavaliba with an admin level account
  • go to the conf module
  • select the user tab.
  • select AUTH_MODE = local
  • save the configuration

Be sure to remove other authentication mode you may have already configured such as OAUTH SAML/OIDC modes.

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

2.3 - 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 externally, as well as inside Cavaliba.

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 containtener
  • restart Cavaliba (the cavaliba_nginx container)
  • in Cavaliba / Conf, configure AUTH_MODE=Basic
  • 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.

2.4 - 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)

Docker .env file

  • Configure the .env docker file with the received registration parameters (client id, secret, URLs)

Oauth2 Proxy configuration

  • configure/adapt the oa2p_xxx.cfg to match the SAML/OIDC requirements of your Identity Provider

Start the Docker OAUTH2 component

  • uncomment the oauth2_proxy block in the docker-compose.yml file
  • start the cavaliba_oa2p container

Configure NGINX to catch/redirect authentication to oauth2

  • uncomment the nginx.conf directives to enable the oauth2 authentication workflow
  • restart the cavaliba nginx container

Inform Cavaliba to use OAUTH2

  • in Cavaliba/Conf, select AUTH_MODE=oauth2

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.

2.5 - 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.

2.6 - 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.

3 - User and Access

User, and access

3.1 - Concepts

AAA Concept

Users, Groups, Permissions, and Roles are the foundation of the security model in Cavaliba. They describe who can access Cavaliba, and what action theyr are allowed to perform.

They are used for Authentication (user identity and proof), Authorization (what can users do) and Accounting (audit trail, who did what). These three topics are known and refered to as the AAA Model.

Users and Groups are also used to describe your Organization or Company from a business point of view. For example within the Notification App, you may wish to notify all HR Users. An “HR Group” will provide this notification target.

What are Users, Roles, Groups, Permissions ?

  • Users are objects describing a real person using Cavaliba, or being refered to in the data model
  • Groups are sets of similar users related to any characteristic you like (organization, business activity, Position, …)
  • Permissions are atomic auhtorizations to perform a specific action in Cavaliba and the data within.
  • Roles are sets of permissions associated with users and groups to be grant those permissions.

To map users to permissions, you use Roles.

Groups are organizational units to group people without no security criteria.

User creation and modification

  • From Cavaliba Web User Interface (UI)
  • From YAML / JSON / CSV file import with cavaliba command line (CLI)
  • From REST API calls
  • From dynamic (Just-In-Time) Provisiong, after a first usccessful (external) authentication

User authentication

Cavaliba supports several mechanisms :

  • Default/Local Application mode with web login/pawsword sign-in forms, and an in-app internal user base
  • External HTTP Basic/Digest Authentication - at the NGINX Tier ; Cavaliba uses HTTP Authentication Headers
  • External SAML / OIDC federated identity - at the NGINX Tier ; an authentication workflow is triggered to an external Identity provider : Keycloak, Okta, Microsoft 365, etc. Response Token are used by Cavaliba to identify the user
  • No Authentication / Forced authentication : in this single user mode, a unique user is always logged in to Cavaliba.

A direct AD/LDAP authentication may be implemented later. However it is already available with the Federation mode to a Keycloak Identity Provider which in turns use an AD/LDAP as a user backend.

Tips and tricks

You should not map Users to Roles directly. Use groups instead to gather similar users, and then link groups to roles.

Technical implementations

Internally, Roles are Groups objects, but with a specific attribut “is_role”. They can be edited to add permissions, which groups cannot.

4 - Sirene Notification App

Sirene Notification App

Sirene App provide a one-clic notification system to contact users about an important business event.

Sirene Concepts

When an important event occurs, like a scheduled Maintenance, an IT outage, or a security breach, you may need to communicate with your users to inform, warn, provide recommandations, activate emergency response plan, etc.

Sirene is a tool included in Cavaliba to provide fast and high-quality notifications.

Key points:

  • Sirene uses the integrated data model provided by Cavaliba for a description of users, sites, groups, services, and their relationships
  • Sirene provides Templates for predefined / frequent messages. They can always be adjusted at notification time.
  • Sirene provides several notifications channels : Web (several kind), Email, SMS
  • Sirene computes automatically target users for a specific message (see Notification Targets)
  • Sirene let you send messages updates (additional notifications)
  • Sirene removes old notification and send them to an archive for audit trail and statistics for example.

Sirene is not intended to be an “automated notification system”, connected to some monitoring solution. It is rather designed to be used manually by a human operator in charge of decisions and notifications. You can still decide to use the Sirene API for automatic notifications though.

Sirene Data Model

Sirene uses the following model : Sites, Groups of Sites, Applications and Services, Users, Groups of users, Customers.

  • Sites describe geographical entities like offices, head quarters, agency, factories, …
  • Groups of Sites are sets of site, based on any criteria like region, geography, activity, business-unit, etc.
  • Applications and Services are assets which may be the subject of a notification : IT application, business process, etc.
  • Users and Groups of Users are any sets of regular Cavaliba Users
  • Customers can be used in a Service Provider model, where a company has many customers and would like to notfy a selected subset of these customers.

The relationship between applications and sites is a key element to understand : Sites object contains a list of subscribed applications for which they want to be notified when a notification targets an application. Subscription means this site wants to be notified for this applicaiton.

Notification Targets and Decision

A Sirene Operator can send notifications to any combination of targets : Sites, Groups of Sites, Applications, Users, Groups of Users, Customers.

Sirene computes automatically the list of users to be notified with the following rules:

  • a notification to a site will reach all users registered with the Site (under the “site notification” attribute)

  • a notification to a group of site will reach all users of each Site in the Group of Sites.

  • a notification to a group of users will obviously reach each user in the group

  • a notification to an application/service will reach :

    • all users registered directly with the application (like the person in charge of the service, mainteners, operators)
    • all users of sites which subscribed to the application/service

Each users is notified once per message notification, that is he receives only one Email / SMS notification even if he belongs to several notifications targets.

Channels

Cavaliba Sirene can send notifications through various communication channels :

  • Public Web Page available to all person, authenticated or not, who can reach the Cavaliba Web system
  • Trusted Web Page available to all person with a trusted origin (trusted source IP address)
  • Private Web Page available to all users authenticated successfully in Cavaliba.
  • Restricted Web Page available to some specific users, after authentication in Cavaliba
  • Email to specific users or groups of users
  • SMS to specific users or groups of users

At a later point, Cavaliba may provide Slack or Teams Channel notifications

Templates - Prepare your messages

It’s not a good idea to write a message from a blank formular in the middle of the night during an urgent situation.

That’s what templates are for. You can prepare as many messages models as you wan’t, including target groups, hints, public web page content, private web page content and more.

During the notification process a Sirene Operators will :

  • select an appropriate template from a list
  • review the message recommandation and the intended use case if any
  • review and adapt the message if needed : content, channels and targets (sites, groups)
  • … send with a clic

Of course, an operator can always craft a new message from a blank form during an event, but templates are really there to improve the quality and speed of notifications.

Message Removal and Archives

When the triggering condition is over, or after a configurable period of time, Sirene will remove notifications displayed in the various Web Page and move the message to an Archive Repository.

Sirene Users and Operators can consult this archive to view past events and the communication around them.

Message Updates

An operator can send updates to a an active notification before it is removed and sent to archive.

It’s a good idea to send an Update before removing (archiving) a message to inform users about the end of the event.

For example, you can keep your users updated with the progress of a long / important maintenance, and expected time of reopening of the service.

User preferences

Users can configure individual preferences regarding the notifications channels :

  • activate / desactivate Mail or SMS notifications
  • enable 24/7 notifications (outside of Business Hours)
  • configure a secondary Email address or Mobile Phone number.

Use case examples

  • information : a new system / a new software version will be available
  • outage : an incident or IT outage, you wan’to notify users, and IT mainteners.
  • maintenance : some system will go to maintenance and won’t be available for a period of time
  • security alert : warn some users that an extra caution is required in case of security event
  • crisis management : open a situation room, call for crisis managers

5 - Reference

Data Models

5.1 - AAA - User Model

Reference

YAML Model

_user:j.doe:
    #_action: create|create_update|delete|enable|disable
    external_id: id#545
    email: j.doe@a.a.com
    mobile: '0101010101'
    firstname: John
    lastname: Doe
    displayname: John DOE
    description: TESTDOE
    is_enabled: true
    want_notifications: true
    want_24: true
    want_email: true
    groups:
      - demogroup_1
      - demogroup_2

5.2 - AAA - Group Model

Reference

YAML Model

_group:demogroup_1:
	  displayname: Demo Group 1
	  description: Demo Group 1 for tests
	  subgroups: 
	    - mysubgroup01
	    - mysubgroup02
	  users: 
	    - f.kafka
	    - b.evans

5.3 - AAA - Role Model

Reference

YAML Model

_role:role1:
	  displayname: Demo Role 1
	  description: Demo Group 1 for tests
	  subgroups: 
	    - group03
	    - group04
	  users: 
	  	# not recommended ; use subgroups instead
	    - t.robinson
	  permissions:
	  	- p_user_read
	  	- p_user_write

Predefined Roles for Cavaliba Apps

Cavaliba Appls comes with a set of predefined Roles, which provide reasonable permissions package.

You can create additional roles and assign custom sets of permissions.

5.4 - DATA - Class/Schema

DataClass and Schema

A Schema describes a DataClass with global and custom fields.

Global Fields for all classes

These fields are default fields, alwas available to all DataClass schema.

  • keyname - unique name of the class ; slug, no special chars ; must be unique

  • _displayname - a short string for humans

  • _page - string, page name in the Web UI displaying the list of available classes

  • _order - int, display order in the Web UI

  • _icon - string, name of a FontAwsome Icon to display in UI

  • role…. - strings, name of a Cavaliba Role to control authorizations on that class/schema

    • _role_show : the class is visible in the UI
    • _role_access :
    • _role_read : Instances of this class can be viewed
    • _role_create : Instances of this class can be created
    • _role_update : Instances of this class can be updated (if they exist)
    • _role_delete : Instances of this class can be deleted
    • _role_onoff : Instances can be enabled/disabled in this class
    • _role_import : Allow import (YAML/JSON) of instances from this class
    • _role_export : Allow export (YAML/JSON) of instances from this class

Custom Fields

Each DataClass Schema can have zero or more custom fields. These fields can be single-valued or multi-valued. They have a type from one of the available field types below.

Field name must be a valid slug string (unique, no special chararcter) within the DataClass schema.

Available field types:

  • string
  • int
  • float
  • date
  • boolean
  • ipv4
  • text
  • enumerate
  • sirene_data
  • sirene_group
  • sirene_user

YAML Example

The _action attribute describes the operation to be performed on the object.


_schema:test_class:
    #_action: create
    _displayname: TestClass
    _is_enabled: yes
    _order: 900
    _page: Test        
    _icon: fa-question
    _role_show: role_data_test_ro
    _role_access: role_data_test_ro
    _role_read: role_data_test_ro
    _role_create: role_data_test_rw
    _role_update: role_data_test_rw
    _role_delete: role_data_test_rw
    _role_onoff: role_data_test_rw
    _role_import: role_data_test_admin
    _role_export: role_data_test_admin

    description:
       displayname: Description
       dataformat: string
       dataformat_ext: ""
       cardinal_min: 0
       cardinal_max: 1
       default : ""
    mystring:
        displayname: MyString
        dataformat: string
        description: description ...            
        order: 100
        page: Strings
    myint:
        displayname: MyInt
        dataformat: int
        order: 200
        description: description ...            
        page: Numbers
    myfloat:
        displayname: MyFloat
        dataformat: float
        description: description ...
        order: 210
        page: Numbers
    myboolean:
        displayname: MyBoolean
        dataformat: boolean
        description: check to activate !
        order: 300
        page: Booleans
    mydate:
        displayname: MyDate
        description: format YYYY-MM-DD
        dataformat: date
        order: 400
        page: Other
    myipv4:
        displayname: MyIPV4
        dataformat: ipv4
        description: A.B.C.D or A.B.C.D/mask
        order: 410
        page: Other

# ---

    my_sirene_group:
        displayname: MysireneGroup
        dataformat: sirene_group
        description: select cavaliba UserGroup object(s)
        order: 500
        page: Objects
        cardinal_max: 0

# ---

    my_sirene_app:      
        displayname: MySireneData(app)
        dataformat: sirene_data
        dataformat_ext: app
        description: Select Cavaliba Data object(s)
        order: 510
        page: Objects
        cardinal_max: 0
# ---

    my_enumerate_ok_ko:      
        displayname: MyEnumerate_OK_KO
        dataformat: enumerate
        dataformat_ext: enum_OK_KO
        description: Choose a value
        order: 505
        page: Static-Enum
        cardinal_min: 0
        cardinal_max: 1

    my_enumerate_ok_ko_na:
        displayname: MyEnumerate_OK_KO_NA
        dataformat: enumerate
        dataformat_ext: enum_OK_KO_NA
        description: Choose a value
        order: 510
        page: Static-Enum
        cardinal_min: 0
        cardinal_max: 1



    my_enumerate_abc:      
        displayname: MyEnumerate_ABC
        dataformat: enumerate
        dataformat_ext: enum_ABC
        description: Choose an enum_ABC value
        order: 520
        page: Static-Enum
        cardinal_min: 0
        cardinal_max: 1

    my_enumerate_abc_multi:      
        displayname: MyEnumerate_ABC_Multi
        dataformat: enumerate
        dataformat_ext: enum_ABC
        description: Choose enum_ABC values
        order: 525
        page: Static-Enum
        cardinal_min: 0
        cardinal_max: 0


    my_enumerate_abcde:      
        displayname: Maturite_ABCDE
        dataformat: enumerate
        dataformat_ext: maturite_ABCDE
        description: Choose an maturite_ABCDE value
        order: 530
        page: Static-Enum
        cardinal_min: 0
        cardinal_max: 1

    my_enumerate_abcde_multi:      
        displayname: Maturite_ABCDE_Multi
        dataformat: enumerate
        dataformat_ext: maturite_ABCDE
        description: Choose maturite_ABCDE values
        order: 535
        page: Static-Enum
        cardinal_min: 0
        cardinal_max: 0

# ---

    my_user:      
        displayname: My Sirene User
        dataformat: sirene_user
        description: Select a Cavaliba User
        order: 550
        page: Orga
        cardinal_min: 0
        cardinal_max: 1

    my_user_multi:
        displayname: My Sirene User Multi
        dataformat: sirene_user
        description: Select one or more Cavaliba Users
        order: 551
        page: Orga
        cardinal_min: 0
        cardinal_max: 0

5.5 - DATA - Authorizations

Data Reference

Data Authorization model

User access to Data Ressources requires a combination of two authorizations:

  1. Global - Operations Authorization on All Data Ressources (access/read/write/…) ; given by Permissions.

  2. Class/Schema - Operations Authorizations on specific Class/Schema ; given by Roles attached to Class/Schema

Global permissions

Global operations on all Data objects is controlled by a small set Permissions.

     ("p_data_access", "Access UI", "", False),
     ("p_data_class_ro", "Access RO on classes", "", False),
     ("p_data_class_rw", "Access RWD on classes", "", False),
     ("p_data_schema_ro", "Schema RO", "", False),
     ("p_data_schema_rw", "Schema RWD", "", False),
     ("p_data_instance_ro", "Global RO on instances", "", False),
     ("p_data_instance_rw", "Global RWD on instances", "", False),
     ("p_data_import", "Use file or YAML import tool", "", False),
     ("p_data_admin", "Other sensitive actions on data app", "", False),

you may provide thes Permissions to users through standard Role/Group. You can use Built-in Roles.

Built-in Roles

Give the following Roles to Users and Groups to provide Global Authorization.


ROLES_BUILTIN = {
    'role_data_ro': [
        "p_data_access",
        "p_data_class_ro",
        "p_data_schema_ro",
        "p_data_instance_ro",

    ],
    # class: create/update/delete/onoff
    'role_data_rw': [
        "p_data_access", 
        "p_data_class_rw",
        "p_data_schema_rw",
        "p_data_instance_rw",
    ],
    # class: import/export
    'role_data_admin': [
        "p_data_access", 
        "p_data_class_rw",
        "p_data_schema_rw",
        "p_data_instance_rw",
        "p_data_import",
        "p_data_admin",
    ],
}

Per Class/Schema Authorizations

Per Class/Schema Authorization is provided by Roles and is mandatory in addition to Global Authorization.

Each class has a set of _role attributes to define which Role controls allowed operation on the Class and its Instances.

# role definitions ...

_role:role_data_test_ro:
    displayname: Role DATA test RO
    subgroups:
      - usergroup1


_role:role_data_test_rw:
    displayname: Role DATA test RW
    subgroups:
      - usergroup2

_role:role_data_test_admin:
    displayname: Role DATA test ADMIN
    subgroups:
      - usergroup3

# .. can be used in specific Class/Schema definition:

_schema:test_class:
    
    _role_show: role_data_test_ro
    _role_access: role_data_test_ro
    _role_read: role_data_test_ro
    _role_create: role_data_test_rw
    _role_update: role_data_test_rw
    _role_delete: role_data_test_rw
    _role_onoff: role_data_test_rw
    _role_import: role_data_test_admin
    _role_export: role_data_test_admin

Per Instance Authorization

Not implemented.

Per Field Authorization

Not implemented.

5.6 - DATA - DataViews

Reference

A DataView describes a subset of a DataClass to be presented to the users in the Web Interface.

You can define multiple DataViews per DataClass for different type of users.

DataView objects

DataViews are implemented as regular DataClass objects and can thus be managed from the Web UI, REST API, console CLI, import/export, etc.

DataViews

# optional Role definitions to manage DataView authorizations
_role:role_data_view_ro:
    displayname: Role data:data_view:ro
    subgroups:
      - admin_cavaliba

_role:role_data_view_rw:
    displayname: Role data:data_view:rw
    subgroups:
      - admin_cavaliba

_role:role_data_view_admin:
    displayname: Role data:data_view:admin
    subgroups:
      - admin_cavaliba

# DataView definition as a specific DataClass structure

_schema:data_view:
    _displayname: Data Views
    _is_enabled: yes
    _icon: fa-table
    _order: 810
    _page: Internal
    _role_show: role_data_view_ro
    _role_access: role_data_view_ro
    _role_read: role_data_view_ro
    _role_create: role_data_view_rw
    _role_update: role_data_view_rw
    _role_delete: role_data_view_rw
    _role_onoff: role_data_view_rw
    _role_import: role_data_view_admin
    _role_export: role_data_view_admin
    description:
        #_action: create_or_update          
        displayname: Description
        order: 100
        dataformat: string
        dataformat_ext: ""
        cardinal_min: 0
        cardinal_max: 1
        default : ""
    # DataClass on which a DataView operates
    classname:
        displayname: classname
        cardinal_min: 0
        cardinal_max: 1
        order: 110
        dataformat: string
    # nested YAML structure with columns and operations on columns
    content:
        displayname: content
        cardinal_min: 0
        cardinal_max: 1
        order: 120
        dataformat: text
        dataformat_ext: yaml

Content format

The classname attribute defines the DataClass on which the DataView will operate.

The content attribute in the DataView object defines what and how to present the DataClass data. It is a nested YAML structure which lists columns to be displayed and operator to apply on each of these columns.

keyname, displayname and last_update are common attributes to all DataClass. They can be omitted from the DataViews columns. If none is requested , Cavaliba adds keyname by default.

Each entry is the name of a column as it will be displayed.

If the from operator is added to a column entry, it indicates wich DataClass attribute should provide content for that column.

An invalid from value will create an empty value for that column.

the intend use of the column/from combination is to provide nicer column names to users.

Some new operators may be added in the future, like aggregate values or computed values from other columns.

# DataView content attribute 
columns:
- keyname
- displayname
- last_update
- city
- zipcode
- my_enumerate_ok_ko
- my_enumerate_ok_ko_na
- my_enumerate_abc
- my_enumerate_abc_multi
- my_enumerate_abcde
- my_enumerate_abcde_multi
- newcol
- ZipAgain:
    from: zipcode
- newcol_invalid:
    from: non_existent_col
    other_operator: tobedone

DataView Example

The follwing YAML snippet create a DataView on the site objects to present some relevant geographical informations.

It says:

  • create a user available DataView for the DataClass site objects.
  • show a table with the following columns: address, region, …
  • some of the columns will have a different name than the underlying DataClass attribute

data_view:site_postal:
  #_action: create_or_update
  classname: site
  is_enabled: true
  displayname: MySiteView_postal
  description: This View displays Geographical information about sites
  content: |
    columns:
      - Site Name:
          from: keyname
      - address
      - Zip Code
          from: zipcode
      - Site city:
          from: city
      - country
        

5.7 - DATA - Enumerate

Reference

Enumerate are predefined lists of values which can be used as Field attributes when defining DataClass models. Enumerate values have various additional options : display widget, description or intended use, etc.

When editing DataClass objects, user will be presented with a list of available values only.

When displaying a DataClass objets, nice widgets can be presented to users.

Enumerate usecase examples:

  • status : OK, KO, N/A
  • maturity_level : Good, Medium, Average, Bad, Terrible, NotAvailable, Unkown, ToBeChecked, …
  • grade : A,B,C,D,E
  • fruits : apple, pear, mango, …
  • publish_status : draft, published, retracted
  • color : red, blue, yellow

Enumerate objects

Enumerate are implemented as regular DataClass objects and can thus be managed from the Web UI, REST API, console CLI, import/export, etc.

# optional Role definitions to manage DataView authorizations
_role:role_data_enumerate_ro:
    displayname: Role data:data_enumerate:ro
    subgroups:
      - admin_meteosi


_role:role_data_enumerate_rw:
    displayname: Role data:data_enumerate:rw
    subgroups:
      - admin_meteosi

_role:role_data_enumerate_admin:
    displayname: Role data:data_enumerate:admin
    subgroups:
      - admin_meteosi

# Enumerate definition as a specific DataClass structure
_schema:data_enumerate:
    _displayname: Data Enumerates
    _is_enabled: yes
    _icon: fa-table
    _order: 810
    _page: Internal
    _role_show: role_data_enumerate_ro
    _role_access: role_data_enumerate_ro
    _role_read: role_data_enumerate_ro
    _role_create: role_data_enumerate_rw
    _role_update: role_data_enumerate_rw
    _role_delete: role_data_enumerate_rw
    _role_onoff: role_data_enumerate_rw
    _role_import: role_data_enumerate_admin
    _role_export: role_data_enumerate_admin
    description:
        #_action: create_or_update          
        displayname: Description
        order: 100
        dataformat: string
        dataformat_ext: ""
        cardinal_min: 0
        cardinal_max: 1
        default : ""
    # nested YAML content, with values, widget, see below
    content:
        displayname: content
        cardinal_min: 0
        cardinal_max: 1
        page: input
        order: 120
        dataformat: text
        dataformat_ext: yaml 

Enumerate Content format

The content attribute defines available values and their options.

- value: "A"
  is_enabled: True
  widget: "green_circle"
  description: "A value to use when eveything is good"
- value: "A"
  widget: "green_circle"
  description: "A value to use when eveything is good"
- value: "Z"
  is_enabled: False     
  description: "deprecated; not available"

Available Widget values

        "red_circle":    "&#x1f534;",
        "orange_circle": "&#x1F7E0;",
        "yellow_circle": "&#x1F7E1;",
        "green_circle":  "&#x1F7E2;",
        "purple_circle": "&#1F7E3;",
        "brown_circle":  "&#1F7E4;",
        "blue_circle":   "&#x1F535;",
        "white_circle":  "&#x25EF;",
        "black_circle":  "&#11044;",
        "default" : ""

Using Enumerate in DataClass models


_schema:my_test_class:
    #_action: create
    _displayname: TestClass

    # (...)

    my_enumerate_abc:      
        displayname: MyEnumerate_ABC
        dataformat: enumerate
        dataformat_ext: enum_ABC
        description: Choose an enum_ABC value
        order: 520
        page: Static-Enum
        cardinal_min: 0
        cardinal_max: 1

    my_enumerate_abc_multi:      
        displayname: MyEnumerate_ABC_Multi
        dataformat: enumerate
        dataformat_ext: enum_ABC
        description: Choose enum_ABC values
        order: 525
        page: Static-Enum
        cardinal_min: 0
        cardinal_max: 0

    # (...)

Enumerate Examples

# ---------------------
# standard enumerates
# ---------------------
data_enumerate:enum_ABC:
  # ACTION
  is_enabled: True
  displayname: "ABC Scale"
  description: "Neutral ABC Scale"
  content: |
    - value: "A"
      widget: "green_circle"
      description: "A"

    - value: "B"
      widget: "orange_circle"

    - value: "C"
      widget: "red_circle"    


data_enumerate:maturite_ABCDE:
  # ACTION
  is_enabled: True
  displayname: "ABCDE Maturity scale"
  description: "Use for product assessment"
  content: |
    - value: "A - Perfect"
      #is_enabled: True
      widget: "green_circle"
      description: "Use if perfect"

    - value: "B - Correct"
      widget: "yellow_circle"

    - value: "C - Average"
      widget: "orange_circle"

    - value: "D - Bad"
      widget: "red_circle"

    - value: "E - Alert"
      widget: "black_circle"

    - value: "n/a"
      widget: "white_circle"

    - value: "to be checked"
      widget: "blue_circle"

    - value: "?"
      # no widget, text value will be displayed    


data_enumerate:enum_OK_KO:
  # ACTION
  is_enabled: True
  displayname: "OK/KO Scale"
  content: |
    - value: "OK"
      widget: "green_circle"
      description: "OK"

    - value: "KO"
      widget: "red_circle"    


data_enumerate:enum_OK_KO_NA:
  # ACTION
  is_enabled: True
  displayname: "OK/KO/NA Scale"
  content: |
    - value: "OK"
      widget: "green_circle"
      description: "OK"

    - value: "KO"
      widget: "red_circle"

    - value: "n/a"
      widget: "white_circle"

    - value: "?"    

5.8 - Sirene - Models

Reference

Sirene Model

severity (built-in)


     "na"       # white
     "critical" # black
     "major"    # red
     "minor"    # yellow
     "info"     # blue
     "other"    # grey
     "ok"       # green

Categories

_sirene_category:incident:
  longname: Incident
  description: Incidents (outage)
  is_enabled: true

_sirene_category:maintenance:
  longname: Maintenance
  description: n/a
  is_enabled: true

Template

_sirene:test_template:
      title: Incident
      severity: ok
      category: info
      description: My description
      publicpage: public_ok
      has_privatepage: true
      body: |
        <p>Hello</p>
        <p>Incident on <b>test apps</b>.</p>
        <p>IT Team</p>        
      has_email: false
      has_sms: false
      notify_group: demo
      notify_site: site01, site02
      notify_sitegroup: region01
      notify_app: testapp, testapp2
      notify_customer: Acme_Corp

_sirene:maintenance:
    title: "IT Maintenance"
    severity: info
    category: maintenance
    publicpage: public_maintenance
    has_privatepage: true
    has_email: true
    has_sms: false    
    message: |
      <pre>
      Hi
      A maintenance is starting.
      Please check <a href="http://wwwW.cavaliba.com">Cavaliba</a> for updates.
      IT Team
      </pre>      
    has_email: true
    has_sms: false
    description: "Unspecified Maintenance"
    notify_group: 
      - usergroup_01
      - usergroup_03

Public Pages


_sirene_public:
  - name: public_ok
    is_default: yes
    is_enabled: true
    severity: ok
    title: "Nothing"
    message: |
      <p>No public notification.</p>
      <p>Please connect to access private messages.</p>
      <p>IT Team</p>      


  - name: public_major
    severity: major
    description: "Major outage ongoing"
    title: Major incident
    message: |
      <p>IT Services are unavailable.</p>
      <p>Please connect to access details.</p>
      <p>IT Team</p>      

5.9 - Docker configuration

Docker ENV entries for docker-compose and Cavaliba

Thoe .envdocker file holds several important options.

DJANGO_CSRF_TRUSTED_ORIGINS

DJANGO_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.

DJANGO_ALLOWED_HOSTS

DJANGO_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.

DJANGO_SECRET_KEY

DJANGO_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.

CAVALIBA_PORT

CAVALIBA_PORT=8000

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

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.

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.

Cavaliba built-in Admin account

CAVALIBA_ADMIN_PASSWORD=change_again
CAVALIBA_ADMIN_EMAIL=admin@mydomain.com

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.

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

SIRENE_EMAIL_HOST=localhost
SIRENE_EMAIL_PORT=25
SIRENE_EMAIL_USER=noreply
SIRENE_EMAIL_PASSWORD=changeme

SMS configurations

SIRENE_SMS_URL="https://my.sms.provider.com/api/"
SIRENE_SMS_LOGIN="my_sms_account"
SIRENE_SMS_PASSWORD="changeme"

Other

# keep 0 in PRODUCTION
DJANGO_DEBUG=0

DJANGO_CELERY_BROKER_URL="redis://cavaliba_redis:6379"
DJANGO_CELERY_RESULT_BACKEND="redis://cavaliba_redis:6379"

6 - Glossary

Terms and Definitions

Glossary of terms

  • Cavaliba - an integrated and fast Web plateform with services (apps) and a structured data model (data)

  • Data Model - Class/Schema/Instance describing a business/company/customers/IT assets/… and their relationships

  • Sirene - a notification App to send SMS/Mail/Web notifications to your users

  • IdP - Identity Provider - SAML / OIDC external federated identity provider (Keycloak, OKTA, Azure Entra, …)

  • User - an object describing a user (identity, mail, login)

  • Group - a set of users, sharing common characteristics like organizational units, geographical location, etc.

  • Permissions - an atomic authorization to perform an operation in Cavaliba, with an App, or on some Data Model

  • Role - a set of permissions and associated user or groups ; used for security / authorization

7 - CMT_Monitor

Companion tool for host monitoring and status

CMT - Monitoring Tool

CMT documentation