Infrastructure
Microsoft Entra Workload ID : diagnostiquer Conditional Access avant d’exclure un pipeline CI
Un runbook de production pour qualifier un blocage Conditional Access sur une workload identity avec logs de service principal, scope de policy, risque, identité CI, preuve KQL, exception bornée et rollback.
Une policy Conditional Access appliquée aux workload identities peut bloquer un pipeline critique sans qu’aucun utilisateur interactif ne soit concerné. Le symptôme arrive souvent comme une panne CI : Terraform ne lit plus Azure, une release Azure DevOps ne récupère plus un secret, un job GitHub Actions échoue sur Microsoft Graph, ou un automatisme d’exploitation perd son accès au moment où il doit corriger la production.
La demande réflexe est simple : exclure le service principal du contrôle. C’est parfois nécessaire, mais c’est rarement la première action. Le runbook ci-dessous sert à qualifier le blocage avant d’ajouter une exception, en séparant policy, identité réelle, ressource appelée, risque workload, preuve de sign-in et retour arrière.
Cadrer l’incident d’identité
Commencez par figer le périmètre. Une workload identity peut représenter une app registration, un service principal utilisé par un pipeline, une fédération OIDC ou un connecteur d’automatisation. Les managed identities et certaines applications ne suivent pas toujours les mêmes règles de ciblage Conditional Access ; ne partez pas du principe que le nom visible dans le pipeline est l’identité évaluée par Entra.
Incident a qualifier
Systeme appelant: pipeline CI, job de deploiement ou runbook automatise
Plateforme: Azure DevOps, GitHub Actions, AWX ou orchestrateur interne
Identite attendue: spn-iac-prod-deploy
Type de credential: federation OIDC, certificat ou secret client
Ressource appelee: Azure Resource Manager, Microsoft Graph, Key Vault ou API interne
Erreur observee: access blocked due to Conditional Access policies
Changement recent: nouvelle policy, nouveau scope, changement de credential, changement d'IP egress
Decision attendue
Corriger la policy
Corriger l'identite ciblee
Ajouter une exception bornee
Revenir en report-only
Rollbacker le deploiement de policy Le cadrage évite deux erreurs classiques : exclure la mauvaise application, ou désactiver une protection globale pour résoudre un problème local de pipeline.
Prouver que Conditional Access bloque réellement
Le message d’erreur du pipeline ne suffit pas. Il peut masquer un secret expiré, une audience OIDC incorrecte, une permission Graph manquante ou un problème réseau vers l’endpoint d’authentification. La preuve doit venir des sign-in logs Entra, côté service principal.
let Lookback = 6h;
let AppName = "spn-iac-prod-deploy";
SigninLogs
| where TimeGenerated > ago(Lookback)
| where ServicePrincipalName == AppName or AppDisplayName == AppName
| project TimeGenerated,
AppDisplayName,
ServicePrincipalId,
ResourceDisplayName,
IPAddress,
ResultType,
ResultDescription,
ConditionalAccessStatus,
ConditionalAccessPolicies,
CorrelationId
| order by TimeGenerated desc Selon votre routage de logs, les événements peuvent être dans une table dédiée aux service principal sign-ins plutôt que dans SigninLogs. L’objectif reste le même : retrouver l’évaluation Conditional Access, la ressource cible et le CorrelationId qui relie le pipeline à Entra.
Lire la policy appliquée, pas seulement son nom
Une policy peut être appliquée parce que l’identité est explicitement ciblée, parce qu’un groupe d’applications est inclus, ou parce qu’une règle large couvre toutes les workload identities possédées par le tenant. L’onglet Conditional Access du sign-in log est souvent plus fiable qu’une lecture rapide de la liste des policies.
Elements a relever depuis le sign-in log
Policy appliquee: nom, id, etat actif ou report-only
Resultat: success, failure, notApplied ou reportOnlyFailure
Condition declenchante: workload identity, localisation, risque, ressource cloud, client app
Controle impose: block, require compliant network, grant control equivalent
Exclusions deja presentes: service principal, repertoire, groupe, location nommee
Derniere modification: auteur, date, ticket ou commit IaC
Question de securite
La policy bloque-t-elle le bon type d'identite ?
La condition detectee correspond-elle au risque attendu ?
L'identite CI aurait-elle du etre dans un groupe pilote ?
Une exception temporaire a-t-elle une date d'expiration et un owner ? Si la policy est en report-only, le pipeline n’est probablement pas bloqué par cette policy. Si elle est en enforcement et que le sign-in porte bien l’échec Conditional Access, vous pouvez passer au diagnostic de ciblage.
Vérifier l’identité effective du pipeline
Le nom du service connection ou du secret dans le pipeline n’est pas une preuve d’identité. Relevez le client ID, le tenant, le subject OIDC quand il existe, puis comparez-les avec le service principal vu dans les logs.
ci_identity:
pipeline: deploy-prod-network
provider: Azure DevOps or GitHub Actions
expected_client_id: 00000000-0000-0000-0000-000000000000
expected_tenant_id: 11111111-1111-1111-1111-111111111111
credential_type: federated_identity
oidc_subject: repo:platform/iac:environment:prod
entra_log_match:
service_principal_id: 22222222-2222-2222-2222-222222222222
app_display_name: spn-iac-prod-deploy
resource: Azure Resource Manager
conditional_access_status: failure
correlation_id: copy-from-signin-log
mismatch_checks:
- wrong tenant selected by tool
- old service connection still used by stage
- fallback client secret in variable group
- app registration duplicated for staging and prod
- federated credential subject not aligned with branch or environment Si l’identité effective n’est pas celle attendue, n’ajoutez pas d’exclusion. Corrigez d’abord le pipeline, le service connection, la fédération ou les variables qui sélectionnent le mauvais principal.
Séparer blocage légitime et faux positif opérationnel
Un blocage Conditional Access peut être sain. Par exemple, une identité de déploiement utilisée depuis une localisation inconnue, une credential volée, ou une app qui appelle une ressource non prévue doit rester bloquée. Le runbook doit donc qualifier le risque avant de restaurer le flux.
Blocage probablement legitime
IP egress inconnue ou hors runner attendu
Ressource appelee hors perimetre du pipeline
Service principal rarement utilise puis soudainement actif
Echec venant d'un pays ou reseau non approuve
Credential ancien, secret partage ou certificat non reference
Plusieurs echecs sur ressources differentes
Faux positif operationnel probable
Nouvelle policy pilotee sans groupe de test
Changement d'IP egress runner documente
Migration OIDC recente avec meme repo et meme environnement
Ressource appelee conforme au runbook de deploiement
Correlation entre rollout policy et debut des echecs
Aucun autre signal de risque workload La bonne question n’est pas “comment faire passer le pipeline ?”. C’est “quel contrôle peut être assoupli sans autoriser une identité compromise à agir ?”.
Préparer une exception bornée
Si le pipeline doit repartir, évitez l’exclusion large et permanente. Une exception exploitable doit porter un propriétaire, une durée, un périmètre d’identité, une ressource, une preuve et un rollback. Le plus sûr est souvent de limiter l’exception au service principal exact et à la ressource cloud attendue, puis de revenir vers une policy corrigée.
{
"exception": "ci-prod-deploy-workload-identity",
"reason": "Production deployment blocked by workload identity Conditional Access policy",
"identity_scope": {
"service_principal_id": "22222222-2222-2222-2222-222222222222",
"app_display_name": "spn-iac-prod-deploy"
},
"resource_scope": ["Azure Resource Manager"],
"allowed_conditions": {
"runner_egress": ["documented-nat-ip-or-named-location"],
"credential": "federated_identity_only",
"environment": "prod"
},
"expires_at": "2026-07-31T18:00:00Z",
"owner": "platform-security",
"evidence": ["signin_correlation_id", "pipeline_run_id", "policy_change_id"],
"rollback": "remove exclusion and restore policy enforcement"
} Une exception sans expiration devient vite une architecture parallèle. Si elle doit durer, transformez-la en règle documentée, testée et relue, pas en trou discret dans la policy.
Valider avant de relancer la production
Ne validez pas uniquement avec un pipeline vert. Vérifiez que le sign-in est passé par le chemin attendu, que les autres ressources restent bloquées, et que le comportement est visible dans les logs.
let Lookback = 2h;
let ServicePrincipalId = "22222222-2222-2222-2222-222222222222";
SigninLogs
| where TimeGenerated > ago(Lookback)
| where ServicePrincipalId == ServicePrincipalId
| project TimeGenerated,
AppDisplayName,
ResourceDisplayName,
IPAddress,
ResultType,
ResultDescription,
ConditionalAccessStatus,
ConditionalAccessPolicies,
CorrelationId
| summarize attempts=count(), failures=countif(ResultType != 0), resources=make_set(ResourceDisplayName, 10), ips=make_set(IPAddress, 10), caStates=make_set(ConditionalAccessStatus, 10) by bin(TimeGenerated, 15m)
| order by TimeGenerated desc Complétez avec un test négatif : même identité depuis une source non autorisée, ou même source vers une ressource non prévue. Si tout passe, l’exception est trop large.
Décider correction ou rollback
La décision finale doit être lisible par l’équipe d’exploitation, pas seulement par l’équipe identité. Notez ce qui est restauré, ce qui reste bloqué, et ce qui doit être retiré après incident.
Autoriser temporairement
Le blocage vient bien de Conditional Access workload identity
L'identite effective correspond au service principal attendu
La ressource appelee est dans le perimetre du pipeline
Aucun signal de risque workload n'est observe
L'exception est bornee par service principal, ressource, source et expiration
Le test negatif prouve que l'exception n'ouvre pas tout
Corriger sans exception
Le pipeline utilise la mauvaise identite
La federation OIDC ne correspond pas a l'environnement
La policy cible un groupe pilote incorrect
La ressource appelee n'est pas celle attendue
La policy est en report-only et ne bloque pas reellement
Rollbacker
Le blocage suit immediatement un rollout de policy non valide
Plusieurs workloads critiques sont coupes hors perimetre prevu
Les logs ne permettent pas d'expliquer l'evaluation
L'exception necessaire serait trop large
Un signal de credential compromisee existe Le rollback peut être le retrait de la policy, le retour en report-only, la suppression de l’exclusion ou le basculement temporaire vers une identité de secours déjà validée. Il doit être testé comme une action de production, pas improvisé dans le portail.
Conclusion
Conditional Access pour workload identities est un bon contrôle quand il reste explicable. Il devient dangereux quand l’équipe ne sait plus quelle identité a été évaluée, quelle policy l’a bloquée, et quelle exception restaure seulement le flux attendu.
Avant d’exclure un pipeline CI, prouvez le blocage dans les sign-in logs, alignez l’identité effective, qualifiez le risque, bornez l’exception et validez par un test négatif. La meilleure issue n’est pas forcément de faire passer le job ; c’est de faire passer le bon job, avec la bonne identité, et un retour arrière déjà prêt.