# Connecter un tenant Microsoft Azure

Créer un principal de service Azure en lecture seule (rôle Reader) pour inventorier les ressources cloud et remonter les constats de posture et les recommandations Defender for Cloud.

> **Accès :** administrateur d’entreprise. Fonctionnalité en **bêta** ; le connecteur doit être activé sur votre plateforme.

## Prérequis

- Être administrateur de l’entreprise dans CISAPP.
- Pouvoir créer une **inscription d’application** dans Microsoft Entra ID et attribuer un rôle sur les abonnements visés (ou sur leur groupe d’administration) : propriétaire, administrateur de l’accès utilisateur ou droits équivalents.
- Un tenant Azure ne peut être connecté qu’à **une seule** organisation CISAPP ; une organisation peut en revanche connecter plusieurs tenants.
- Cloud Azure **public** uniquement : les clouds Chine (21Vianet) et US Government ne sont pas pris en charge.

### Droits minimaux

Le rôle **Reader** (Lecteur) suffit, sur chaque abonnement à analyser ou sur un groupe d’administration. Le rôle **Security Reader** n’est pas nécessaire : Reader lit déjà les recommandations de Microsoft Defender for Cloud.

**N’accordez jamais** Contributor, Owner, User Access Administrator, ni un rôle d’accès aux données (par exemple Key Vault Secrets User, Storage Blob Data Reader) : CISAPP n’en a pas besoin. Aucune permission Microsoft Graph n’est requise non plus.

## Créer l’accès dans Azure

CISAPP n’utilise jamais votre compte personnel : créez un **principal de service** dédié, en lecture seule, avec un **secret client**.

### Avec Azure CLI

Remplacez `<subscriptionId>` par l’identifiant de l’abonnement à analyser.

```bash
az ad sp create-for-rbac --name cisapp-reader --role Reader --scopes /subscriptions/<subscriptionId> --years 1
```

Plusieurs abonnements : séparez les portées par des espaces.

```bash
az ad sp create-for-rbac --name cisapp-reader --role Reader --scopes /subscriptions/<subscriptionId1> /subscriptions/<subscriptionId2>
```

Un groupe d’administration (couvre les abonnements actuels et futurs). Indiquez son **identifiant**, pas son nom d’affichage :

```bash
az ad sp create-for-rbac --name cisapp-reader --role Reader --scopes /providers/Microsoft.Management/managementGroups/<managementGroupId>
```

N’exécutez qu’**une** de ces trois commandes (chacune crée le principal de service). Pour étendre ensuite le périmètre, utilisez `az role assignment create` :

```bash
az role assignment create --assignee <appId> --role Reader --scope /subscriptions/<subscriptionId>
```

La commande de création affiche un JSON, **une seule fois** ; le secret ne peut plus être relu ensuite :

| Champ affiché par Azure | Champ CISAPP |
| --- | --- |
| `tenant` | **Tenant** |
| `appId` | **Identifiant client** |
| `password` | **Secret client** (c’est la **valeur** du secret) |
| `displayName` | Information seulement, non demandé |

Le secret est valable un an (`--years 1`). Pour relever sa date de fin (à saisir dans CISAPP, voir plus bas ; gardez les 10 premiers caractères, au format `AAAA-MM-JJ`) :

```bash
az ad app credential list --id <appId> --query "[].[displayName,keyId,endDateTime]" -o tsv
```

La commande affiche aussi le `keyId` de chaque secret, utile pour supprimer l’ancien lors d’une rotation. La date saisie dans CISAPP doit être **à venir**.

### Depuis le portail

1. Dans le centre d’administration Microsoft Entra, **Inscriptions d’applications → Nouvelle inscription** : un seul tenant, sans URI de redirection, et n’ajoutez aucune permission d’API (Microsoft Graph). Copiez l’**ID d’application (client)** et l’**ID de l’annuaire (tenant)**.
2. **Certificats & secrets → Nouveau secret client** : choisissez une expiration, puis copiez immédiatement la **Valeur** (et non l’**ID du secret**).
3. Dans le portail Azure, ouvrez **Abonnements** (ou **Groupes d’administration**), choisissez la portée, puis **Contrôle d’accès (IAM) → Ajouter → Ajouter une attribution de rôle**.
4. Choisissez le rôle **Reader** (Lecteur), puis **Membres → Sélectionner des membres**, recherchez le nom de l’application, sélectionnez-la et validez avec **Vérifier + attribuer**. Répétez pour chaque abonnement.

> Une attribution de rôle peut mettre jusqu’à **10 minutes** à se propager (parfois davantage pour un groupe d’administration). Si CISAPP ne voit encore aucun abonnement, patientez puis réessayez.

## Connecter dans CISAPP

1. Ouvrez **Mon entreprise → Connecteurs**, puis **Connecter** sur la carte Azure.
2. Renseignez :
   - **Tenant** : le GUID de l’annuaire (champ `tenant` de la commande), ou un domaine vérifié du tenant (par exemple `contoso.onmicrosoft.com`) ;
   - **Identifiant client** : l’ID d’application (`appId`) ;
   - **Secret client** : la **valeur** du secret (pas son ID) ;
   - **Le secret expire le** (facultatif, format `AAAA-MM-JJ`, obligatoirement **une date à venir**) : permet d’être alerté 30 jours avant l’expiration du secret ;
   - **Abonnements** (facultatif) : identifiants GUID, 100 au maximum. Vide : tous les abonnements que le principal peut lire (au-delà de 100 abonnements, laissez le champ vide ou attribuez le rôle Reader sur un groupe d’administration). La liste se modifie plus tard depuis la fiche.
3. **Vérifier les identifiants** : CISAPP teste les identifiants auprès de Microsoft avant d’enregistrer quoi que ce soit.
4. À l’étape **Confirmer le tenant Azure**, contrôlez l’**identifiant du tenant** affiché, puis **Connecter**. Un tenant Azure ne peut être connecté qu’à une seule organisation CISAPP. La première synchronisation démarre.

Si vous fermez le panneau avant la confirmation, la connexion reste **En attente** : utilisez **Confirmer le compte** depuis sa fiche.

Les abonnements dont l’état est **Disabled** ne sont pas collectés (voir « Abonnement non collecté » ci-dessous). Connecter un tenant déjà rattaché à une autre organisation CISAPP est refusé (« Ce tenant Azure est déjà connecté par une autre organisation CISAPP. »).

## Ce que CISAPP collecte

CISAPP interroge **Azure Resource Graph** et quelques lectures ciblées d’Azure Resource Manager. Il ne lit que des **configurations**, jamais de contenu :

- comptes de stockage (configuration du service blob, pas les objets) ;
- groupes de sécurité réseau, réseaux virtuels et sous-réseaux, adresses IP publiques ;
- machines virtuelles et disques managés ;
- serveurs SQL (Azure SQL), serveurs flexibles PostgreSQL et MySQL, comptes Cosmos DB ;
- coffres Key Vault (propriétés du coffre uniquement), clusters AKS ;
- applications App Service et Functions ;
- abonnements et nombre de propriétaires (attributions de rôle Owner) ;
- recommandations de Microsoft Defender for Cloud.

CISAPP ne modifie rien dans votre tenant. Il ne lit jamais les clés d’accès, les secrets, les paramètres d’application, les chaînes de connexion ni les fichiers `kubeconfig`, et n’utilise pas le plan de données de Key Vault. Le rôle Reader ne permet d’ailleurs pas les actions qui révèlent ces valeurs, et CISAPP ne les appelle pas. Les ressources sont visibles dans le menu **Sécurité opérationnelle → Patrimoine cloud** et sa **Cartographie**.

## Constats de posture

Les constats apparaissent dans les constats de sécurité avec la source **Posture Azure**. Une règle ne se déclenche que si l’information est certaine : un état inconnu (droit manquant, donnée absente, ressource non collectée) ne crée ni ne résout de constat.

| Identifiant | Règle | Gravité |
| --- | --- | --- |
| `azure-storage-public-blob-access` | Compte de stockage autorisant l’accès public aux blobs | Élevée |
| `azure-storage-http-allowed` | Compte de stockage acceptant le trafic HTTP non chiffré | Moyenne |
| `azure-storage-weak-tls` | Compte de stockage acceptant TLS 1.0 ou 1.1 | Moyenne |
| `azure-storage-network-open` | Compte de stockage ouvert à tous les réseaux | Moyenne |
| `azure-storage-blob-soft-delete-disabled` | Compte de stockage sans suppression réversible des blobs | Faible |
| `azure-nsg-remote-admin-exposed` | Groupe de sécurité réseau exposant SSH ou RDP à Internet | Élevée |
| `azure-nsg-database-ports-exposed` | Groupe de sécurité réseau exposant un port de base de données à Internet | Élevée |
| `azure-sql-public-network-access` | Serveur SQL accessible depuis le réseau public | Moyenne |
| `azure-sql-weak-tls` | Serveur SQL acceptant TLS inférieur à 1.2 | Moyenne |
| `azure-sql-firewall-open-to-internet` | Serveur SQL avec règle de pare-feu ouverte à toutes les adresses IP | Critique |
| `azure-dbflex-public-network-access` | Serveur PostgreSQL/MySQL flexible accessible depuis le réseau public | Moyenne |
| `azure-dbflex-tls-not-required` | Serveur PostgreSQL/MySQL flexible n’imposant pas TLS | Élevée |
| `azure-keyvault-purge-protection-disabled` | Coffre de clés sans protection contre la purge | Moyenne |
| `azure-keyvault-public-network-open` | Coffre de clés ouvert à tous les réseaux | Moyenne |
| `azure-aks-api-server-public` | Cluster AKS dont l’API Kubernetes est exposée sans restriction IP | Élevée |
| `azure-aks-rbac-disabled` | Cluster AKS sans RBAC Kubernetes | Élevée |
| `azure-webapp-https-only-disabled` | Application web n’imposant pas HTTPS | Moyenne |
| `azure-webapp-weak-tls` | Application web acceptant TLS 1.0 ou 1.1 | Moyenne |
| `azure-cosmos-public-network-open` | Compte Cosmos DB accessible publiquement sans filtre | Élevée |
| `azure-subscription-too-many-owners` | Abonnement avec plus de 3 propriétaires (Owner) | Moyenne |

Un pare-feu SQL n’est signalé que pour la plage complète 0.0.0.0 à 255.255.255.255 ; la règle spéciale « services Azure » (0.0.0.0 à 0.0.0.0) ne déclenche pas de constat, et un serveur dont l’accès réseau public est désactivé est conforme.

Pour les groupes de sécurité réseau, les règles sont évaluées par priorité : une règle illisible placée avant la règle décisive rend l’état inconnu, et une règle de refus ne ferme un port pour tout le groupe que si sa destination est quelconque (`*`, `0.0.0.0/0`, `::/0`).

### Abonnement non collecté

Si un abonnement sélectionné n’est pas collecté (état **Disabled**, identifiant configuré mais plus listé, ou pas encore visible d’Azure Resource Graph), CISAPP crée toujours les nouveaux constats mais **ne résout automatiquement aucun constat des règles CISAPP** pendant cette synchronisation, et ne supprime rien de cet abonnement. Les recommandations Defender for Cloud des abonnements collectés se résolvent normalement. La cause est signalée par une note en anglais, affichée sous le texte de la dernière synchronisation incomplète : `Posture findings are not auto-resolved while these subscriptions are not collected: <ids>. Remove them from subscriptionIds, or wait until Azure deletes them.`

Azure supprime un abonnement **Disabled** environ 90 jours plus tard ; il disparaît alors de la liste. Si vous avez saisi une liste d’abonnements, retirez-le de la liste. Si un abonnement **Disabled** reste listé (mode par défaut : tous les abonnements), saisissez une liste explicite d’abonnements qui ne le contient pas pour reprendre la résolution automatique.

### Recommandations Defender for Cloud

Si Microsoft Defender for Cloud est activé sur un abonnement, CISAPP importe aussi ses recommandations à l’état **Unhealthy** comme constats, avec la même source **Posture Azure**. Un constat est créé par recommandation et par ressource concernée. Leurs titres, descriptions et gravités sont ceux de Microsoft : ils restent en **anglais**. Le nombre de recommandations importées est plafonné par abonnement (les plus graves d’abord). Quand une recommandation n’est plus en défaut, son constat est résolu. Si Defender for Cloud n’est pas activé ou ne renvoie aucune donnée, rien n’est importé ni résolu. Rien n’est non plus résolu lorsque le plafond est atteint.

### Expiration du secret

La date d’expiration (**Le secret expire le**) est traitée à part des règles : sans date saisie, aucun avertissement n’est affiché ; à moins de 30 jours de l’échéance déclarée, un badge **Identifiants bientôt expirés** apparaît sur la fiche.

## Remplacer le secret (rotation)

1. Créez un nouveau secret **en conservant l’ancien** :

   ```bash
   az ad app credential reset --id <appId> --append --years 1 --display-name cisapp-AAAA
   ```

   N’oubliez jamais `--append` : sans lui, la commande supprime tous les secrets existants et la connexion tombe immédiatement en erreur.
2. Sur la fiche de la connexion, **Mettre à jour les identifiants** : dans le panneau **Remplacer le secret Azure**, collez la **valeur** du nouveau secret, renseignez **Le secret expire le** avec sa nouvelle date (obligatoirement à venir : le champ est prérempli avec l’ancienne date, à remplacer surtout après une expiration), puis **Vérifier et remplacer**. L’ancien secret reste utilisé tant que le nouveau n’est pas validé.
3. Le nouveau secret doit appartenir au **même tenant Azure** ; sinon il est refusé et le secret actuel est conservé.
4. Supprimez ensuite l’ancien secret : relevez son `keyId` avec `az ad app credential list --id <appId> --query "[].[displayName,keyId,endDateTime]" -o tsv`, puis `az ad app credential delete --id <appId> --key-id <keyId>`.

Les abonnements se modifient depuis la fiche (**Modifier**, panneau **Modifier le périmètre**), sans ressaisir le secret. Retirer un abonnement de la connexion retire ses ressources de l’inventaire à la synchronisation suivante. La date d’expiration (**Le secret expire le**), elle, se met à jour avec le secret, pas depuis **Modifier**.

Un secret expiré met la connexion en **Erreur** (**Identifiants expirés**) : créez un nouveau secret et faites la rotation depuis la fiche.

## Difficultés courantes

**À la connexion**, Azure ne détaille pas la cause dans l’interface : tout refus affiche le message « Azure a refusé ces identifiants : secret invalide (collez la valeur du secret, pas son identifiant) ou expiré, application ou tenant introuvable, accès bloqué par une politique d’accès conditionnel, ou rôle Reader absent… ». **À la synchronisation**, les codes AADSTS ci-dessous apparaissent dans **Dernière synchronisation incomplète** (fiche de la connexion) lorsqu’un secret déjà enregistré est refusé ; leur sens y diffère parfois de celui de la connexion.

| Message | Que faire |
| --- | --- |
| Le connecteur Azure est indisponible sur cette instance CISAPP (chiffrement des secrets non configuré). Contactez le support. | Le connecteur n’est pas encore configuré sur votre plateforme : contactez le support. |
| Azure a refusé ces identifiants… | Vérifiez, dans l’ordre : la **valeur** du secret (pas son ID), sa date d’expiration, le **Tenant** et l’**Identifiant client**, l’absence de politique d’accès conditionnel bloquant l’application, et l’attribution du rôle Reader sur chaque abonnement indiqué (propagation : jusqu’à 10 minutes). |
| AADSTS7000215 / AADSTS70002 à la synchronisation (secret invalide) | Le secret enregistré a été supprimé ou remplacé côté Azure (par exemple `az ad app credential reset` sans `--append`) : créez un nouveau secret et faites la rotation depuis la fiche. À la connexion, la cause habituelle est l’**ID du secret** collé à la place de sa **valeur** (`password` dans la sortie de la commande). |
| AADSTS7000222 (secret expiré) | Le secret client a expiré : créez-en un nouveau et faites la rotation depuis la fiche. |
| AADSTS700016 (application introuvable) | À la connexion : l’identifiant client ou le tenant est incorrect, vérifiez que l’application appartient bien à ce tenant. À la synchronisation : l’application a été supprimée dans Microsoft Entra ID ; recréez-la, puis faites la rotation depuis la fiche. |
| AADSTS90002 (tenant introuvable) | L’identifiant ou le domaine du tenant est incorrect : utilisez le GUID de l’annuaire. |
| Ce principal de service appartient à un autre tenant Azure : le secret actuel est conservé. | Lors d’une rotation, le nouveau secret doit appartenir au même tenant que la connexion. |
| Statut **Permissions insuffisantes** et dernière synchronisation `no readable subscription` (message en anglais) | Le rôle Reader n’est pas attribué à l’application (ou a été retiré), ou l’attribution n’est pas encore propagée (jusqu’à 10 minutes) : vérifiez l’attribution, patientez puis réessayez. |
| Un abonnement est signalé comme non lisible dans la synchronisation (message en anglais, `Subscription … not readable`) | Le rôle Reader manque sur cet abonnement, ou son identifiant est erroné dans la liste : les autres abonnements sont analysés normalement. Corrigez l’attribution ou retirez-le de la liste. |
| Abonnement absent de l’inventaire, ou constats qui ne se résolvent plus | Un abonnement sélectionné n’est pas collecté (état **Disabled**, plus listé, pas encore visible d’Azure Resource Graph) : la synchronisation le signale (note sous la dernière synchronisation incomplète) et suspend la résolution automatique des constats de règles CISAPP. Voir « Abonnement non collecté ». |
| Ressource récente absente | Azure Resource Graph est à cohérence différée : une ressource créée à l’instant apparaît à la synchronisation suivante. |
| Ce tenant Azure est déjà connecté par une autre organisation CISAPP. | Un tenant Azure n’a qu’une connexion : déconnectez-le d’abord de l’autre organisation CISAPP. |
| Identifiants expirés ou Identifiants refusés | Créez un nouveau secret et faites la rotation depuis la fiche. |

## Limites

- Cloud Azure public uniquement (pas de Chine ni d’US Government).
- Un tenant Azure ne peut être connecté qu’à une seule organisation CISAPP ; une organisation peut connecter plusieurs tenants.
- La synchronisation suit la même périodicité que les autres connecteurs cloud : automatique chaque nuit, et relançable à la demande avec **Synchroniser** sur la fiche.
- La date d’expiration du secret est **déclarative** : CISAPP ne peut pas la lire dans Azure, et elle doit être à venir. Sans date, l’expiration n’est détectée qu’au moment où Microsoft refuse le secret.
- Les abonnements sélectionnés sont limités à 100 (au-delà : champ vide, ou rôle Reader sur un groupe d’administration).
- Quand un abonnement quitte le périmètre (retiré de la liste, ou supprimé par Azure), ses ressources sont retirées de l’inventaire et ses constats de règles CISAPP sont résolus, mais ses recommandations Defender for Cloud déjà importées restent ouvertes jusqu’à la déconnexion du connecteur.

## Déconnecter

**Déconnecter** supprime la connexion et l’inventaire cloud associé, et passe ses constats de posture en résolus. Supprimez ensuite le secret (ou l’inscription d’application et ses attributions de rôle si elles n’ont plus d’usage) dans Microsoft Entra ID et dans le portail Azure.

## Résultat attendu

La connexion est active, l’inventaire cloud est alimenté et les constats de posture Azure, ainsi que les recommandations Defender for Cloud, remontent dans CISAPP.

Voir aussi : [Configurer les connecteurs](https://docs.cisapp.eu/organisation/connecteurs).
