La gestion des identités et de l’authentification sur le cloud public est un sujet demandant beaucoup d’attention et de réflexion. En effet, il peut être parfois compliqué de porter un modèle IAM existant sur un hébergeur donné. Et ceci s’accentue encore plus lorsque l’on se retrouve dans un contexte multi cloud provider, chacun ayant sa propre vision de ce que doit être la gestion d’identité. Et Azure n’échappe pas à la règle.

Si vous ne le saviez pas, le cloud de Microsoft se base sur un système unique en son genre centré autour d’un composant : l’Azure Active Directory. Très similaire à ce que l’on peut retrouver dans un Active Directory classique, celui que l’on appelle plus communément l’Azure AD est la pierre angulaire de la gestion des identités chez la société de Redmond. Cela apporte des avantages, comme par exemple le portage de l’authentification de vos applications ou encore la synchronisation simple d’un AD on-premise vers Azure. Cependant, celle-ci est également un de ses plus gros désavantages puisque jusqu'à récemment, si l’on souhaitait utiliser un fournisseur d'identités tiers déjà existant, ce n’était tout bonnement pas possible.

Dans cet article, nous allons nous concentrer sur External Identities, une nouvelle fonctionnalité permettant de répondre à cette problématique.

Bring Your Own Identity

En mars dernier, Microsoft a mis à disposition External Identities, un composant faisant partie intégrante de l’Azure Active Directory. Celui-ci a été conçu pour donner la possibilité aux entreprises de fournir un accès à leurs applications et ressources Azure à des personnes extérieures tout en les laissant s’authentifier en utilisant le fournisseur d'identités de leur choix. Ceci permet alors à des distributeurs, partenaires, ou clients d’amener leur propre identité (on emploie alors le terme de “Bring Your Own Identity”) et d’utiliser leurs identifiants pour accéder à vos ressources tout en gardant la mainmise sur les accès donnés à ces personnes.

À ce jour, External Identities supporte plusieurs fournisseurs d'identités :

  • Microsoft Account : les utilisateurs invités peuvent utiliser leur propre compte Microsoft. On parle alors de collaboration B2B.
  • Email one-time password : envoi d’un code temporaire par mail à l’utilisateur pour accéder aux ressources.
  • Google : autorise l’authentification directement via son compte Gmail.
  • Facebook : permet la mise en place d’un service d’inscription à vos applications par le biais d’un compte Facebook. À noter cependant que ceci ne fonctionne pas pour l’authentification au portail Azure mais uniquement pour l'inscription en self-service.
  • Direct Federation : donne la possibilité de configurer une fédération avec tout fournisseur externe d'identités qui supporte les protocoles d’authentification SAML ou WS-Fed.

Pour toute information concernant la configuration de ces différents types de provider, Microsoft met à disposition cette documentation (section “How-to-guides -> Identity Providers) décrivant de manière succincte les différentes étapes pour mettre en place cette fonctionnalité.

Même si l’ouverture du cloud de Microsoft à d'autres fournisseurs d'identités est réelle, une dépendance à l’Azure Active Directory reste bien présente. En effet, la structuration de l’IAM Azure est centralisée autour de cette brique, ce qui nous oblige à lui rattacher ces identités externes, notamment pour des questions d’affectations de droits. La conséquence directe de cela est la nécessité de créer, pour chaque entité externe, un utilisateur de type “Guest” avec son propre nom de domaine.

Même si l’on pourrait s’attendre à ce que l’opération soit faite automatiquement, cette création manuelle est belle et bien nécessaire pour s’intégrer au modèle Azure.

Concrètement, comment ça se passe ?

Lorsque vous avez fait le choix du fournisseur d'identités que vous allez utiliser, il vous faudra configurer la fédération avec Azure. La procédure ainsi que le processus d’authentification diffèrent alors selon le provider sélectionné. Nous allons ici nous concentrer sur la fonctionnalité au travers du protocole SAML.

Pour ce protocole en particulier, voici à quoi ressemble le processus d’authentification :

  1. Accéder à l’adresse https://portal.azure.com/<TENANT_ID> en renseignant l’ID de l’organisation Azure (tenant) sur lequel vous souhaitez vous connecter. Il est indispensable de le mentionner puisqu’Azure doit être en mesure d’identifier que vous utilisez un utilisateur externe.
  2. Renseigner l’adresse mail de l’utilisateur externe avec le domaine renseigné lors de la configuration de la délégation.
  3. Azure va alors détecter que l’utilisateur en question est soumis à la fonctionnalité d’External Identities et vous rediriger vers l’IDP que vous avez configuré pour ce domaine.
  4. Se connecter au provider externe comme on le ferait normalement.
  5. Une fois authentifié, une nouvelle redirection sur Azure est ainsi effectuée et vous voilà connecté sur votre tenant Azure !

À noter que le processus d’authentification ne peut s’initier qu’à partir d’Azure et non pas depuis le fournisseur d'identités. En effet, il est nécessaire que celui-ci détecte que vous souhaitez utiliser une identité externe pour ensuite engager la redirection vers votre IDP. On parle alors de connexion Service Provider initiated (vs IDP initiated).

Pour accéder à la configuration relative aux External Identities, rendez-vous sur le portail Azure dans la partie Azure Active Directory, accédez à la tuile correspondante puis sélectionnez “All identity providers”. Vous obtenez ainsi la page de configuration des fournisseurs d'identités :

Cette section résume tous les IDP configurés sur votre tenant. Vous avez ainsi à votre disposition tous les types de fournisseurs énoncés précédemment. Il ne vous reste donc plus qu’à configurer votre fournisseur d'identités et à le renseigner sur cette page. Dans le cadre de cet article, cette partie sera couverte par un cas pratique dans la section suivante.

Un cas pratique

Histoire de mettre la main à la pâte, nous allons rentrer un peu plus dans le concret avec un cas pratique d’implémentation d’External Identities. Comme énoncé précédemment, nous prenons ici le parti d’utiliser le SAML comme protocole d’authentification. Le fournisseur d'identités que nous allons utiliser sera Keycloak, un composant open source sous la gestion de RedHat.

Afin de simuler la demande d’accès d’un partenaire à nos ressources Azure, nous allons utiliser le domaine mycompany.org comme exemple. L’objectif sera donc d’authentifier les utilisateurs de ce domaine sur notre tenant Azure grâce à External Identities.

Pour ce qui est du déploiement, nous utiliserons Terraform, outil d’Infrastructure as Code très populaire du marché. Si vous ne l’avez pas sur votre poste, vous pouvez dès à présent l’installer à partir de cette page. Tout le code utilisé est disponible dans un dépôt Github. Il vous suffit donc de le récupérer et de l’exécuter si vous souhaitez réaliser cette démonstration en même temps de votre côté.

Préparation de l’environnement

Avant toute chose, il nous faut bien évidemment un serveur Keycloak à notre disposition. Pour cela, nous allons tout simplement instancier un conteneur Docker (on excusera le mot de passe non sécurisé pour cette démonstration) :

export KEYCLOAK_USER=admin
export KEYCLOAK_PASSWORD=admin

docker run -d --name keycloak -p 8443:8443 -e KEYCLOAK_USER=$KEYCLOAK_USER \
-e KEYCLOAK_PASSWORD=$KEYCLOAK_PASSWORD quay.io/keycloak/keycloak:12.0.4

# Nous allons également configurer localement un domaine customisé pour accéder à notre keycloak
sudo vi /etc/hosts
  ...
  127.0.0.1       keycloak.mycompany.org

Une fois le conteneur déployé, vous pouvez accéder directement à la page d’administration du Keycloak via l’adresse https://keycloak.mycompany.org:8443/auth/admin en renseignant les identifiants définis dans la commande précédente. Si tout se passe bien, vous vous retrouvez connecté en tant qu’administrateur :

Nous allons maintenant préparer Keycloak en créant un realm dédié ainsi que des utilisateurs pour le bon fonctionnement de cette démonstration.
Si l’on regarde dans le dossier setup du dépôt de sources, on retrouve les ressources dans le fichier keycloak.tf (les variables d’entrées sont définies dans le fichier input.tf) :

# Realm Keycloak contenant toute la configuration
resource "keycloak_realm" "realm" {
  realm   = var.realm_name
  enabled = true
}

# Ensemble d'utilisateurs appartenant au realm
resource "keycloak_user" "user_with_initial_password" {
  for_each = { for user in var.users : user.username => user }

  realm_id = keycloak_realm.realm.id
  enabled  = true

  username   = each.value.username
  first_name = each.value.first_name
  last_name  = each.value.last_name
  email      = each.value.email

  # On configure ici le mot de passe d'une manière très simple pour la démonstration
  initial_password {
    value     = "password"
    temporary = false
  }
}

Pour créer ces ressources, lancez les commandes suivantes (faites bien attention à avoir configuré les variables d’environnement KEYCLOAK_USER et KEYCLOAK_PASSWORD car elles sont utilisées par le provider Terraform pour s’authentifier auprès du Keycloak) :

cd setup

# Initialiser la configuration Terraform
terraform init

# Établir un plan des changements effectués si la configuration est appliquée
terraform plan

# Appliquer la configuration Terraform (une confirmation vous sera demandée)
terraform apply

Lorsque l’exécution est terminée, on peut constater que le realm ainsi que les utilisateurs sont créés :

Configuration du SAML

Passons maintenant à la configuration de l’authentification SAML qui permettra à nos utilisateurs externes de se connecter au tenant Azure. Pour mettre cela en place côté Keycloak, il est nécessaire de créer un client SAML. Le code Terraform permettant de le déployer est disponible dans le dossier saml du dépôt Git.

locals {
  azure_tenant_login_url = "https://login.microsoftonline.com/${var.tenant_id}/saml2/"
}

# Client utilisé pour l’authentification SAML auprès d’Azure
resource "keycloak_saml_client" "saml_client" {
  realm_id    = data.keycloak_realm.realm.id
  client_id   =  "urn:federation:MicrosoftOnline"
  name        =  "azure-idp-saml"
  description = "SAML client to federate access on an Azure tenant"

  base_url            = "/auth/realms/${data.keycloak_realm.realm.id}/protocol/saml/clients/${local.saml_client_name}"
  valid_redirect_uris = [local.azure_tenant_login_url]                                                                 

  name_id_format              = "email" 
  assertion_consumer_post_url = local.azure_tenant_login_url

  sign_documents            = true 
  sign_assertions           = true
  signature_algorithm       = "RSA_SHA1" 
  client_signature_required = false                                            

  include_authn_statement = true
  front_channel_logout    = true
}

# Mapper SAML pour inclue l’adresse email de l’utilisateur dans les documents SAML
resource "keycloak_saml_user_attribute_protocol_mapper" "saml_email_mapper" {
  realm_id  = data.keycloak_realm.realm.id
  client_id = keycloak_saml_client.saml_client.id
  name      = "email"

  user_attribute             = "email"
  saml_attribute_name        = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
  saml_attribute_name_format = "Basic"
}

Quelques remarques concernant ce code Terraform :

  • La valeur du client_id est obligatoirement celle-ci sinon l’authentification ne fonctionnera pas. Cela a un impact assez important côté Keycloak car cela signifie qu’il n’est pas possible de créer plusieurs clients SAML avec le même ID. Si vous êtes dans un contexte multi-tenant Azure, il faudra tout configurer dans le même client Keycloak.
  • La propriété valid_redirect_uris contient l’ensemble des endpoints d’authentification SAML. Dans le cadre de multiples tenants Azure, c’est ici qu’il faudra lister l’ensemble des URIs possibles.
  • Le name_id_format doit être dans le format email.
  • La nécessité de signer des documents par le client a été désactivée car Azure ne semble pas prendre en compte cette fonctionnalité.

Il est également possible qu’une problématique supplémentaire se présente à vous. En effet, une des limitations de la mise en place de Direct Federation est qu’il n’est pas possible de configurer un domaine déjà revendiqué par un Azure Active Directory. Dans certains cas spécifiques, vous pouvez donc vous retrouver dans l’impossibilité de spécifier le domaine de vos utilisateurs externes.

Afin de pallier cela, il est possible de créer un script protocol mapper au niveau du client SAML Keycloak :

resource "keycloak_saml_script_protocol_mapper" "saml_script_mapper" {
  realm_id  = data.keycloak_realm.realm.id
  client_id = keycloak_saml_client.saml_client.id
  name      = "email"

  saml_attribute_name        = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
  saml_attribute_name_format = "Basic"

  script = <<-EOT
  var new_domain = '${var.domain_name}';
  var username = user.email.substring(0, user.email.lastIndexOf("@"));
  var new_email = username + '@' + new_domain;

  exports = new_email;
  EOT
}

Ce script protocol mapper va, pour chaque processus d’authentification, remplacer le domaine de l’adresse mail de l’utilisateur Keycloak par le domaine de votre choix configuré dans External Identities, ce qui évite d’avoir à modifier la base d’utilisateurs Keycloak. À noter que si vous utilisez ce mapper, veillez à commenter le précédent pour éviter d’avoir un conflit au moment de leur création.

N.B : l’utilisation de ce script protocol mapper oblige l’utilisateur à mentionner l’adresse mail avec le domaine cible au moment de l’authentification sur le portail Azure.

Le processus de déploiement de ces ressources est similaire au précédent. La seule différence est la nécessité de fournir une variable d’entrée tenant_id correspondant à l’ID de votre tenant Azure :

export TENANT_ID=...

cd saml

terraform init

terraform plan -var tenant_id=$TENANT_ID

terraform apply -var tenant_id=$TENANT_ID

Une fois le code Terraform exécuté, on retrouve alors le client SAML créé et configuré :

Nous avons maintenant toutes les ressources nécessaires côté Keycloak pour authentifier nos utilisateurs. Il ne reste plus qu’à configurer le pendant Azure pour obtenir le processus d’authentification complet.

Configuration d’External Identities

Côté Azure, plusieurs éléments sont nécessaires. Tout d’abord, nous allons configurer le tenant pour pouvoir identifier les utilisateurs provenant de notre Keycloak. Pour cela, rendons-nous dans la tuile de configuration d’External Identities (le moyen d’y parvenir est décrit plus tôt dans la deuxième section de cet article). Ensuite, ajoutons notre Keycloak en tant que provider SAML en cliquant sur “New SAML/WS-Fed IDP”. On obtient alors le formulaire suivant :

Les informations à fournir sont les suivantes :

  • Identity provider protocol : choisir "SAML".
  • Domain name of federating IdP : nom de domaine des utilisateurs externes. Ce champ est très important car c’est lui qui va déterminer si une redirection vers un IDP externe est nécessaire au moment de l’authentification sur le portail. Si vous êtes dans la situation énoncée précédemment où vous devez effectuer une réécriture du domaine des adresses emails, mentionnez le domaine cible.
  • Select a method for populating metadata : ici on a deux choix. Soit on renseigne les informations relatives à l’IDP manuellement, soit on utilise un fichier de metadata qui sera parsé par Azure. Dans le cadre de notre démonstration, on optera pour la deuxième option en récupérant le fichier par Keycloak à l’URL suivant :  https://keycloak.mycompany.org:8443/auth/realms/external-identities/protocol/saml/descriptor. Si vous préférez les renseigner vous-même, il vous suffit de récupérer les informations depuis ce lien.
  • Issuer URI : lien référençant le fournisseur d'identités. Il correspond à l’URL du realm Keycloak (dans notre cas https://keycloak.mycompany.org:8443/auth/realms/external-identities).
  • Passive authentication endpoint : endpoint fournissant l’authentification SAML (dans notre cas https://keycloak.mycompany.org:8443/auth/realms/external-identities/protocol/saml).
  • Certificate : certificat utilisé par Keycloak pour signer les documents SAML. Il est disponible dans le champ X509Certificate du fichier de metadata.
  • Metadata URL : lien vers le fichier de metadata. Ce champ est optionnel. Cependant, il est conseillé de le spécifier puisqu’Azure va automatiquement renouveler le certificat lorsque celui-ci arrive à expiration. S’il n’est pas mentionné, il est nécessaire de renouveler le certificat manuellement.

Ensuite, une fois External Identities configuré, il ne reste plus qu’à créer les utilisateurs invités. Comme mentionné au début de cet article, ceci est nécessaire pour qu’Azure autorise l’authentification d’utilisateurs externes. Toutefois, on peut remarquer qu’il n’est pas nécessaire d’accepter l’invitation pour que l’utilisateur puisse se connecter, cela fonctionne directement.

Contrairement aux parties précédentes, nous allons effectuer leur création manuellement drepuis le portail par souci de simplicité. En effet, au moment de l’écriture de cet article, il n’existe pas de ressource Terraform pour inviter un utilisateur. Des travaux sont en cours pour créer cette ressource dans le provider AzureAD afin de la rendre disponible dans une future version.

À noter qu’il est possible dans l’état actuel de le faire fonctionner via Terraform en utilisant l’API Graph HTTP avec des null_resource et le provisioner local-exec mais l’implémentation reste complexe et non optimale, ce qui est loin d’être idéal et surtout non nécessaire dans le cadre de cet article.

Pour inviter des utilisateurs via le portail Azure, il faut se rendre dans la tuile "Users" de l’Azure Active Directory puis cliquer sur “New Guest user”. Il suffit alors de renseigner l’adresse mail de l’utilisateur externe pour envoyer une invitation. Dans le contexte de notre démonstration nous allons inviter nos deux utilisateurs, aaliceberg@mycompany.org et bbobson@mycompany.org.

Et si nous testions tout ça ?

Une fois les utilisateurs invités, nous disposons de tous les éléments pour autoriser l’authentification d’utilisateurs externes à notre tenant Azure. Nous pouvons dès à présent tester le processus de connexion décrit précédemment :

Et voilà ! Nous sommes bien identifiés sur notre tenant Azure en utilisant le compte aaliceberg@mycompany.org de notre partenaire fictif. Il nous suffit maintenant de gérer l’utilisateur invité correspondant à cet utilisateur comme n’importe quel autre. Vous êtes donc libre de lui donner les droits d’accès aux ressources que vous souhaitez, l’ajouter à un groupe existant, etc.

N.B : la session Azure de l’utilisateur externe est liée à celle sur le fournisseur d'identités externe ce qui signifie que si vous vous déconnectez sur Azure, la session de l’IDP se fermera également, et inversement.

Conclusion

Nous venons de voir que grâce à External Identities, il est maintenant possible de se passer, même partiellement, d’Azure Active Directory pour authentifier des utilisateurs sur le cloud de Microsoft. Cette fonctionnalité va permettre à de nombreuses entreprises possédant déjà un fournisseur d'identités d’accéder à des ressources Azure tout en conservant les mêmes identifiants. En plus de cela, la multitude de choix dans le type de fournisseur d'identités amène une vraie flexibilité et s’adapte à de nombreux cas d’usage.

Même si cela apporte des avantages d’un point de vue fonctionnel, il est également important de prendre connaissance de certaines limitations, notamment dues à la disponibilité récente de la fonctionnalité :

  • Comme mentionné précédemment, il est impossible d’autoriser l’accès à un domaine revendiqué par un Azure Active Directory.
  • Azure ne supporte pour le moment qu’un seul domaine par délégation. Si l’IDP héberge plusieurs domaines d’utilisateurs, il faudra créer autant de délégations dans le tenant.
  • Le fournisseur d'identités doit être accessible via le protocole HTTPS même avec un certificat auto-signé.
  • Il est obligatoire de créer un utilisateur invité dans l’Azure AD pour chaque utilisateur de l’IDP externe.
  • L’intégration avec Keycloak impose l’utilisation d’un unique client SAML, même dans un contexte multi-tenant, en raison de la nécessité d’avoir un clientID bien identifié.

En mettant à disposition cette fonctionnalité, Microsoft ouvre une porte à la venue de nouvelles entreprises en levant un des points bloquants de la gestion des identités sur Azure. External Identities vient alors en complément d’autres composants comme Azure Lighthouse qui favorise la gestion de ressources dans un contexte multi-tenant. La synchronisation d’Azure AD avec le protocole standardisé SCIM peut également être une option si votre fournisseur d'identités le permet.