OpenClaw - Partie 03 : Vault et NGINX

Introduction

Après avoir établi la cible à atteindre et préparer l'OS de la VM avec les prérequis, il est temps de passer à l'installation des premiers composants qui vont servir aux futurs agents.

Vault

Présentation

Vault est un logiciel produit depuis 2015 par la société américaine Hashicorp, qui appartient désormais à IBM.

C'est un gestionnaire centralisé de secret et un système de chiffrement. Il agit comme un référentiel hautement sécurisé auprès duquel des opérateurs humains ou logiciels peuvent s'adresser pour stocker et/ou accéder à des données sensibles (mots de passe, clés API, clés privées, certificats… globalement des secrets).

Logo Vault par Hashicorp

Cliquez sur l'image pour l'agrandir.

Fonctionnement

Le fonctionnement de Vault repose sur plusieurs concepts importants :

  • L'Authentification (prouver qui on est) : Lorsqu'une application (ou un humain) veut un mot de passe, elle s'adresse à Vault en devant d'abord prouver son identité. Vault peut vérifier cette identité de plein de manières différentes (annuaire d'entreprise, token, certificat…)
  • Les Politiques d'accès (La règle du "moindre privilège") : Une fois l'identité confirmée, Vault consulte ses règles. Grâce à cette fonctionnalité, il sera en mesure de déterminer avec exactitude quels secrets une identité peut consulter et avec quels droits (écriture/lecture).
  • Les Secrets dynamiques (La puissance de Vault) : c'est la fonctionnalité la plus avancée. Au lieu de stocker un mot de passe fixe (qui pourrait être volé et réutilisé), Vault peut générer des mots de passe à la volée et à usage unique. Ce mot de passe dispose d'une durée de vie et une fois expirée, même s'il venait à être intercepté, il n'est plus valable.
  • Le chiffrement en tant que service (Transit) : Vault peut chiffrer les données. Une application peut lui envoyer une donnée sensible, Vault le chiffre et lui renvoie la version illisible, sans jamais sauvegarder la donnée elle-même. C'est l'application qui stocke la version chiffrée.
  • Le Scellement (Le principe du coffre de banque) : Pour se protéger lui-même, Vault utilise une technique mathématique (Shamir's Secret Sharing). Quand le serveur Vault démarre, il est "scellé", il ne peut pas lire ses propres données chiffrées. Pour le déverrouiller, il faut entrer un minimum de token parmi plusieurs (par exemple trois sur cinq). Si le quorum est réuni, alors Vault passe en mode « unseal » et peut être utilisé.

Vault remplace donc les secrets éparpillés par un guichet unique, ultra-sécurisé, qui distribue des accès temporaires uniquement à ceux qui peuvent prouver qu'ils en ont besoin.

Dans le cas de nos agents OpenClaw, cela va nous être bénéfique, puisque, plutôt que de stocker les données sensibles directement dans la configuration des agents, on va pouvoir les organiser au sein de Vault et chaque agent ne pourra consulter que ceux qui lui sont rattachés.

Installation

Nous allons donc installer Vault de manière standard, en dehors du contexte de l'utilisateur openclaw créé lors de l'étape précédente.

Le certificat

Avant de s'attaquer aux binaires, on va déjà préparer le certificat qui va servir à présenter l'interface de Vault.

Comme j'en ai l'habitude, je vais exploiter ma PKI interne reposant sur mon domaine AD. Je ne vais pas détailler spécifiquement l'opération. Chacun peut utiliser la méthode de son choix, l'objectif étant d'avoir à la fin une clef privée et un certificat associé.

Ma PKI étant privée et non connue de l'OS Rocky Linux, je commence par déclarer mon CA au sein des certificats de confiance du système.

Je place ce dernier récupéré depuis l'une de mes machines de mon parc dans le dossier /etc/pki/ca-trust/source/anchors/

Récupération de mon CA

Cliquez sur l'image pour l'agrandir.

Récupération de mon CA

Cliquez sur l'image pour l'agrandir.

sudo cp /tmp/ca.crt /etc/pki/ca-trust/source/anchors/

j'accorde les bons droits

sudo chown root:root /etc/pki/ca-trust/source/anchors/ca.crt
sudo chmod 644 /etc/pki/ca-trust/source/anchors/ca.crt

Puis je tape la commande suivant qui va permettre d'intégrer mon CA a l'ensemble des certificats de confiance reconnu par l'OS

sudo update-ca-trust extract
Ajout de mon CA dans la CA de confiance

Cliquez sur l'image pour l'agrandir.

Je confirme que tout est en ordre en effectuant une requête CURL vers l'une de mes URL internes, qui utilisent un certificat émis par ma PKI, par exemple mon instance Xen Orchestra.

curl -sSI https://prdxcpxor501.coolcorp.priv:8443/ | head -3
Test de la prise en compte de mon CA

Cliquez sur l'image pour l'agrandir.

Aucune erreur de certificat, c'est donc OK à ce niveau, ma PKI est reconnue.

Test du CA via curl

Cliquez sur l'image pour l'agrandir.

On s'attaque maintenant au certificat pour vault.

On prépare d'abord une configuration openssl

at > vault-csr.conf <<'EOF'
[req]
default_bits       = 4096
default_md         = sha256
prompt             = no
distinguished_name = dn
req_extensions     = req_ext

[dn]
C  = FR
ST = Ile-de-France
L  = Paris
O  = COOLCORP
OU = IT Infrastructure
CN = prdlinage501

[req_ext]
subjectAltName = @alt_names
keyUsage       = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[alt_names]
DNS.1 = prdlinage501
DNS.2 = prdlinage501.coolcorp.priv
DNS.3 = localhost
IP.1  = 127.0.0.1
EOF
Configuration certificat pour vault

Cliquez sur l'image pour l'agrandir.

J'installe également Openssl, qui n'est pas présent par défaut sur Rocky Linux :

sudo dnf install openssl

Je génère ma clef privée en 4096 bits

openssl genrsa -out vault.key 4096
Génération de la clef

Cliquez sur l'image pour l'agrandir.

Puis à partir de cette clef et de la configuration que j'ai créée juste avant, je génère le csr (Certificat Signing Request)

openssl req -new -key vault.key -out vault.csr -config vault-csr.conf
Génération CSR

Cliquez sur l'image pour l'agrandir.

C'est ce csr que je vais présenter à ma PKI pour obtenir le certificat, étant sous Windows à ce niveau, j'utilise la commande

certreq -attrib "CertificateTemplate:TPL-SRV-WEB-DEFAULT" -submit .\vault.csr

TPL-SRV-WEB-DEFAULT étant le nom de mon template de certificat que j'utilise pour ce type d'usage.

Récupération du certificat

Cliquez sur l'image pour l'agrandir.

En fin d'opération, j'ai mon certificat et ma clef. Encore une fois, le but n'est pas de rentrer dans le détail à ce niveau, chacun peut utiliser la méthode de son choix en fonction de ce dont il dispose.

On garde la clef et le certificat au chaud pour l'instant (attention, la clef est une donnée critique).

Récupération du certificat pour vault

Cliquez sur l'image pour l'agrandir.

Liste des éléments pour le certificat

Cliquez sur l'image pour l'agrandir.

Installation des paquets

Vault n'est pas dans les paquets de bases de l'OS, il faut donc d'abord ajouter les repo hashicorp

sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo

On peut ensuite installer l'outil

sudo dnf install -y vault
Installation de vault

Cliquez sur l'image pour l'agrandir.

Une fois en place, on vérifie la version du vault.

Test version de vault

Cliquez sur l'image pour l'agrandir.

Le paquet a préconfiguré le nécessaire pour le fonctionnement de l'application à savoir:

  • Création d'un user et d'un groupe dédiés vault:vault
  • Création des répertoires :
    • /opt/vault : pour stocker les données (base vault et clef/certificat)
    • /etc/vault.d/ : pour stocker les configurations
  • Un Unit systemd pour le démarrage du service/usr/lib/systemd/system/vault.service
  • Le binaire /usr/bin/vault

À noter que le binaire est le même pour le côté serveur et le côté client, il prend des variables différentes fonctions des cas. Le service lui tourne avec vault en mode serveur, et nous nous utiliserons le binaire vault en mode client pour interagir avec le serveur.

Configuration de vault

La configuration par défaut ne nous intéresse pas, on va néanmoins la mettre de côté au cas où

sudo mv /etc/vault.d/vault.hcl /etc/vault.d/vault.hcl.rpm-orig

De même on va supprimer le certificat et la clef autogénérés à l'installation pour les remplacer par ceux que l'on vient de créer (dans mon cas, ma clef et mon certificat attendaient patiemment dans /tmp).

sudo rm /opt/vault/tls/tls.crt
sudo rm /opt/vault/tls/tls.key
sudo cp /tmp/vault.key /opt/vault/tls/vault.key
sudo cp /tmp/vault.crt /opt/vault/tls/vault.crt
sudo cp /tmp/ca.crt /opt/vault/tls/ca.crt
Suppression conf par défault

Cliquez sur l'image pour l'agrandir.

Surtout on s'assure de mettre les bons droits sur ces composants

sudo chown -R vault:vault /opt/vault/tls/
sudo chmod 600 /opt/vault/tls/vault.key
sudo chmod 644 /opt/vault/tls/vault.crt
sudo chmod 644 /opt/vault/tls/ca.crt
Attribution des bon droits

Cliquez sur l'image pour l'agrandir.

Il est temps de se concentrer sur la conf elle-même. Cette dernière va être relativement basique, car on va déployer vault sur une configuration mononode.

En effet, Vault peut être déployé en cluster, ce qui est d'ailleurs recommandé en production. Son mécanisme de réplication est basé sur raft et permet ainsi d'avoir plusieurs instances onlines se répliquant la base de données contenant les secrets pour une haute disponibilité du service.

Ce n'est pas ce que je vais retenir ici, car je n'ai pas besoin de cette résilience.

Je vais me contenter d'un vault unique sur ma VM paramétrée pour écouter sur le port par défaut, soit le TCP 8200.

Voici la conf en question

sudo tee /etc/vault.d/vault.hcl > /dev/null <<'EOF'
# Vault configuration - prdlinage501
# Single-node Raft storage, TLS via enterprise PKI

ui = true

# Storage backend: Raft integrated
storage "raft" {
  path    = "/opt/vault/data"
  node_id = "prdlinage501-vault-1"
}

# Listener: HTTPS sur toutes les interfaces
# (0.0.0.0 obligatoire pour que les conteneurs rootless Podman puissent
listener "tcp" {
  address       = "0.0.0.0:8200"
  tls_cert_file = "/opt/vault/tls/vault.crt"
  tls_key_file  = "/opt/vault/tls/vault.key"
  tls_min_version = "tls12"
  # tls_client_ca_file : ne pas déclarer si on n'utilise pas le mTLS client
  # tls_prefer_server_cipher_suites : supprimé en Vault 2.0
}

# Cluster address (Raft mono-nœud, loopback suffit)
cluster_addr = "https://127.0.0.1:8201"
# api_addr doit utiliser le FQDN externe (utilisé par volt-agent dans les conteneurs)
api_addr     = "https://prdlinage501.coolcorp.priv:8200"

# Disable mlock only if swap is disabled (it usually isn't)
# Keeping mlock enabled (default) to prevent secrets swap
disable_mlock = false

# Seal: Shamir (default, no config needed)

# Telemetry (optional, useful for monitoring)
telemetry {
  prometheus_retention_time = "24h"
  disable_hostname          = true
}
EOF

J'ai commenté la conf avec l'IA pour aider à comprendre qui fait quoi.

Configuration de vault

Cliquez sur l'image pour l'agrandir.

On s'assure toujours d'avoir les bons droits sur cette nouvelle configuration.

sudo chown root:vault /etc/vault.d/vault.hcl
sudo chmod 640 /etc/vault.d/vault.hcl
Mise en place des droits

Cliquez sur l'image pour l'agrandir.

À noter la présence de l'option disable_mlock. Par défaut vault empêché l'usage de la swap pour éviter que des secrets y soient stockés et potentiellement accessible. Il faut donc s'assurer de la désactiver sur le serveur.

sudo swapoff -a
Désactivation de la swap

Cliquez sur l'image pour l'agrandir.

On s'assure qu'elle ne se réactive pas au prochain démarrage en commentant la ligne associée dans le fstab.

sudo vi /etc/fstab
Désactivation de la swap dans fstab

Cliquez sur l'image pour l'agrandir.

Comme dit plus haut, Vault utilise un port spécifique pour être consulté ; on va donc l'ouvrir sur le serveur avec firewall-cmd.

sudo firewall-cmd --permanent --add-port=8200/tcp
sudo firewall-cmd --reload
Ouverture Firewall

Cliquez sur l'image pour l'agrandir.

Il reste plus qu'a démarrer le service et s'assurer que la conf est correcte

sudo systemctl enable --now vault.service

sudo systemctl status vault.service --no-pager
Démarrage du service vault

Cliquez sur l'image pour l'agrandir.

Initialisation

Arrivé à ce stade, on va devoir initialiser la base.

On commence par fixer la variable d'environnement de l'URL vault, afin que la commande vault que nous allons appeler sachent qu'elle doit se connecter au serveur vault local.

export VAULT_ADDR=https://127.0.0.1:8200

On vérifie si l'accès est fonctionnel.

vault status

On arrive à un moment critique : la création de la base et du mécanisme de protection qui y est rattaché.

Il est conseillé d'utiliser en amont la commande

set +o history

Afin de désactiver l'historique bash pour éviter que des éléments compromettants se retrouvent à l'intérieur.

On initie la conf vault avec la commande suivante :

vault operator init -key-shares=5 -key-threshold=3 > /tmp/vault-init.txt

J'ai choisi d'avoir une génération de 5 clefs de descellement avec un minimum requis de trois.

L'ensemble est stocké dans /tmp/vault-init.txt

Attention : ce fichier est ultra critique ; il contient tous les éléments nécessaires à la sécurité de la configuration de Vault qu'on vient de créer.

Si on le consulte, on retrouve

  • Les 5 clefs permettant d'unseal Vault
  • Le token root, soit le token permettant de s'authentifier sur l'instance vault avec le plus haut niveau de droit.

Toutes ces informations doivent être récupérées et conservées dans un endroit sécurisé. En l'occurrence, pour moi, mon keepaas, le fichier doit être absolument supprimé. Il faut s'assurer qu'il n'a été synchronisé nulle part.

Initialisation de vault et génération des clefs

Cliquez sur l'image pour l'agrandir.

Comme expliquer, au démarrage vault est "scellé".

Vault sealed

Cliquez sur l'image pour l'agrandir.

On doit donc maintenant le déverouiller via la commande:

vault operator unseal

On entre la première clef.

On répète l'opération 3x en rappelant la même commande, mais en indiquant la clef suivante.

On peut choisir n'importe laquelle parmi les cinq générées, l'important étant d'en prendre trois différentes pour arriver au quorum et unseal vault.

Vault unseal

Cliquez sur l'image pour l'agrandir.

On peut le vérifier en fin d'opération.

vault status | grep -E 'Sealed|Initialized'

Initialized doit être à true et Sealed à false.

Controle Unseal de vault

Cliquez sur l'image pour l'agrandir.

Petite précision à ce niveau. Il est important de comprendre que, dorénavant, chaque fois que l'instance Vault sera redémarrée (que ce soit le service ou le serveur), elle sera à nouveau scellée et il faudra répéter cette opération. C'est pourquoi je vous conseille, à ce stade, de faire un premier redémarrage du serveur et de vous assurer de la capacité à refaire la chose.

En production, il est manifeste que cela peut entraîner des ennuis. Heureusement, des mécanismes existent pour déverrouiller automatiquement Vault au moment de son lancement. On peut par exemple exploiter un vault Azure, rien à voir avec le vault d'hashicorp, mais il s'agit la aussi d'un espace sécurisé, mais hébergé dans Azure via un service managé. On peut l'utiliser pour y stocker les clés générées à l'initialisation de Vault. Ensuite, on dit à notre instance Vault d'aller se présenter au Vault Azure (je répète, ce n'est pas le Vault Hashicorp que nous venons d'installer) pour récupérer les clés et se déverrouiller. D'autres solutions sont possibles. À vous de voir ce qui vous arrange.

Dans mon cas, j'accepte le fait de devoir manuellement entrer au moins trois clefs à chaque fois que je devrai redémarrer Vault.

Activation des fonctions

Une fois unseal, on peut interagir avec vault en lui présentant cette fois-ci le token root généré en même temps que les cinq clefs précédemment utilisées.

vault login

(ne pas oublier de remettre la variable VAULT_ADDR si reboot entre temps)

Login en root

Cliquez sur l'image pour l'agrandir.

Toutes les commandes suivantes vont donc être exécuté en tant que root de l'instance vault.

Première étape, activez le moteur de secret

vault secrets enable -path=secret -version=2 kv
Activation de la base de secrets

Cliquez sur l'image pour l'agrandir.

On vérifie

vault secrets list

Seconde étape, activez la fonction d'authentification AppRole.

Activation de approle

Cliquez sur l'image pour l'agrandir.

vault auth enable approle

On vérifie que c'est le cas

vault auth list

Configuration RBAC pour les agents

On va maintenant passer à la logique de policy.

Policy

L'idée c'est que chaque agent soit accompagné d'un conteneur Vault Client, qui se présentera à l'instance Vault avec un rôle clairement établi.

Par exemple, mon premier bot, it-claw, sera associé à une politique ne lui autorisant que la lecture des secrets qui seront stockés dans Vault dans la branche.

secret/openclaw/it-claw/

Ce qui donne comme police via la syntaxe vault :

vault policy write openclaw-it-claw-read - <<'EOF'
# Read access to it-claw secrets only
path "secret/data/openclaw/it-claw/*" {
  capabilities = ["read"]
}

# Allow listing keys (useful for vault-agent templating)
path "secret/metadata/openclaw/it-claw/*" {
  capabilities = ["list", "read"]
}

# Allow token self-management (renew its own lease)
path "auth/token/renew-self" {
  capabilities = ["update"]
}

path "auth/token/lookup-self" {
  capabilities = ["read"]
}
EOF

On vient de créer une police openclaw-it-claw-read qui n'autorise que la lecture (list, read) dans l'arborescence de secret secret/metadata/openclaw/it-claw/*.

On peut d'ailleurs vérifier la présence de cette dernière

vault policy list
vault policy read openclaw-it-claw-read
Création et vérification de la policy

Cliquez sur l'image pour l'agrandir.

Role

Maintenant qu'on a cette police, il faut qu'elle soit rattachée à un rôle, c'est la même logique RBAC que Kubernetes.

On définit une liste d'actions réalisable sur une arborescence donnée (la policy) et on l'associe à un rôle.

vault write auth/approle/role/openclaw-it-claw \
    token_policies="openclaw-it-claw-read" \
    token_ttl=1h \
    token_max_ttl=24h \
    secret_id_ttl=0 \
    secret_id_num_uses=0

En l'occurrence ici un rôle openclaw-it-claw avec une politique de durée de vie de jeton de maximum 24H et une obligation pour l'app associée à ce rôle (notre agent) de se réauthentifié toutes les heures.

Création du role

Cliquez sur l'image pour l'agrandir.

Par contre le secretID associé est lui sans expiration.

Ce n'est pas forcément simple en comprendre au début.

Avec cette commande, nous venons de créer une identité (un rôle) pour l'application openclaw-it-claw.

On lui configure un mot de passe (SecretID) qui n'expirera jamais et qui pourra être utilisé à l'infini. En échange de ce mot de passe, l'application, donc notre agent Vault, en lien avec notre agent IT-Claw, va recevoir du serveur Vault un token d'une durée de vie limitée. Via ce token, l'agent vault rattaché à l'agent IA aura accès en lecture pour une heure à ses secrets en toute sécurité.

Ce petit schéma devrait simplifier la compréhension.

Schéma de fonctionnement Role / Policy / SecretID

Cliquez sur l'image pour l'agrandir.

Certains d’entre vous pourraient me dire que, dans cette logique, le secretID est un élément critique. C’est effectivement le cas. Nous ne l’avons pas encore exploité à ce stade, mais il devra être récupéré plus tard et mis en œuvre par la suite. Plusieurs techniques sont possibles pour réduire l’impact d’un vol de ce dernier. Dans mon cas, l’une des améliorations les plus simples à mettre en œuvre serait de figer l’usage de ce token depuis une IP source locale. Il suffit pour ça de modifier le rôle en ajoutant l’option secret_id_bound_cidrs et token_bound_cidrs pour ficher les demandes possibles depuis le localhost. On pourrait également limiter la durée de vie du secretID à 1 ans (secret_id_ttl)

vault write auth/approle/role/openclaw-it-claw \
    token_policies="openclaw-it-claw-read" \
    token_ttl=1h \
    token_max_ttl=24h \
    secret_id_ttl=8760h \
    secret_id_num_uses=0 \
    secret_id_bound_cidrs="127.0.0.1/32" \
    token_bound_cidrs="127.0.0.1/32"

C’est une amélioration possible que je n’ai pas encore mise en œuvre et qu’il faut que j’évalue, mais c’est à savoir.

ID

Maintenant que la conf est en place, il nous faut récupérer le role_id associé au rôle qu'on vient de créer.

ROLE_ID=$(vault read -field=role_id auth/approle/rôle/openclaw-it-claw/rôle-id)
echo "$ROLE_ID"

Ce n'est pas un élément sensible, c'est comme un login. On peut donc l'inscrire dans un fichier, en l'occurrence au niveau de notre arborescence dédiée à nos agents et détaillée dans l'article précédent.

sudo mkdir -p /var/lib/openclaw/vault
echo "$ROLE_ID" | sudo tee /var/lib/openclaw/vault/it-claw-role-id > /dev/null
sudo chown openclaw:openclaw /var/lib/openclaw/vault/it-claw-role-id
sudo chmod 644 /var/lib/openclaw/vault/it-claw-role-id

On place cette id dans le sous-dossier Vault, en prenant soin de bien indiquer les bons droits, puisque note utilisateur openclaw manipulera ce fichier pour gérer les agents.

Mise en place de l'id de role

Cliquez sur l'image pour l'agrandir.

Mise en place de l'id de role

Cliquez sur l'image pour l'agrandir.

Tout est maintenant en place au niveau vault pour qu'il puisse être utilisé ultérieurement.

GUI

Il est également possible d'accéder à l'interface utilisateur de Vault depuis un poste externe en utilisant l'URL indiquée dans le certificat créé au début de cet article (le nom de mon serveur pour ma part).

Sur un accès https sur le port 8200, on doit pouvoir utiliser son token root et retrouver l'interface de vault.

Interface graphique de Vault

Cliquez sur l'image pour l'agrandir.

Interface graphique de Vault

Cliquez sur l'image pour l'agrandir.

L'idée n'est pas d'entrer dans le détail à ce stade, mais sachez que tout peut être configuré via GUI.

Vous pouvez décider de ne pas l'exposer et de ne pas l'utiliser pour des raisons de sécurité.

De même, on conseille souvent de créer un nouvel utilisateur admin et de ne pas utiliser le compte root créé par défaut pour ses taches d'administration.

Comme je ne suis pas non plus un expert de vault et que l'objectif n'est pas de faire un tutoriel avancé de vault, je n'irais pas plus loin sur ce point. Mais n'hésitez pas à vous documenter et à vous former sur cet outil, il est très largement utilisé dans l'IT et fait figure de référence.

NGINX

L'article est déjà costaud, mais il faut encor ajouter un petit composant avant d'aller plus loin : NGINX.

Je ne présenterais pas le serveur web ultra connu, mais on va en avoir besoin pour plus tard, notamment pour fournir un accès sécurisé à la GUI de chacun des agents.

OpenClaw ne propose pas de TLS en natif pour l'accès à son interface, et il faut proxifier l'accès si l'on veut sécuriser un peu mieux ce point.

Certificat

Une fois de plus, il nous faudra un certificat, mais cette fois-ci pas pour l'interface graphique de Vault, mais pour l'interface graphique de mon premier agent IA, it-claw.

Pour ça, j'utilise un nouveau fichier de configuration « openssl ».

cat > it-claw-csr.conf <<'EOF'
[req]
default_bits       = 4096
default_md         = sha256
prompt             = no
distinguished_name = dn
req_extensions     = req_ext

[dn]
C  = FR
ST = Ile-de-France
L  = Paris
O  = COOLCORP
OU = IT Infrastructure
CN = prdlinage501

[req_ext]
subjectAltName = @alt_names
keyUsage       = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[alt_names]
DNS.1 = prdlinage501
DNS.2 = prdlinage501.coolcorp.priv
DNS.3 = localhost
DNS.4 = it-claw.coolcorp.priv
IP.1  = 127.0.0.1
EOF
Création du csr et de la clef pour la GUI openclaw

Cliquez sur l'image pour l'agrandir.

Le but est d'avoir un certificat utilisable par NGINX qui répond pour https://it-claw.coolcorp.priv.

Je ne vais pas aller plus loin dans le détail pour le certificat, c'est exactement la même logique que pour vault.

On créé la clef et le csr

openssl genrsa -out it-claw.coolcorp.priv.key 4096
openssl req -new -key it-claw.coolcorp.priv.key -out it-claw.coolcorp.priv.csr -config it-claw-csr.conf
Création du csr et de la clef pour la GUI openclaw

Cliquez sur l'image pour l'agrandir.

Et on utilise le csr pour l'obtention du certificat.

On se garde notre clef et le certificat de côté.

Création du csr et de la clef pour la GUI openclaw

Cliquez sur l'image pour l'agrandir.

Installation et configuration

On installe nginx.

sudo dnf install -y nginx httpd-tools
Installation NGINX

Cliquez sur l'image pour l'agrandir.

On copie notre clef et notre certificat dans le bon emplacement pour qu'il soit utilisable par nginx.

En ce qui me concerne, je choisis /etc/pki/tls/certs et je place les bons droits.

sudo cp it-claw.coolcorp.priv.crt /etc/pki/tls/certs/it-claw.coolcorp.priv.crt
sudo cp it-claw.coolcorp.priv.key /etc/pki/tls/private/it-claw.coolcorp.priv.key
sudo chmod 644 /etc/pki/tls/certs/it-claw.coolcorp.priv.crt
sudo chmod 600 /etc/pki/tls/private/it-claw.coolcorp.priv.key
sudo chown root:root /etc/pki/tls/certs/it-claw.coolcorp.priv.crt \
                     /etc/pki/tls/private/it-claw.coolcorp.priv.key

Il s'agit également d'utiliser nginx pour assurer l'authentification de l'accès à l'interface graphique d'openclaw.

Authentification

On pourrait aller jusqu'à implanter l'OAUTH2 et exploiter une solution comme Azure Entra, mais le tutoriel est déjà assez long.

Je vais donc rester sur une simple authentification web, mais sachez qu'il est possible de faire beaucoup mieux.

J'utilise donc la commande htpasswd installée avec le package httpd-tools pour créer un fichier d'authentification dans /etc/nginx/htpasswd

sudo mkdir -p /etc/nginx/htpasswd
sudo htpasswd -c /etc/nginx/htpasswd/it-claw bvivi57

Dans mon cas, mon login d'accès à la GUI de openclaw sera bvivi57.

Création du fichier htpasswd pour nginx

Cliquez sur l'image pour l'agrandir.

Création du fichier htpasswd pour nginx

Cliquez sur l'image pour l'agrandir.

Configuration

On termine par la configuration de nginx

sudo tee /etc/nginx/conf.d/it-claw.conf <<'EOF'
server {
    listen 443 ssl;
    server_name it-claw.coolcorp.priv;

    ssl_certificate     /etc/pki/tls/certs/it-claw.coolcorp.priv.crt;
    ssl_certificate_key /etc/pki/tls/private/it-claw.coolcorp.priv.key;

    auth_basic "OpenClaw it-claw";
    auth_basic_user_file /etc/nginx/htpasswd/it-claw;

    location / {
        proxy_pass http://127.0.0.1:18790;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-User $remote_user;
    }
}
EOF

Cette configuration exploite nos certificats et permet à nginx de répondre à it-claw.coolcorp.priv, tout en incluant l'authentification web.

Si cette étape est franchie, nginx redirigera vers l'intérieur du conteneur sur le port 18790, qui correspondra au port sélectionné ultérieurement pour exposer l'interface web de notre premier agent it-claw.

Il sera nécessaire de renvoyer l'utilisateur pour que OpenClaw puisse l'exploiter plus tard.

Vous pensiez que c'était terminé, mais vous aviez tort.

Il va falloir autoriser nginx à renvoyer les requêtes vers ce port interne. Par défaut SElinux ne laissera pas faire ce renvoi.

Il faut donc passer les commandes suivantes

sudo semanage port -a -t http_port_t -p tcp 18790
sudo setsebool -P httpd_can_network_connect 1
Configuration SElinux pour NGINX

Cliquez sur l'image pour l'agrandir.

Configuration SElinux pour NGINX

Cliquez sur l'image pour l'agrandir.

Faut pensez aussi à ouvrir le port https

sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

On peut enfin activer le service nginx.

sudo systemctl enable --now nginx

Pour l'instant on ne peut pas aller plus loin sur cette configuration.

Conclusion

Vault est un outil extrêmement puissant, mais complexe à appréhender au départ. Néanmoins, en l'associant à des conteneurs disposant du binaire Vault et des solutions de connexion appropriées, ils pourront récupérer de manière sécuritaire et dynamique tout ce dont nos agents ont besoin pour fonctionner.

Nginx lui garantira un minimum de protections et de chiffrements pour exploiter les interfaces graphiques que nos agents pourraient exposer pour être contrôlés.

On a désormais ce qu'il faut pour sécuriser les données sensibles qui vont devoir être utilisées par nos agent openclaw. On dispose également d'une solution d'exposition des interfaces de ces mêmes agents.

Le prochain article nous permettra enfin de déployer notre premier agent. La suite au prochain épisode.