Managed Service Identity pour machines virtuelles Windows

Managed Service Identity est une réponse élégante au problème de la sécurité du contexte d’exécution de code pour des services comme Virtual Machines, Web App et Azure Functions pour ne citer qu’eux (pas encore disponible pour d’autres ressources providers pendant la phase de preview). Pour les machines virtuelles, c’est intéressant car cela va nous permettre de ne plus stocker de credentials directement dans la machine virtuelle pour exécuter du code. En fait, Managed Service Identity aurait pu trouver sa place dans un billet de 2016 : Cacher les mots de passe dans les scripts PowerShell.

Dans le contexte d’une machine virtuelle Azure, Managed Services Identity propose une API accessible localement uniquement. Un secret local sera présenté à cette API qui va ensuite nous permettre de récupérer un « Access Token » que nous allons pouvoir consommer pour accéder à différentes ressources dans Azure.

A ce jour, Managed Service Identity est en Preview. La fonctionnalité s’active dans le portail, au niveau du blade « Configuration » d’une machine virtuelle. Activer cette fonctionnalité va réaliser plusieurs opérations que nous allons tenter de détailler dans ce billet.

clip_image001

 

La partie la plus visible de Managed Service Identity, c’est la présence d’une VM Extension au sein de notre machine virtuelle. Voilà pour la surface des choses.

clip_image002

 

Pourtant, on ne parle pas encore d’identité. En fait Managed Service Identity a déjà fait le job (pour peu qu’on dispose des privilèges Azure AD). Si on explore un peu notre Azure AD, on constatera la présence d’un nouveau Service Principal au nom de notre machine virtuelle :

Get-AzureRMADServicePrincipal | Where {$_.displayname -eq « <Nom machine virtuelle> »} | Fl -Property *

clip_image003

 

Sujet intéressant, on peut constater que ce Service Principal utilise un certificat auto-signé comme méthode d’authentification. A ce stade, cela me pose un problème. Pour utiliser Managed Service Identity, il faut impérativement avoir le rôle d’administration le plus élevé dans Azure AD. Il n’est pas encore possible d’utiliser un Service Principal existant. Ce Service Principal, on peut l’utiliser pour positionner des permissions. Dans l’illustration ci-dessous, j’associe le rôle « Virtual Machine Contributor » pour permettre à la machine virtuelle de gérer les ressources de type machine virtuelle dans le groupe de ressources « TESTVSIVM ».

clip_image004

 

Maintenant, allons voir ce qui se passe au sein de la machine virtuelle. S’il y a une VM Extension installée, on doit en trouver la trace. En fait, on trouve même mieux que cela avec la configuration de l’API présente au sein de notre machine virtuelle. La VM Extension, c’est une API qui écoute en localhost sur le port 50432 (par défaut). D’un point de vue sécurité, c’est parfait.

clip_image005

 

En creusant un peu dans le même répertoire, on va mettre la main sur le Service Principal à consommer par la VM Extension :

[xml]$xmldocument = Get-Content C:\Packages\Plugins\Microsoft.ManagedIdentity.ManagedIdentityExtensionForWindows\1.0.0.10\RuntimeSettings\20180211172356Z.xml

$xmldocument.RDConfig.SecureIdentity

clip_image006

 

On connait l’identité, reste maintenant, le certificat associé au Service Principal. Logiquement, on le trouve dans le magasin personnel de d’ordinateur : Get-ChildItem Cert:\LocalMachine\My

clip_image007

 

Ne cherchez pas, la clé privée du certificat n’est pas exportable. Pour la suite, il faut prendre soin de disposer d’une version d’Azure PowerShell datant d’au moins Janvier 2018

clip_image008

 

Avant de pouvoir nous authentifier, nous devons demander un jeton d’accès auprès de l’API. C’est ce jeton d’accès que nous allons utiliser pour nous authentifier avec la commande Login-AzureRmAccount en spécifiant :

  • L’utilisation d’un AccessToken
  • L’identité que nous utilisons (‘MSI@50342’ par défaut

$response = Invoke-WebRequest -Uri http://localhost:50342/oauth2/token -Method GET -Body @{resource= »https://management.azure.com/ »} -Headers @{Metadata= »true »}

$content =$response.Content | ConvertFrom-Json

$access_token = $content.access_token

Login-AzureRmAccount -AccessToken $access_token -AccountId « MSI@50342 »

Get-AzureRmResourceGroup

Get-AzureRmVM

clip_image009

 

L’authentification Azure est bien fonctionnelle et nous sommes bien capables d’accéder aux ressources auxquelles le Service Principal a été accrédité.

Bonus

Allons plus loin avec un KeyVault, en accordant au Service Principal la possibilité d’accéder à des secrets (Get et List pour les permissions).

clip_image010

 

Pour vérifier, voilà le secret à révéler dans le coffre-fort numérique.

clip_image011

 

$response = Invoke-WebRequest -Uri http://localhost:50342/oauth2/token -Method GET -Body @{resource= »https://vault.azure.net »} -Headers @{Metadata= »true »}

$content = $response.Content | ConvertFrom-Json

$KeyVaultToken = $content.access_token

$return = (Invoke-WebRequest -Uri https://testmyvault991v1.vault.azure.net//secrets/JoinDomainPassword?api-version=2016-10-01 -Method GET -Headers @{Authorization= »Bearer $KeyVaultToken »}).content

$return

($return | convertfrom-json).value

clip_image012

 

Conclusion

Au moment de l’écriture de ce billet, la fonctionnalité Managed Service Identity est encore en preview et ne concerne pas encore tous les services. La seule contrainte identifiée à ce jour, c’est l’impossibilité de spécifier le Service Principal à utiliser. Sinon, c’est un excellent moyen pour ne plus code ses credentials dans le code de ses machines virtuelles.

 

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Sécuriser son exposition RDP Internet Azure

Voilà un problème que je rencontre souvent chez mes clients, les Vm Azure accessible librement sur Internet. Il faut comprendre une chose, les adresses IP Azure sont connues (référence fichier XML mis à jour chaque semaine : https://www.microsoft.com/en-us/download/details.aspx?id=41653), donc scanner les ports RDP, c’est tout ce qu’il y a de plus simple.

Généralement, on en trouve la trace dans Azure Log Analytics. La première piste, c’est la présence de nombreux events 4625 avec la requête suivante :

SecurityEvent | Where (EventID == 4625) | Summarize Count() By TargetAccount

Nous en avons un exemple ci-dessous. A une période donnée, une machine virtuelle a été exposée directement sur Internet.

clip_image001

 

De ce qu’on constate dans l’illustration ci-dessous, il y a eu beaucoup de tentatives infructueuses pour le seul compte Administrator. Presque 10 000 tentatives en moins d’une semaine. Voilà le premier effet kiss-cool d’une machine virtuelle librement exposée sur Internet. Le second et il est moins drôle, c’est qu’on constate aussi d’autres tentatives en ciblant des comptes plus génériques. Avec un compte comme Helpdesk, un attaquant aurait certainement moins de privilège que « Administrator » mais il a plus de chance que ce compte soit partagé par un plus grand nombre d’utilisateurs qui d’un commun accord auront choisi un mot de passe beaucoup moins stricte, pire ne pas imposer une politique de renouvellement.

Pas encore convaincu ? OK, disons maintenant que vous avez mis en œuvre l’Azure Security Center en plus de Log Analytics pour cette machine virtuelle, comment considère t’il la chose avec la requête suivante : SecurityDetection | Where (AlertTitle == « Failed Brute Force Attack »)

clip_image002

 

Du point de vue de Security Center, cette accumulation d’event 4625 n’est rien d’autre qu’une attaque de type brute force RDP. Heureusement pour le cas illustré ci-dessus, ce n’est qu’une attaque qui a échouée, … Si elle a échoué, n’y aurait-il pas des attaques qui ont-elles réussies ? Posons la question: SecurityDetection| where ( AlertTitle == « Successful RDP brute force attack » )

clip_image003

 

Houston, we have a fucking problem. C’est le cas de le dire. Cependant, ce qu’il faut comprendre avec cet évènement, c’est qu’au milieu du flot de tentatives d’authentifications infructueuses, il y a aussi les accès légitimes. Le problème, c’est comment ne pas considérer la chose suspecte, si un compte est compromis, l’accès à la machine virtuelle devient possible.

clip_image004

 

Problème, comment identifier un compte qui aurait une activité suspicieuse ? Dès lors qu’un attaquant dispose d’un accès dans un système d’information, la première tâche après avoir validé la persistance de l’accès, c’est de passer en mode de recherche de cibles à haut potentiel. Ici encore, l’Azure Security Center est capable d’identifier des comportements douteux. Imaginons qu’après de multiples tentatives, un attaquant ait réussi par un moyen ou un autre à découvrir le mot de passe de mon compte utilisateur.

SecurityDetection | Where (AlertTittle == « Suspicious Process Execution Activity Detected »)

clip_image005

 

Que je me logge sur un serveur, normal. Que j’utilise ce type de commande aussi vieilles que Windows for Workgroup 3.11, c’est douteux (PowerShell & VBScript fan Boy). Voilà de bonnes raisons pour ne pas exposer ses machines virtuelles Windows directement sur Internet. Sans Log Analytics couplé à Security Center, difficile de savoir qu’on est dans ce type de situation. Avec l’arrivée cette année de la GDPR, voilà comment je justifie l’investissement dans ces deux produits :

  • Voir vos données compromises est un risque pour l’entreprise
  • Chaque incident de sécurité avéré coutera jusqu’à 4% du CA de l’entreprise

Azure Security Center et Log Analytics ne sont pas des solutions magiques (compliance GDPR) mais au plus tôt on est capable d’identifier une situation à risque, au plus tôt l’équipe sécurité est capable de réagir. Azure Security Center est capable de vous avertir que vous avez une machine virtuelle Windows / Linux qui est exposée en direct sur Internet avec RDP / SSH en Open Bar. Après, il vous faut un peu de process (s’il n’y a personne pour lire les recommandations d’Azure Security Center, je ne peux rien pour vous)

Alternatives

Exposer une machine virtuelle Windows ou Linux sur Internet n’est clairement pas une bonne idée. Si vraiment, vous en avez besoin, voilà quelques idées pour remédier au problème.

  • Changer le port RDP
  • Azure Load Balancer
  • Tunnel IPSEC
  • Un peu de bricolage
  • Just in time Access (Preview)
  • Bastion (RDS)

 

Changer le port RDP

Autant le dire tout de suite, c’est une solution « Low-cost ». Elle va effectivement réduire le volume d’attaque. Le problème, c’est qu’on a tendance à utiliser des noms « parlants » pour désigner nos machines virtuelles. Donc si on a une réponse pour l’host bastion ou dmz, en scannant les ports pour l’IP, l’attaquant trouvera assez facilement le nouveau port RDP d’exposition. Si le sujet vous intéresse, je vous conseille la lecture du billet suivant : Change the default RDP port (3389) on a Azure Windows ARM VM to a high range port. Après, faudra aussi adapter votre règle au niveau des Network Security Groups.

 

Azure Load Balancer

Disons que c’est un peu moins « Low cost » mais pas top quand même. Avec cette solution on masque plusieurs expositions RDP (ou même SSH) derrière un Azure Load Balancer. Pour chaque exposition, nous devons créer une règle de NAT comme illustré ci-dessous :

Le premier problème de RDP/SSH, c’est que le port est connu. La première approche est donc de changer ce port. C’est ce que nous propose Azure Load Balancer. Avantage, une seule adresse IP publique permet d’exposer un grand nombre de machines virtuelles, aussi bien RDP que SSL.

clip_image006

 

De mon point de vue, on ne fait que masquer le problème.

 

Tunnel IPSEC

La on commence à traiter le problème. On impose l’établissement d’un tunnel IPSEC entre le client RDP et la machine virtuelle dans Azure. Le bon établissement du tunnel IPSEC nous garantit que le client à l’autre bout est bien celui qu’il prétend puis qu’il dispose d’un mécanisme d’authentification. De mon point de vue, on commence à traiter le problème. Pourtant cette solution a aussi sa faiblesse. Une implémentation bâclée d’IPSEC utiliserait une clé pré-partagée. Or si tous les utilisateurs partagent la même clé, cela devient difficile d’en isoler un pour le bloquer. Cela implique donc une clé d’authentification propre à chaque utilisateur (certificat client par exemple).

 

Un peu de bricolage

C’est une trouvaille un peu par hasard : Good news everyone! We are under brute force attack!. Si votre machine virtuelle doit nécessairement être exposée sur Internet, il faut au moins pouvoir se défendre en bloquant les adresses IP. Sa solution est intéressante et propose même le reporting dans Log Analytics et la visualisation dans PowerBI. Bref, je like.

clip_image007

 

Just in Time Access (Preview)

Si le besoin d’exposer le RDP est avéré, il n’est peut-être nécessaire que l’exposition soit permanente. Une approche serait de procéder à l’ouverture uniquement lorsque le besoin est nécessaire. Voilà une approche intéressante. C’est la solution proposée dans Azure Security Center avec l’option Just-in time Access.

Attention, cela impliquera un pricing standard et non free (donc un coût par machine virtuelle). Pour chaque machine virtuelle, nous pouvons configurer la liste des ports qui seront ouverts. Pour une machine virtuelle Windows, c’est donc du RDP en TCP et UDP (oui oui, il n’y a pas d’erreur) qui sera mis en œuvre « à la demande ». Ce qui est intéressant, c’est que l’ouverture demandée ne sera réalisée que pour l’adresse IP « source » et pendant une durée de vie limitée.

clip_image008

 

Une fois la configuration en place, on peut demander notre ouverture des flux avec le bouton « Request Access ».

clip_image009

 

Dans le cas ci-dessous je demande l’ouverture du flux RDP pour mon adresse IP pour une durée de vie d’une heure seulement.

clip_image010

 

De retour, nous pouvons constater qu’une requête d’ouverture de flux est bien en cours pour un utilisateur donné.

clip_image011

La fonctionnalité semble plus qu’intéressante, reste à voir comment serait proposé des mécanismes comme l’approbation des requêtes par des administrateurs. Au moment d’écrire ce billet, la fonctionnalité Just in time Access est encore en Preview.

 

Bastion (RDS)

Cette approche implique l’utilisation d’un point d’accès unique qui sera utilisé comme référence IP pour les machines exposées. Ce qui est bien, c’est que Windows embarque cette technologie depuis Windows 2008 : RDS Gateway. Donc on a juste besoin de licences CAL RDS. La on commence réellement à adresser le risque :

A ce jour, c’est l’approche la plus complète. Encore pour cela qu’on s’attarde un peu sur le hardening de la RDS Gateway. La mise en place d’un équipement d’analyse de flux (IDS) est plus que recommandée.

 

Conclusion

Voilà, vous n’avez plus d’excuse pour continuer à laisser vos RDP exposés librement sur Internet. Pour finir, faites attention à ne plus provisionner inutilement d’adresse IP publique pour vos machines virtuelles déployées via le portail. Juste une case à cocher.

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Enfin les jobs dans le module Azure Powershell

Voilà un truc que j’attendais depuis longtemps. Même si la recommandation est d’utiliser les templates ARM, on a tous une bibliothèque de scripts PowerShell qui créé des machines virtuelles aux petits oignons (charte de nommage, tags, activation de la sauvegarde, supervision avec un beau DSC ou Custom script pour finir la personnalisation de la machines virtuelle). Un truc propre quoi.

Pourtant on a tous pestés sur les commandes les plus connues du module AzureRm.Compute :

  • New-AzurermVM
  • Update-AzurermVM
  • Start-AzurermVM
  • Stop-AzurermVM

 

Pour mieux comprendre une illustration toute simple

$startdate = Get-Date

Write-host $startdate -ForeGroundColor Green -BackgroundColor Black

Stop-azurermvm -Name $vm.name -ResourceGroupName $vm.ResourceGroupName -Force

$enddate = Get-Date

Write-Host $enddate -ForeGroundColor Green -BackgroundColor Black

Write-Host (New-TimeSpan -Start $startdate -End $enddate).Totalseconds -ForeGroundColor Red

clip_image001

 

Le problème, c’est de devoir attendre plus de deux minutes pour que l’API Azure nous rende la main. Multipliez-le par le nombre de machines virtuelles à déployer en même temps en une seule journée, à la fin, ça commence à faire long. Par le passé, j’avais tenté les jobs PowerShell mais, ces commandes PowerShell n’étaient pas éligibles. C’était vrai jusqu’à la version 5.1.1 du module PowerShell pour Azure introduite début décembre 2017.

Depuis la version 5.1.1, les commandes PowerShell citées en début de ce billet introduisent l’argument AsJob

clip_image002

 

Reprenons le même exemple en ajoutant juste « -AsJob »

clip_image003

 

Tout de suite plus intéressant d’un point de vue performance. Si c’est un job, lors on doit pouvoir le suivre avec la commande Get-Job :

clip_image004

 

Ce qui est intéressant, c’est que même si la commande échoue, on peut quand même récupérer le pourquoi en creusant en peu dans les propriétés du job.

clip_image005

 

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Azure Scheduled Maintenance

Azure Scheduled Maintenance est une nouvelle approche de la gestion de la maintenance des infrastructures Azure. Celle-ci a été introduite progressivement mais ce n’est qu’en cette fin d’année 2017 que l’on peut constater l’arrivée de cette fonctionnalité dans les régions North Europe & West Europe.

Pour rappel, la fonctionnalité doit permettre aux clients Azure :

  • D’être notifié des périodes de maintenances pour le service Azure Virtual machines.
  • De pouvoir influer sur les périodes de maintenance proposées en les anticipant

 

Dans le portail Azure, cela se présente comme illustré ci-dessous avec la mention « Scheduled maintenance will start soon ».

clip_image002

 

Si on regarde plus en détail, nous n’avons que peu d’information. C’est normal car pour cette machine virtuelle, Azure ne nous annonce que la période de maintenance planifiée, pas encore la période de « pré-maintenance ».

clip_image004

 

Donc à ce stade, cliquer sur le bouton Redeploy ne permettra pas d’anticiper la maintenance. Par contre, quand on regarde une machine virtuelle dont la planification de maintenance est un peu plus avancée, l’interface est un peu différente :

clip_image006

 

Nous sommes informés que la future possibilité d’anticiper la phase de maintenance. C’est important car une fois entrée en phase de Scheduled Maintenance, le processus est 100% automatisé, nous ne pourrons plus intervenir.

clip_image008

 

Lorsque la fenêtre de pré-maintenance sera ouverte, nous recevons un mail comme celui-ci, tout du moins, un par souscription Azure dans laquelle nous avons des machines virtuelles.

clip_image009

 

A noter que la même information est disponible maintenant dans le Azure Service Health dans la rubrique « Planned Maintenance ».

clip_image011

 

Lorsqu’on regarde l’onglet « Affected ressources », on a une vue synthétique. Dans l’illustration ci-dessous, j’ai deux machines virtuelles pour lesquelles je peux dès maintenant anticiper la période de maintenance proposée par Azure

clip_image013

 

Maintenant qu’on est dans la fenêtre de pré-maintenance, on peut lancer l’opération avec le bouton « Start Maintenance ».

clip_image015

 

L’opération va consister tout simplement en un « Redeploy ». La machine virtuelle va donc s’arrêter, quitter l’hôte Hyper-V et être redéployé sur un autre hôte Hyper-V qui lui a déjà été mis à niveau par Microsoft.

clip_image016

 

Avantage d’anticiper la maintenance, c’est nous qui contrôlons la durée de l’indisponibilité. Ce n’est plus le cas au terme de la période de pré-maintenance.

Pour avoir une vue d’ensemble, le plus simple reste de personnaliser la vue « Virtual machines » pour inclure les colonnes suivantes :

  • Maintenance – Auto-Scheduled Window
  • Maintenance – Proactive Windows

clip_image018

 

Après, on peut aussi jouer en PowerShell :

get-azurermvm -status | select Name, MaintenanceRedeployStatus -ExpandProperty MaintenanceRedeployStatus | select Name, IsCustomerInitiatedMaintenanceAllowed, PreMaintenanceWindowStartTime, PreMaintenanceWindowEndTime, MaintenanceWindowStartTime, MaintenanceWindowEndTime | Out-GridView

clip_image020

 

Les informations sont identiques. Ce qui est bien, c’est qu’on n’est pas obligé d’interroger chaque machine virtuelle pour collecter l’information.

clip_image022

Bonus

Le Bonus, c’est d’être informé de ces opérations dès que possible. Comme dans Azure, il y a une fonctionnalité pour tout, en creusant dans Azure Service Health, vous découvrirez la possibilité de créer une alerte sur ce sujet. La seule critique, c’est que l’alerte est liée à un groupe de ressources. Il faudra donc autant d’alertes que de groupes de ressources contenant des machines virtuelles.

clip_image024

 

Pour conclure, un peu de lecture sur le sujet :

 

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Azure API Management 5/5 – PowerShell Time

C’est la dernière ligne droite et aussi le temps du PowerShell. Pour Parler PowerShell, tout comme pour Azure Function, cela reposera sur un Invoke-WebRequest. C’est donc presque pareil, à quelques exceptions. La première chose qui change, c’est l’URL. Pour rappel, voilà l’URL de notre Azure Function exposée via notre instance du service Azure API Management.

clip_image001

 

La seconde chose qui change, c’est la clé d’authentification. Nous ne passons plus la clé d’authentification de notre Azure Function (c’est géré au niveau des policies d’Azure API Management) mais une des deux clés dont nous disposons dans la souscription au produit qui présente notre Azure Function. En tant que consommateur, nous pouvons retrouver cette information dans le portail développeur mis à disposition par l’instance du service Azure API Management. Cette clé, nous allons la référencer sous le nom « Ocp-Apim-Subscription-Key »

clip_image003

 

Nous avons toutes les informations, ne nous reste plus qu’à construire notre requête.

$url = « https://tpapimanagement.azure-api.net/AzuretableValetKeyAPI/api/AzuretableValetKeyAPI »

Invoke-RestMethod -Uri $Url -Method POST -ContentType « application/json » -Headers @{« Ocp-Apim-Subscription-Key »= »2fab81140f42490683XXXXXXXXa26ac0 »}

clip_image005

 

Nous y sommes. Nous avons réussi à consommer notre Azure Function exposée par Azure API Management.

 

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Azure API Management 4/5 – C’est l’heure de consommer

Nous avons une API exposée avec des nouvelles fonctionnalités :

  • Point d’accès unique pour toutes mes futures API
  • Une méthode d’authentification unique pour toutes mes API
  • Une journalisation centralisée et non plus gérée au niveau de chaque API
  • Une politique de limitation d’usage

 

La prochaine étape, c’est donc nécessairement de consommer. Azure API Management est capable de s’interfacer avec bon nombre de systèmes d’authentification. Dans le contexte de cette série de billets, nous allons utiliser le fournisseur d’identité par défaut. Chaque utilisateur doit disposer d’un compte et d’un mot de passe pour accéder au service. On peut soit créer des utilisateurs ou les inviter. L’avantage de l’invitation, c’est que c’est l’invité qui sera chargé de configurer son mot de passe. J’ai donc retenu de lui envoyer une invitation.

clip_image002

 

Le client de ma licorne reçoit un mail qui l’invite à se connecter au portail. A noter que ces éléments de communication (template de mails) sont configurables dans Azure API Management.

clip_image004

 

Point d’attention, la politique de mot de passe d’Azure API Management est assez pointue. N’essayez pas d’utiliser des séquences continues dans vos mots de passe.

clip_image006

 

Une fois authentifié, on arrive sur le portail développeurs de notre instance du service Azure API Management. Dans la rubrique « Products », on constate qu’il nous est proposé la souscription d’un service. La notion de souscription à un produit est importante car pour chaque souscription de produit, une paire de clés d’accès est générée.

clip_image008

 

Au sens Azure API Management, un produit permet aux futurs clients de ma licorne de souscrire à nos API. Dans l’exemple ci-dessous, Azure API Management va imposer une Policy qui limite le nombre d’appels par minutes / semaines. Dans mon Business plan de la mort qui tue, j’ai un mode gratuit mais faut pas non plus qu’il me coute les yeux de la tête. Pour l’instant, il n’y a qu’une seule API.

clip_image009

 

Il est possible de personnaliser le nom de chaque souscription réalisée. C’est intéressant si on souscrit plusieurs fois au même produit.

clip_image011

 

C’est souscrit, pour accéder à mon API, je peux constater que j’ai deux clés.

clip_image013

 

En tant que client consommateur de l’API, je peux aussi référencer ma propre application qui va changer la face du monde.

clip_image015

 

Je peux la soumettre à publication, reste à voir si l’administrateur de l’Azure API Management service est prêt à m’aider à démarrer et qui sait devenir demain le nouveau Facebook 3.0.

clip_image017

 

Nous approchons de la fin de cette série de billets. Ne nous reste plus qu’à nous placer en tant que client pour consommer notre API. Ce sera le sujet du dernier billet.

 

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Azure Reserved Instances – La fonctionnalité la plus simple à expliquer

Généralement, les lecteurs de mon blog s’attendent à ce que je disserte sur les fonctionnalités les plus technique d’Azure. La, on va faire juste expliquer la fonctionnalité la plus simple d’Azure. Pour la démontrer, même pas besoin du portail Azure, la calculatrice Azure suffira. L’idée de base, c’est plus on s’engage dans le temps pour consommer plus on obtient de remise. Pour illustrer mon propos, voilà le prix du service Azure compute pour la SKU D1 déployée en standard avec l’OS Windows, le tout hébergé dans la région West Europe. C’est notre prix de référence pour du « Pay as you go ».

clip_image001

Maintenant, si on s’engage à ce que notre machine virtuelle soit provisionnée dans Azure pendant un an, le prix baisse de 33%. C’est bien mais pas top.

clip_image002

Pour être top, il faut s’engager sur trois ans. La, le prix baisse de 44%.

clip_image003

Voilà, c’est tout ce qu’il y à savoir sur Azure Reserved Instance, enfin presque. Il y a quand même quelques limitations. A ce jour, cela ne concerne que les souscriptions de type Pay as you go ou Enterprise Agreement, pas encore les CSP.

Pour plus d’informations, lisez la FAQ.

 

Désolé, j’ai pas plus simple. Même le DAF il va liker!

 

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Azure API Management 3/5 – Exposition de notre première API

A partir de maintenant, tout va se passer dans Azure API Management. Notre Azure Function est prête à être référencée comme API. Dans l’interface de gestion du service, en cliquant sur « API », on arrive à l’interface ci-dessous :

clip_image001

Azure API Management prend en charge plusieurs langages de description pour nos API. Par chance, l’intégration avec Azure Function est nativement supportée ou presque. L’interface nous propose bien de sélectionner notre Function App (ce qui porte notre fonction) mais pas la fonction en elle-même. C’est pour cela que je spécifie le paramètre API Url suffixe correspondant le nom de la fonction.

clip_image002

Autre sujet important, l’accès authentifié à notre Azure Function. Pour rappel, chaque fonction que nous avons développée dispose de sa propre URL et clé d’accès :

clip_image003

Si je ne fais rien, aucune authentification sera présentée à mon Azure Function. Il faut donc pouvoir intégrer ce code d’authentification dans l’appel depuis Azure API Management. Vu que c’est un secret, on va commencer par le stocker dans une Named Value. Au moment de l’écriture de cette série de billets, il n’est pas encore possible de stocker ses secrets dans un Azure KeyVault. A ce jour, c’est un feedback qui a été remonté à Microsoft : Integration with Azure KeyVault. En attendant KeyVault, nous allons utiliser les Named Values.

clip_image004

Azure API Management permet d’injecter des paramètres additionnels dans le Header. C’est une des nombreuses fonctionnalités offertes par les Azure Policies d’Azure API Management. Nous allons travailler au niveau « Inbound Processing »

clip_image005

Notre opération consistera à ajouter un nouveau paramètre à notre requête HTTP. Pour éditer ma policy, je suis passé en mode « Code-View » pour intégrer une règle de transformation nommée « Set query request parameter ». De cette manière, on va injecter le paramètre « Code » avec la valeur contenue dans la Named Value {{AzureFunctionAPICode}}. Reste à ne pas oublier de cliquer sur le bouton Save.

clip_image006

De retour dans la view « From View », c’est plus simple à comprendre.

clip_image007

Attention, l’utilisation du Named Parameters, dans la vue form view ne conservera pas le named parameters mais va juste remplacer le contenu. D’ou le passage en mode « Form View ».

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Azure API Management 2/5 – Préparer l’exposition de notre Azure Function

Notre service Azure API Management est maintenant posé. Nous allons y revenir. Pour commencer, nous allons rendre notre Azure Function consommable par mon service API Management. Il faut un peu de préparation. A ce stade, il manque une description contenant :

  • Ce que produit notre API
  • Les paramètres qu’elle attend en entrée
  • Les paramètres qu’elle retourne
  • La ou ses différentes versions

Première étape, on va commencer par limiter ce que va accepter notre Azure Function en termes de verbes. Au niveau du nœud « Integrate » de notre fonction. Nous allons affiner la listes méthodes HTTP pour ne retenir que POST sans oublier de sauvegarder notre modification.

clip_image001

 

Prochaine étape, documenter notre API. Dans le contexte Azure Function, c’est le Framework Swagger qui a été retenu par Microsoft pour l’intégration avec Azure API management. Le Framework Swagger utiliser les spécifications OpenAPI. Allons configurer la définition de notre API en cliquant sur « API Definition ».

clip_image002

 

Azure Function peut être exposé sous forme d’API de deux manières :

  • Function (Preview pour l’intégration avec Azure API Management)
  • External URL (Utilisation d’un service tierce)

 

Azure API Management étant un service interne Azure, nous allons cliquer sur « Function (Preview) ».

clip_image003

 

Remarque importante, cela ne change strictement rien sur la méthode d’authentification de notre Azure Function. Nous pouvons toujours la solliciter ne direct dès lors que nous disposons de toutes les informations. C’est un sujet sur lequel nous allons revenir dans un prochain billet de la série.

clip_image004

 

Pour décrire notre API, nous allons utiliser les spécifications OpenAPI. L’intégration avec Azure est bien faite puisqu’on nous propose de créer un squelette JSON en cliquant sur le bouton « Generate API Definition template ».

clip_image005

 

OpenAPI va nous permettre de produire une description qui sera consommée par Azure API Management. Heureusement que mon API est simple. Globalement, j’ai indiqué :

  • Que mon API ne supportera que le HTTPS pas le HTTP
  • Que mon API ne supportait que la méthode POST via une URL bien précise
  • Qu’elle consomme ses paramètres au format JSON (même s’il n’y en a pas dans mon exemple)
  • Quelle produira du contenu au format JSON avec un seul message documenté

clip_image006

 

N’oubliez pas d’appuyer sur « Save ».

Avant d’aller plus loin dans l’intégration, nous allons déjà valider que cela fonctionne. Pour cela nous avons besoin d’une clé d’accès pour notre Azure Function. Dans le nœud « Manage » de notre Azure Function, nous allons récupérer une clé d’authentification en cliquant sur le bouton « Copy ».

clip_image007

 

De retour dans la configuration de la définition de notre API, dans la zone droite de l’interface, nous avons la possibilité de valider l’accès à notre future API. Cliquons sur « Change Authentication ».

clip_image008

 

Dans l’interface ci-dessous, nous allons renseigner la clé d’accès précédemment obtenus puis cliquer sur le bouton « Authenticate ».

clip_image009

 

Un peu plus bas dans l’interface, on constate la présence de la description de la seule méthode supportée par notre API : « Post ». En cliquant sur « Try this operation », nous allons réaliser un appel à notre future API avec la clé d’authentification.

clip_image010

 

Côté Request, mon API étant assez simpliste (aucun paramètre en entrée), ayant limité les choix d’utilisation à HTTPS seulement et imposé le JSON pour les paramètres, il ne nous reste qu’à appuyer sur le bouton « Send Request ».

clip_image011

 

Si tout se passe bien, nous devrions avoir le résultat retourné par notre Azure Function.

clip_image012

 

Côté Azure Function, les prérequis sont en place. Prochaine étape, l’exposition de notre première API.

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Azure API Management 1/5 – Introduction

A forcer de créer des API, je vais finir par créer ma licorne. Problème, avec la GDPR qui arrive, si je commence à annoncer à mes futurs investisseurs et clients que je vais développer ma stack sécurité de bout en bout, autant dire que je vais la tuer ma licorne dans l’œuf.

clip_image002

Si développer ma stack sécurité n’est pas une option viable, autant en choisir une qui offre la possibilité de : S’intégrer avec les principaux fournisseurs du marché (Facebook, LinkedIn, Microsoft, Google, …).

  • Proposer un point d’accès unique pour toutes mes API
  • Permettre la mise en place de politiques de contrôle de l’usage de mes API
  • Permettre de gérer la souscription à mes API

Dans la liste des services Azure à destination des développeurs, on trouve Azure API Management Service. Ça fait tout cela et même plus. Dans cette série de billet, nous allons reprendre mon Azure Function proposée dans le billet Azure Function avec Managed Service Identity. Pour rappel voilà son contenu : Une Azure Function qui permet d’extraire un secret de mon Key Vault avec une identité Azure AD utilisant Managed Service Identity.

clip_image004

 

Dans la situation actuelle, tant qu’on dispose de la clé d’authentification associées à la fonction, on peut la solliciter autant qu’on veut et donc gérer une surfacturation. C’est une des fonction d’Azure API Management de limiter la consommation de notre API a un certain nombre d’appel par minutes.

Nous allons commencer par mettre en œuvre une instance du service API Management Service dans un nouveau groupe de ressources. Le service API Management est disponible en trois éditions :

  • Développeur
  • Standard
  • Premium

Pour le détail, je vous renvoie vers la page prévue à cet effet : API Management pricing . J’ai fait le choix de la version développeurs. Au passage, je me désigne comme l’administrateur de ce service.

clip_image005

 

Le provisionning du service API Management est plutôt lent (genre 40 minutes). Azure API Management supporte plusieurs fournisseurs d’identité. On peut :

  • Gérer les utilisateurs accédant à nos API nous-même car il intègre son propre module de gestion des utilisateurs
  • Gérer les utilisateurs en utilisant un Tenant Azure AD, ce qui permet de séparer les comptes des autres ressources Azure, ce qui est déjà bien mieux (mais on gère toujours les utilisateurs)
  • Gérer des utilisateurs issus d’un Tenant Azure AD B2C ce qui est l’option la plus intéressante puisque chaque utilisateur vient avec son identité, nous n’avons plus à la gérer

Remarque : Attention avec Azure AD B2C, au moment de l’écriture de ce billet, il n’est pas encore disponible en CSP. Pour cette raison, nous allons travailler avec le fournisseur d’authentification standard.

Ce qu’il faut comprendre, c’est que ces identités vont permettre à nos consommateurs de se connecter à un portail pour y souscrire l’accès aux API de notre future licorne. Le consommateur ne va donc pas s’authentifier directement avec un compte / mot de passe mais une clé d’accès générée par Azure API Management.

Une fois le provisioning terminé, l’administrateur est notifié par mail de la création du service. Dans le portail Azure, cela ressemble à l’illustration ci-dessous :

clip_image007

 

Première information, le service API Management est accessible selon deux URL :

  • L’URL de la Gateway pour exposer nos API
  • L’URL que nous mettons à disposition de nos partenaires pour gérer la souscription à nos API

clip_image008

 

Avant de poursuivre, on va commencer par configurer la journalisation pour tout envoyer dans Log Analytics.

clip_image009

 

Un peu plus haut, j’avais indiqué que notre service API Management était accessible selon deux URL. En fait, il y en a un peu plus. Bonus, on peut les personnaliser (notion de Custom Domain) ainsi que d’utiliser nos propres certificats.

clip_image011

 

Notre service API Management peut lui-même exposer ses propres API pour le gérer à distance. Par défaut, ce n’est pas activé.

clip_image013

 

Côté Identité, il y a des multiples fournisseurs. Nous allons conserver le fournisseur par défaut. Le service API Management va alors lui-même prendre en charge l’authentification des utilisateurs. Charge à nous administrateur de créer ou inviter des utilisateurs. Nous on va imposer notre marque avec un message de bienvenu sur les services mis à disposition par notre nouvelle licorne.

clip_image015

 

Voilà pour les fondations. Pour la suite, il faudra attendre la publication des prochains billets :

 

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)