> ## Documentation Index
> Fetch the complete documentation index at: https://docs.snakysec.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Onboarding client

# Runbook — Onboarding d'un nouveau client

**Temps estimé:** 30–60 min
**Prérequis:** Accès MSSP\_ADMIN sur la plateforme + accès Azure Portal tenant client
**Dernière mise à jour:** 2026-04-09

***

## Checklist pré-onboarding

* [ ] Contrat signé + DPA (RGPD) en place
* [ ] Tenant ID Microsoft 365 fourni par le client
* [ ] Product areas à auditer confirmées (Entra, Exchange, Teams, SharePoint, Defender, Purview)
* [ ] Cadence d'audit définie (hebdomadaire / mensuelle)
* [ ] Contact technique client identifié
* [ ] Domaine de connexion SSO choisi (ex: `acme-corp.snakysec.com` ou domaine custom)

***

## Étape 1 — Créer l'app registration Entra ID chez le client

Dans le tenant client (Azure Portal > Microsoft Entra ID) :

### 1.1 Enregistrer l'application

```
App registrations → New registration
  - Name: "SnakySec Audit"
  - Supported account types: "Accounts in this organizational directory only"
  - Redirect URI: Web → https://snakysec.com/api/auth/callback/microsoft-entra-id
```

### 1.2 Ajouter les permissions Graph API (Application)

Permissions minimales par product area :

| Area       | Permissions                                                              |
| ---------- | ------------------------------------------------------------------------ |
| Entra      | `Directory.Read.All`, `Policy.Read.All`, `RoleManagement.Read.Directory` |
| Exchange   | `MailboxSettings.Read`, `Mail.Read` (+ EXO PowerShell module)            |
| Teams      | `TeamSettings.Read.All` (+ Teams PowerShell module)                      |
| SharePoint | `SharePointTenantSettings.ReadWrite.All` (+ SPO PowerShell module)       |
| Defender   | `SecurityEvents.Read.All` (+ EXO PowerShell module for transport rules)  |
| Purview    | `InformationProtectionPolicy.Read.All`                                   |
| Commun     | `AuditLog.Read.All`, `Organization.Read.All`                             |

> Les permissions exactes sont listées dans chaque fichier framework :
> `src/frameworks/cis/*.json` et `src/frameworks/scuba/*.json` (champ `requiredPermissions`).

**Grant admin consent** après avoir ajouté toutes les permissions.

### 1.3 Configurer l'authentification par certificat

```
Certificates & secrets → Certificates → Upload certificate
  - Uploader le fichier .cer ou .pem (clé publique uniquement)
  - Noter le thumbprint
```

> Pas de client\_secret. L'authentification X.509 est obligatoire en production.
> Voir ADR: docs/adr/003-x509-over-client-secret.md

### 1.4 Créer une 2ème app pour le SSO (si le client veut se connecter à la plateforme)

```
App registrations → New registration
  - Name: "SnakySec Portal SSO"
  - Supported account types: "Accounts in this organizational directory only"
  - Redirect URI: Web → https://snakysec.com/api/auth/callback/microsoft-entra-id
  - Permissions: openid, profile, email, User.Read, offline_access
  - Certificates & secrets → Upload certificate (même certificat ou dédié)
```

### 1.5 Collecter les informations

```
Application (client) ID audit  : <AUDIT_CLIENT_ID>
Application (client) ID SSO    : <SSO_CLIENT_ID>
Directory (tenant) ID          : <TENANT_ID>
Certificate private key (.pem) : entra-app.key.pem
Certificate public key (.pem)  : entra-app.cert.pem
```

***

## Étape 2 — Stocker les credentials dans Vault

Depuis le serveur VPS (ou via `docker exec`) :

```bash theme={null}
# Lire les certificats en une ligne (Vault accepte les sauts de ligne)
CERT_PEM=$(cat entra-app.cert.pem)
CERT_KEY=$(cat entra-app.key.pem)

docker exec mssp-vault vault kv put mssp/clients/<slug> \
  tenant_id="<TENANT_ID>" \
  sso_client_id="<SSO_CLIENT_ID>" \
  audit_client_id="<AUDIT_CLIENT_ID>" \
  entra_cert_pem="$CERT_PEM" \
  entra_cert_private_key="$CERT_KEY"
```

**Vérifier :**

```bash theme={null}
docker exec mssp-vault vault kv get mssp/clients/<slug>
```

> Les clés attendues par le code (`src/lib/vault.ts:getClientSecrets`) :
> `tenant_id`, `sso_client_id`, `audit_client_id`, `entra_cert_pem`, `entra_cert_private_key`

***

## Étape 3 — Créer le client sur la plateforme

### Via l'interface admin

Dashboard → Clients → Nouveau client :

* **Nom** : Acme Corp
* **Slug** : `acme-corp` (lowercase, hyphens uniquement)
* **Tenant ID** : `<TENANT_ID>`
* **CI Client ID** : `<AUDIT_CLIENT_ID>` (UUID de l'app registration audit)
* **Product areas** : cocher les areas contractuelles
* **CISO Assistant** : activer si applicable

### Via l'API

```bash theme={null}
curl -X POST https://snakysec.com/api/v1/clients \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "slug": "acme-corp",
    "tenantId": "<TENANT_ID>",
    "ciClientId": "<AUDIT_CLIENT_ID>",
    "environment": "prod",
    "featureEntra": true,
    "featureIntune": true,
    "featureDefender": true,
    "featureTeams": false,
    "featureSharepoint": false,
    "featurePurview": false
  }'
```

***

## Étape 4 — Configurer le domaine SSO

Le client doit pouvoir se connecter via un domaine dédié (ex: `acme-corp.snakysec.com`).

### 4.1 Ajouter le domaine au client

```bash theme={null}
curl -X PATCH https://snakysec.com/api/v1/clients/<id> \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "acme-corp.snakysec.com" }'
```

Ou via l'interface admin : Clients → Acme Corp → Edit → Domain.

### 4.2 Configurer le DNS

Ajouter un CNAME dans Cloudflare (ou le DNS du sous-domaine) :

```
acme-corp.snakysec.com → snakysec.com (CNAME, proxied)
```

Le login page résout automatiquement : `hostname → Client.domain (DB) → slug → Vault secrets → Entra SSO`.

***

## Étape 5 — Lancer le premier audit de validation

### Smoke test (rapide, sans écriture d'artefacts)

Depuis l'UI : Dashboard → Audits → Trigger → sélectionner le client, framework CIS, area Entra.

Ou via API :

```bash theme={null}
curl -X POST https://snakysec.com/api/v1/audits/trigger \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "<CLIENT_PRISMA_ID>",
    "framework": "cis",
    "productArea": "entra"
  }'
```

### Audit complet

```bash theme={null}
curl -X POST https://snakysec.com/api/v1/audits/trigger \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "<CLIENT_PRISMA_ID>",
    "framework": "all",
    "productArea": "all"
  }'
```

Suivre la progression : Dashboard → Audits → barre de progression en temps réel.

***

## Étape 6 — Configurer la cadence d'audit

```bash theme={null}
curl -X PATCH https://snakysec.com/api/v1/clients/<id> \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "cronExpression": "0 6 * * 1" }'
```

Expressions courantes :

* `0 6 * * 1` — lundi 6h (hebdomadaire)
* `0 6 1 * *` — 1er du mois 6h (mensuel)
* `0 6 * * 1,4` — lundi + jeudi 6h (bi-hebdo)

***

## Étape 7 — Créer l'accès CLIENT\_USER

Quand le contact client se connecte via SSO pour la première fois, un utilisateur est créé automatiquement avec le rôle `MSSP_ADMIN` (par défaut). Ajuster le rôle :

```bash theme={null}
# Via Prisma Studio ou directement en base
UPDATE users SET role = 'CLIENT_USER' WHERE email = 'contact@acme-corp.com';
```

Puis associer l'utilisateur au client :

```bash theme={null}
curl -X POST https://snakysec.com/api/v1/clients/<id>/users \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "userId": "<USER_ID>" }'
```

***

## Checklist post-onboarding

* [ ] Vault secrets écrits et vérifiés (`vault kv get mssp/clients/<slug>`)
* [ ] Client créé en base (visible dans Dashboard → Clients)
* [ ] Domaine SSO configuré et DNS propagé
* [ ] Premier audit terminé avec status `COMPLETED`
* [ ] Score de conformité calculé (> 0%)
* [ ] Gap findings importés en base
* [ ] Accès CLIENT\_USER créé pour le contact client
* [ ] Cadence d'audit planifiée (cronExpression renseignée)
* [ ] CISO Assistant configuré (si applicable)

***

## Dépannage

### L'audit échoue avec "insufficient\_perms"

Le pre-flight check a détecté des permissions manquantes. Vérifier :

1. Les permissions Graph API de l'app registration (admin consent ?)
2. Le certificat est-il bien celui associé à l'app ?
3. La clé privée dans Vault correspond-elle au certificat uploadé ?

### Le SSO ne fonctionne pas

1. Vérifier `Client.domain` en DB correspond au hostname
2. Vérifier le CNAME DNS pointe vers snakysec.com
3. Vérifier les Vault secrets (`sso_client_id`, `tenant_id`)
4. Vérifier la redirect URI dans l'app SSO Entra

### L'import d'artefacts échoue

1. Vérifier le webhook GitLab (`/api/webhooks/gitlab`)
2. Sync manuelle : Dashboard → Audit → Sync
3. Vérifier les logs : `docker logs mssp-next-app`

***

## Rollback

Si l'onboarding échoue et doit être annulé :

1. **Supprimer le client** via `DELETE /api/v1/clients/:id/gdpr` (header `X-Purge-Confirm: purge`)
2. **Supprimer les secrets Vault** : `docker exec mssp-vault vault kv delete mssp/clients/<slug>`
3. **Révoquer l'app registration** dans le tenant client (Azure Portal)
4. **Supprimer le CNAME DNS** si configuré
