🚀 Installation de CISO Assistant
Installation basique
L'installation de base fournie par la documentation permet de se faire une idée de l'application. Il faut au préalable avoir installé Docker et Docker compose.
olivier@ws01:~$ git clone https://github.com/intuitem/ciso-assistant-community.git
olivier@ws01:~$ cd ciso-assistant-community
olivier@ws01:~/ciso-assistant-community$ ./docker-compose.sh
Vous trouverez le docker-compose.yml fourni par Intuitem sur leur dépôt Github (ou dans le dépôt cloné). Vous constaterez alors l'utilisation de Caddy comme reverse-proxy.
Lors de l'initialisation des conteneurs, il vous sera demandé de saisir l'adresse mail du super utilisateur avec son mot de passe.
Ensuite il vous suffira de vous connecter sur https://localhost:8443 et vous authentifier avec les creds précédemment renseignés.
Cette installation est très bien pour prendre en main le logiciel mais l'accès est limité à nous-même. Voyons maintenant comment l'intégrer avec Nginx et Traefik à la place de Caddy pour le rendre accessible aux collaborateurs.
Installation avec Docker et Nginx
Il n'y a pas encore de documentation officielle concernant cette configuration. J'ai donc recherché une façon de faire à m'appyant sur les "issues" du dépôt Github de l'application.
Dans tous les cas, l'application se veut collaborative et il faut donc la rendre accessible à minima sur le réseau.
Pour ce mode d'installation, vous devez au préalable :
- Avoir installé Docker et Docker compose
- Avoir installé Nginx (façon "old-school" )
- Avoir (créé) un nom de domaine (portée locale ou globale)
- Préparer un compte mail qui servira pour les notifications et lors de l'ajout d'un utilisateur supplémentaire.
- Générer une clé secrète pour Django avec par exemple la commande
openssl rand -base64 50
olivier@srv01:~$ sudo mkdir /srv/ciso-assistant && sudo chown olivier: /srv/ciso-assistant
olivier@srv01:~$ cd /srv/ciso-assistant
olivier@srv01:/srv/ciso-assistant$ mkdir data db
olivier@srv01:/srv/ciso-assistant$ vim compose.yml
À la base Ciso Assistant peut fonctionner avec Sqlite. Cependant en production, je vous recommande de partir directement sur Postgresql car il ne semble pas possible de migrer les données saisies lors du passage de Sqlite vers PGSQL.
---
services:
backend:
image: ghcr.io/intuitem/ciso-assistant-community/backend:latest
container_name: backend
restart: unless-stopped
environment:
- ALLOWED_HOSTS=backend,ciso.domain.fr
- CISO_ASSISTANT_URL=https://ciso.domain.fr
- DJANGO_DEBUG=True # Pour le démarrage, on peut ensuite passer la directive à False.
- AUTH_TOKEN_TTL=7200
- DJANGO_SECRET_KEY=<DJANGO_KEY> # Key générée avec la commande "openssl rand -base64 50"
# DB
- POSTGRES_NAME=ciso
- POSTGRES_USER=<USER_PGSQL>
- POSTGRES_PASSWORD=<MOT_DE_PASSE_PGSQL>
- DB_HOST=ciso_db
- DB_PORT=5432
# Email
- DEFAULT_FROM_EMAIL=<EMAIL>
- EMAIL_HOST=<SERVEUR_MAIL>
- EMAIL_PORT=<PORT>
- EMAIL_HOST_USER=<USER>
- EMAIL_HOST_PASSWORD=<PASSWORD>
- EMAIL_USE_TLS=True # Si utilisation du chiffrement
volumes:
- ./db:/code/db # Permettra de stocker les fichiers uploadés
frontend:
image: ghcr.io/intuitem/ciso-assistant-community/frontend:latest
container_name: frontend
restart: unless-stopped
ports:
- 127.0.0.1:3000:3000
environment:
- PUBLIC_BACKEND_API_URL=http://backend:8000/api
- ORIGIN=https://ciso.domain.fr
- PROTOCOL_HEADER=x-forwarded-proto
- HOST_HEADER=x-forwarded-host
depends_on:
- backend
ciso_db:
image: docker.io/postgres:latest
container_name: ciso_db
environment:
- POSTGRES_USER=<USER_PGSQL>
- POSTGRES_PASSWORD=<MOT_DE_PASSE_PGSQL>
- POSTGRES_DB=ciso
- PGDATA=/var/lib/postgres/data
volumes:
- ./data:/var/lib/postgres/data
olivier@srv01:/srv/ciso-assistant$ vim /etc/nginx/sites-available/01-ciso.domain.lan :
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name ciso.domain.fr;
ssl_certificate /etc//nginx/ssl/ciso/ciso.domain.fr.crt;
ssl_certificate_key /etc/nginx/ssl/ciso/ciso.domain.fr.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Il ne vous reste plus qu'à relancer Nginx et lancer les conteneurs. Comptez une ou deux minutes pour le lancement du backend CISO.
Une fois les conteneurs lancés, il faut créer le super-utilisateur :
olivier@srv01:/srv/ciso-assistant$ docker compose exec backend poetry run python manage.py createsuperuser
# Vous renseignerez alors un email et un mot de passe.
source : Issue du dépôt Github de CISO Assistant
Installation avec Traefik
---
networks:
cisonet:
traefik:
external: true
services:
backend:
image: ghcr.io/intuitem/ciso-assistant-community/backend:latest
container_name: backend
restart: unless-stopped
networks:
- cisonet
environment:
- ALLOWED_HOSTS=backend,ciso.domain.fr
- CISO_ASSISTANT_URL=https://ciso.domain.fr
- DJANGO_DEBUG=True # Pour le démarrage, on peut ensuite passer la directive à False.
- AUTH_TOKEN_TTL=7200
- DJANGO_SECRET_KEY=<DJANGO_KEY> # Key générée avec la commande "openssl rand -base64 50"
# DB
- POSTGRES_NAME=ciso
- POSTGRES_USER=<USER_PGSQL>
- POSTGRES_PASSWORD=<MOT_DE_PASSE_PGSQL>
- DB_HOST=ciso_db
- DB_PORT=5432
# Email
- DEFAULT_FROM_EMAIL=<EMAIL>
- EMAIL_HOST=<SERVEUR_MAIL>
- EMAIL_PORT=<PORT>
- EMAIL_HOST_USER=<USER>
- EMAIL_HOST_PASSWORD=<PASSWORD>
- EMAIL_USE_TLS=True # Si utilisation du chiffrement
volumes:
- ./db:/code/db # Permettra de stocker les fichiers uploadés
frontend:
container_name: frontend
image: ghcr.io/intuitem/ciso-assistant-community/frontend:latest
restart: unless-stopped
networks:
- cisonet
- traefik
environment:
- PUBLIC_BACKEND_API_URL=http://backend:8000/api
- ORIGIN=https://ciso.domain.fr
- PROTOCOL_HEADER=x-forwarded-proto
- HOST_HEADER=x-forwarded-host
depends_on:
- backend
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik"
- "traefik.http.routers.ciso-frontend.rule=Host(`ciso.domain.fr`)"
- "traefik.http.routers.ciso-frontend.tls=true"
- "traefik.http.routers.ciso-frontend.tls.certresolver=letsencrypt"
- "traefik.http.services.ciso-frontend-service.loadbalancer.server.port=3000"
ciso_db:
image: docker.io/postgres:latest
container_name: ciso_db
restart: unless-stopped
networks:
- cisonet
environment:
- POSTGRES_USER=<USER_PGSQL>
- POSTGRES_PASSWORD=<MOT_DE_PASSE_PGSQL>
- POSTGRES_DB=ciso
- PGDATA=/var/lib/postgres/data
volumes:
- ./data:/var/lib/postgres/data
Comme pour l'installation avec Docker et Nginx, il vous faudra créer manuellement un super-utilisateur avec la même commande.
Utilisation de l'API
Pour ceux qui utilisent des process d'automatisation tels que l'intégration des informations issues de CISO Assistant dans une autre application par exemple, il est possible d'exposer l'API du backend. L'inverse est également vrai. Nous pouvons récupérer des informations pour les intégrer à CISO Assistant à travers son API.
Personnellement, j'y vois une grande utilité notamment dans la gestion documentaire des preuves. D'ailleurs j'ai récemment démarré un projet dont l'idée est de mettre à jour automatiquement des fichiers rattachés à des preuves lorsque ces fichiers en question sont modifiés.
En effet, si nous reprenons la stack de l'installation de base, il est techniquement possible de configurer le backend pour interroger l'API directement sans passer par le frontend.
La documentation et les tests de l'API sont accessibles par le biais de Swagger.
Voici comment faire avec les différentes configurations vues plus haut.
Exposition de l'API sur l'installation basique
Une fois votre stack déployée, arrêtez-la et modifiez le service "backend" dans le fichier docker-compose.yml comme ci-dessous.
services:
backend:
container_name: backend
image: ghcr.io/intuitem/ciso-assistant-community/backend:latest
restart: unless-stopped
ports:
- 127.0.0.1:8000:8000 # Publication du port
environment:
- ALLOWED_HOSTS=backend,localhost # Ajout de localhost. Sans cela vous aurez une erreur Django.
- CISO_ASSISTANT_URL=https://localhost:8443
- DJANGO_DEBUG=True
volumes:
- ./db:/code/db
(...)
Lancez la stack puis connectez-vous sur : http://localhost:8000/api/iam/login/
Vous arriverez alors sur cette page.
Renseignez votre utilisateur et votre mot de passe ici :
Puis cliquez sur "Post".
Vous obtiendrez alors juste au dessus un token qui sera utilisé avec Swagger.
Copiez le token puis rendez-vous sur l'interface de Swagger http://localhost:8000/api/schema/swagger/
Cliquez ensuite sur le bouton "Authorize" afin d'y renseigner votre token afin de pouvoir interroger l'API.
Exposition de l'API sur l'installation avec Docker et Nginx
Ici je pars du principe que nous pourrions ouvrir l'accès à CISO Assistant sur le net. J'ai donc mis des restrcitions d'accès à l'API basées sur les IP. Cela n'empêche pas de configurer des accès restreints aux IP utiles dans le cas d'une portée locale uniquement du logiciel (Zero Trust ! ).
services:
backend:
image: ghcr.io/intuitem/ciso-assistant-community/backend:latest
container_name: backend
restart: unless-stopped
environment:
- ALLOWED_HOSTS=backend,ciso.domain.fr
- CISO_ASSISTANT_URL=https://ciso.domain.fr
- DJANGO_DEBUG=True # Pour le démarrage, on peut ensuite passer la directive à False.
- AUTH_TOKEN_TTL=7200
- DJANGO_SECRET_KEY=<DJANGO_KEY> # Key générée avec la commande "openssl rand -base64 50"
# DB
- POSTGRES_NAME=ciso
- POSTGRES_USER=<USER_PGSQL>
- POSTGRES_PASSWORD=<MOT_DE_PASSE_PGSQL>
- DB_HOST=ciso_db
- DB_PORT=5432
# Email
- DEFAULT_FROM_EMAIL=<EMAIL>
- EMAIL_HOST=<SERVEUR_MAIL>
- EMAIL_PORT=<PORT>
- EMAIL_HOST_USER=<USER>
- EMAIL_HOST_PASSWORD=<PASSWORD>
- EMAIL_USE_TLS=True # Si utilisation du chiffrement
volumes:
- ./db:/code/db # Permettra de stocker les fichiers uploadés
ports:
- 127.0.0.1:8000:8000
frontend:
image: ghcr.io/intuitem/ciso-assistant-community/frontend:latest
container_name: frontend
restart: unless-stopped
environment:
- PUBLIC_BACKEND_API_URL=http://backend:8000/api
- PUBLIC_BACKEND_API_EXPOSED_URL=https://ciso.domain.fr/api
- PROTOCOL_HEADER=x-forwarded-proto
- HOST_HEADER=x-forwarded-host
depends_on:
- backend
ports:
- 127.0.0.1:3000:3000
ciso_db:
image: docker.io/postgres:latest
container_name: ciso_db
restart: unless-stopped
environment:
- POSTGRES_USER=<USER_PGSQL>
- POSTGRES_PASSWORD=<MOT_DE_PASSE_PGSQL>
- POSTGRES_DB=ciso
- PGDATA=/var/lib/postgres/data
volumes:
- ./data:/var/lib/postgres/data
olivier@srv01:/srv/ciso-assistant$ vim /etc/nginx/sites-available/01-ciso.domain.lan :
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name ciso.domain.fr;
ssl_certificate /etc//nginx/ssl/ciso/ciso.domain.lan.crt;
ssl_certificate_key /etc/nginx/ssl/ciso/ciso.domain.lan.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Ajout de l'accès à l'API avec restriction sur les IP des clients
location /api {
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Exposition de l'API sur l'installation avec Docker et Traefik
La mise est en place avec Traefik est plutôt triviale. Comme avec Nginx, on va limiter l'accès à l'API aux IP de notre LAN.
---
networks:
cisonet:
traefik:
external: true
services:
backend:
container_name: backend
image: ghcr.io/intuitem/ciso-assistant-community/backend:latest
restart: unless-stopped
networks:
- cisonet
- traefik
environment:
- ALLOWED_HOSTS=backend,localhost,ciso.domain.fr
- CISO_ASSISTANT_URL=https://ciso.domain.fr
- DJANGO_DEBUG=True
- AUTH_TOKEN_TTL=7200
- DJANGO_SECRET_KEY=<DJANGO_KEY> # Key générée avec la commande "openssl rand -base64 50"
# DB
- POSTGRES_NAME=ciso
- POSTGRES_USER=<USER_PGSQL>
- POSTGRES_PASSWORD=<MOT_DE_PASSE_PGSQL>
- DB_HOST=ciso_db
- DB_PORT=5432
# Email
- DEFAULT_FROM_EMAIL=<EMAIL>
- EMAIL_HOST=<SERVEUR_MAIL>
- EMAIL_PORT=<PORT>
- EMAIL_HOST_USER=<USER>
- EMAIL_HOST_PASSWORD=<PASSWORD>
- EMAIL_USE_TLS=True # Si utilisation du chiffrement
volumes:
- ./db:/code/db
# Configuration de l'accès direct à l'API :
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik"
- "traefik.http.routers.ciso-backend.rule=Host(`ciso.domain.fr`) && PathPrefix(`/api`)"
- "traefik.http.routers.ciso-backend.tls=true"
# Déclaration du middleware permettant de limiter l'accès :
- "traefik.http.middlewares.ciso-backend-ipfilter.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.0/24"
- "traefik.http.routers.ciso-backend.middlewares=ciso-backend-ipfilter"
- "traefik.http.services.ciso-backend-service.loadbalancer.server.port=8000"
frontend:
container_name: frontend
image: ghcr.io/intuitem/ciso-assistant-community/frontend:latest
restart: unless-stopped
networks:
- cisonet
- traefik
environment:
- PUBLIC_BACKEND_API_URL=http://backend:8000/api
- PUBLIC_BACKEND_API_EXPOSED_URL=https://ciso.domain.fr/api
- PROTOCOL_HEADER=x-forwarded-proto
- HOST_HEADER=x-forwarded-host
depends_on:
- backend
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik"
- "traefik.http.routers.ciso-frontend.rule=Host(`ciso.domain.fr`)"
- "traefik.http.routers.ciso-frontend.tls=true"
- "traefik.http.routers.ciso-frontend.tls.certresolver=letsencrypt"
- "traefik.http.services.ciso-frontend-service.loadbalancer.server.port=3000"
ciso_db:
image: docker.io/postgres:latest
container_name: ciso_db
restart: unless-stopped
networks:
- cisonet
environment:
- POSTGRES_USER=<USER_PGSQL>
- POSTGRES_PASSWORD=<MOT_DE_PASSE_PGSQL>
- POSTGRES_DB=ciso
- PGDATA=/var/lib/postgres/data
volumes:
- ./data:/var/lib/postgres/data
Utilisation de l'API avec Curl et Python
Dans ces exemples, nous allons voir comment récupérer la liste des preuves créées au préalable sur l'application afin d'uploader un document pour une preuve donnée.
Curl
curl -X POST 'https://ciso.domain.fr/api/iam/login/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"username": "<USER@mail.com>", "password": "<PASSWORD>"}'
# Sortie :
{"expiry":"2024-12-29T11:18:29.788054Z","token":"0c7666074ca0edb1ec86e976d035f3b39df853feebc477ee037a88ead0d96676"}%
curl -X 'GET' 'https://ciso.domain.fr/api/evidences/' \
-H 'accept: application/json' \
-H 'Authorization: Token 0c7666074ca0edb1ec86e976d035f3b39df853feebc477ee037a88ead0d96676' | jq
# Sortie
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": "b88c55a2-94ea-4487-96ae-1590886eea23",
"attachment": "",
"size": null,
"folder": {
"str": "CISOTEST,
"id": "08337776-e33e-4d91-a816-aa087f8e11da"
},
"applied_controls": [],
"requirement_assessments": [
{
"str": "",
"id": "cb150a50-374e-4342-8b44-bbc2ffc6b42d"
}
],
"created_at": "2024-12-29T10:19:56.041157Z",
"updated_at": "2024-12-29T10:24:24.284697Z",
"is_published": false,
"name": "Registre d'accès des admins",
"description": null,
"link": null
},
{
"id": "b828ad59-4a2a-4b80-9c0a-a79e5b1d6733",
"attachment": "",
"size": null,
"folder": {
"str": "CISOTEST",
"id": "08337776-e33e-4d91-a816-aa087f8e11da"
},
"applied_controls": [],
"requirement_assessments": [
{
"str": "",
"id": "06e52314-acec-414e-a339-198a58b04d3a"
}
],
"created_at": "2024-12-29T10:23:48.670814Z",
"updated_at": "2024-12-29T10:23:48.670828Z",
"is_published": false,
"name": "Registre d'accès au serveur de fichiers",
"description": null,
"link": null
}
]
}
Nous allons maintenant uploader un fichier concernant la preuve Registre d'accès des admins en utilisant l'id de cette dernière.
curl -X 'POST' 'https://ciso.maison.bro/api/evidences/b88c55a2-94ea-4487-96ae-1590886eea23/upload/' \
-H 'Authorization: Token 0c7666074ca0edb1ec86e976d035f3b39df853feebc477ee037a88ead0d96676' \
-H 'accept: application/json' \
-H 'Content-Type: document' \
-H 'Content-Disposition: attachment; filename="admins.png"' \
--data-binary @/home/olivier/Images/admins.png
Une fois la requête exécutée, nous retrouvons le fichier attaché à la preuve concernée.
Python
Voici un script de base pour uploader un fichier. Ici nous allons uploader un fichier pour la preuvre Registre d'accès au serveur de fichiers
import requests
# Première requête : Connexion pour obtenir le token
login_url = 'https://ciso.domain.fr/api/iam/login/'
login_headers = {
'accept': 'application/json',
'Content-Type': 'application/json'
}
login_data = {
"username": "<USER@MAIL.FR>",
"password": "<PASSWORD>"
}
response = requests.post(login_url, headers=login_headers, json=login_data)
if response.status_code == 200:
print("Connexion réussie!")
token = response.json().get('token') # Assurez-vous que la clé est correcte selon la réponse
print("Token reçu:", token)
else:
print("Échec de la connexion:", response.status_code, response.text)
exit()
# Deuxième requête : Upload du fichier pour la preuvre "Registre d'accès au serveur de fichiers"
upload_url = 'https://ciso.domain.fr/api/evidences/b828ad59-4a2a-4b80-9c0a-a79e5b1d6733/upload/'
upload_headers = {
'Authorization': f'Token {token}',
'accept': 'application/json',
'Content-Type': 'document',
'Content-Disposition': 'attachment; filename="tableau-des-droits.pdf'
}
file_path = '/home/olivier/Documents/tableau-des-droits.pdf'
with open(file_path, 'rb') as file:
response = requests.post(upload_url, headers=upload_headers, data=file)
if response.status_code == 200:
print("Fichier uploadé avec succès!")
else:
print("Échec de l'upload:", response.status_code, response.text)
python3 upload.py
#Sortie
Connexion réussie!
Token reçu: f6af5ecdec756a06a3bc28634ed250274332b5e1dd0969d1463210a01083247d
Fichier uploadé avec succès!
On constate alors sur l'application la présence du fichier uploadé pour la preuvre concernée.
La suite
Il ne vous reste plus qu'à commencer à jouer avec le logiciel. Pour une première prise en main, je vous recommande de commencer par l'approche par la conformité avec un audit basé sur le guide de l'hygiène informatique de l'ANSSI (choisir la version détaillé pour bénéficier de mesures prédéfinies). D'autres référentiels sont disponibles dans l'application comme vous pourrez le constater sur la page d'accueil du dépôt Github
Vous trouverez la documentation officielle du logiciel sur https://intuitem.gitbook.io/ciso-assistant.