Authentifiez vos Azure Function avec Azure AD

De retour sur Azure Function. Après avoir exploré les possibilité d’intégration entre Azure Function et Azure API Management, revenons dans Azure Function avec un aspect sécurité. Comment sécuriser l’accès à vos API? Techniquement, Azure API Management nous propose ce type de service avec la capacité de supporter de multiples fournisseurs, cependant lorsqu’on a qu’une seule Azure Function à exposer, ça fait un peu lourd et cher. On va donc voir ce que nous propose App Service out of the box que nous allons aborder en plusieurs étapes :

  • Mise en place des fondations
  • Prise en charge de l’authentification Azure AD
  • Bonus : Postman

 

Mise en place des fondations

La première chose dont on va avoir besoin, c’est effectivement d’une instance du service Azure Function. Jusque-là, rien de bien compliqué.

clip_image001

De là, il ne nous reste plus qu’à mettre en place notre Azure Function à sécuriser. Celle-ci sera configurée sans authentification. Elle sera donc librement accessible à toute personne connaissant l’URL. La fonction d’authentification sera déportée dans Azure AD plus tard.

clip_image002

 

Pour finir notre mise en place, on a juste besoin d’une petite dose de code, de PowerShell en fait. Ce qu’il faut comprendre, c’est que Web App sui sert de socle à Azure Function va faire la majorité du travail pour nous. Tout ce que nous attendons, c’est l’identité de l’utilisateur connecté que nous allons retrouver dans les Server Variables dans notre session. Ce que va faire Azure Web App, c’est peupler des variables pour nous dont la variable « HTTP_X_MS_CLIENT_PRINCIPAL_NAME ». Attention, nous allons n’avoir que l’identité de l’appelant à notre Azure Function pas le claims obtenu (un peu plus de travail). En PowerShell, c’est aussi simple que cela :

$requestBody = Get-Content $req -Raw | ConvertFrom-Json

$result = Get-Variable -name REQ_HEADERS_X-MS-CLIENT-PRINCIPAL-NAME -ErrorAction SilentlyContinue

if ($result.name -ne $null)

{

Out-File -Encoding Ascii -FilePath $res -inputObject « Hello $($result.value) »

}

else

{

Out-File -Encoding Ascii -FilePath $res -inputObject « Unauthenticated. »

}

 

On peut tester immédiatement, l’authentification Azure AD n’étant pas encore en place, la variable n’existe pas pour l’instant. D’où le retour « Unauthentified ».

clip_image003

 

Prise en charge de l’authentification Azure AD

C’est maintenant que les choses se compliquent. On a bien une fonctionnalité « Authentication / Authorization ». Activer la fonctionnalité va impacter toutes les Azure Functions qui sont portées par l’instance de notre service.

clip_image004

 

Activer la fonctionnalité, c’est ce qu’il y a de plus simple. On va donc forcer l’authentification pour toutes les connexions et indiquer que nous allons utiliser le fournisseur Azure Active Directory.

clip_image005

 

Pour les besoins de la démonstration, on sa se contenter de la configuration Express. Maintenant challenge : avez-vous le privilège Administrateur général au niveau AD ? Si oui, alors on peut créer immédiatement l’application (et le service principal associé). Dans le cas contraire, il faudra demander à celui qui détient les droits de gérer cela pour vous pour ensuite sélectionner l’application Azure AD nouvellement déclarée. Dans notre contexte, je dispose des privilèges, on continue.

clip_image006

 

Ne surtout pas oublier de sauvegarder la configuration.

clip_image007

 

Derrière, on sait tout de suite que cela fonctionne, il suffit de tenter de réexécuter notre Azure Function. Il est clairement indiqué que l’authentification bloque l’utilisation du débugger.

clip_image008

 

Revenons sur la configuration de cette application déclarée dans Azure AD. Nous allons accorder à notre application des permissions déléguées pour autoriser l’authentification des utilisateurs et ne surtout pas oublier de sauvegarder la configuration.

clip_image009

 

Le message d’avertissement nous indique que dans la configuration actuelle aucun utilisateur de Tenant Azure Active Directory n’a accès à cette application. On a deux choix :

  • Une assignation manuelle pour chaque utilisateur ou collective (bouton Grant permissions)
  • Une assignation selon appartenance de groupe (Pas disponible avec une SKU Free d’Azure AD)

 

On va donc procéder à une activation massive pour tous les utilisateurs de notre Tenant Azure AD, que ceux-ci soient des utilisateurs dépendant du tenant ou simplement invités.

clip_image010

 

De là, on peut tester immédiatement (si on n’a pas limité le verbe GET dans notre Azure Function) en appelant simplement d’Azure Function depuis notre navigateur. Si nous avons été préalablement authentifiés, notre token sera utilisé. Sinon, une mire d’authentification nous sera proposée.

clip_image011

 

Bonus : Postman

Pour le bonus, pas de PowerShell. En fait, j’ai découvert qu’obtenir un token Oauth2 et le soumettre pour négocier un token pour s’authentifier auprès de notre Azure Function est à ce jour d’une complexité incroyable. Je me suis donc mis en quête d’une méthode plus simple pour tester mon Azure Function : Postman. C’est un client REST qui a pour avantage de prendre en charge Swagger pour générer la documentation associée à note API.

Avant de rentrer dans Postman, nous allons collecter quelques informations nécessaires. La première est l’identité de notre application Azure Active Directory. Celle-ci utilise l’identité d’un Service Principal (équivalent d’un compte de service). On va commencer par collecter l’identifiant unique de notre application déclarée dans Azure.

clip_image012

 

Passons à la suivante avec un peu de PowerShell pour retrouver l’identifiant unique de notre Tenant Azure Active Directory dans l’attribut TenantID :

$cred = get-credential

Connect-AzureAD -Credential $Cred

Get-AzureADCurrentSessionInfo | fl

clip_image013

 

Continuons en PowerShell en récupérant la ReplyURL de notre application enregistrée dans Azure Active Directory : Get-AzureRMADApplication -DisplayNameStartWith authenticatedaz

clip_image014

 

Maintenant, un peu de construction :

Retournons au niveau de notre application publiée dans Azure. Nous avons besoin de générer un secret qui sera utilisé lors de l’authentification. Pour les besoins de la démonstration, nous allons générer ce secret sans date d’expiration. La bonne pratique consiste à renouveler ces secrets régulièrement et bien sûr de ne pas partager un même secret entre plusieurs applications. Attention à copier la clé générée avant de quitter l’interface. Après-cela, elle ne sera plus divulguée.

clip_image015

 

Maintenant, tout se passe dans Postman. Si on tente le direct, on va clairement nous répondre que nous ne sommes pas autorisés.

clip_image016

 

En fait, on a besoin de construire une authentification Oauth2.

clip_image017

 

Ci-dessous la configuration à utiliser avec quelques explications :

  • Token name : Your choice
  • Grant Type : Authorization Code
  • CallBack URL : Celle que nous avons collectée
  • Auth URL : Celle que nous avons générée
  • Client ID : C’est l’Application ID de notre application (ne cherchez pas ClientID dans le portail, ça sert à rien)
  • Client Secret : Normalement, vous l’avez conservé
  • Scope : Inutile dans notre cas
  • State : Inutile dans notre cas
  • Client Authentication : Send client credentials in Body

 

clip_image018

 

Ne reste plus qu’à cliquer sur « Request Token » pour obtenir notre Access Token. Une mire d’authentification Azure AD nous sera proposée. Attention, dans la configuration par défaut d’Azure AD, la durée de vie est d’une heure. Après, c’est personnalisable : Configurable token lifetimes in Azure Active Directory (Public Preview). Et cela fonctionne.

clip_image019

 

C’est une utilisation très basique de Postman car l’outil va bien plus loin que cela, en particulier pour réaliser des tests unitaires, voire même des tests automatiques.

Benoît – Simple and secure by design but business compliant

Azure Serial console (Preview)

Lorsque je délivre mes cours Azure, quand on aborde le IaaS, je rappelle toujours que nous client consommons des ressources mises à disposition par notre fournisseur sur sa plateforme. Cette plateforme est prévue pour tirer parti de la moindre ressource mise à disposition. Dans le contexte d’Azure, cela signifie que par défaut nos ressources sont hébergées sur des hosts mutualisés. Les équipes de Microsoft ont pour charge de nous garantir une parfaite isolation entre les workloads des clients. D’un point de vue sécurité, il serait catastrophique pour Microsoft que deux de ses clients distincts puissent accéder aux ressources d’un autre sans accords explicit préalable.

Ce rappel fait, on commence à comprendre pourquoi la fonctionnalité « Azure Serial Console » n’est pas native. Quand un Windows ou un Linux ne démarre plus, on a besoin d’un accès direct au système d’exploitation. On-Premises, nos équipes peuvent nous permettre d’accéder à la vue console, que ce soit avec une solution de virtualisation (VMWARE, Hyper-V, …) ou en bare-metal (carte ILO). Dans le Cloud, c’est un peu plus compliqué. En fait, elle n’est disponible en preview que depuis aujourd’hui. Pour tout fournisseur cloud, développer ce type de fonctionnalité pose plusieurs challenges. Le plus important d’entre eux, c’est l’accès à l’infrastructure : Le fait que les clients n’ait pas accès à l’infrastructure Azure est une forme de garantie à destination des clients. S’ils n’ont pas accès aux Hosts Azure, on réduit le risque d’exposition à des failles 0 Day.

La fonctionnalité devrait être visible dans le portail Azure. Dans le blade Virtual Machines, on doit maintenant constater la présence de « Serial (Console Preview) ».

 

Le fait que la fonctionnalité soit visible dans votre portail ne veut pas dire qu’on peut l’utiliser immédiatement. Il y a nécessairement quelques prérequis :

  • L’activation de la fonctionnalité Boot Diagnostics
  • Disposer au minimum du rôle VM Contributor
  • Disposer d’un OS pour lequel la fonctionnalité a été préalablement activée.

Prenons les choses dans l’ordre.

 

Activation de la fonctionnalité Boot Diagnostics

Jusqu’à maintenant, cette fonctionnalité était nécessaire pour journaliser les opérations réalisées par la machine virtuelle pendant la phase de boot ainsi que pour prendre des captures d’écran de la vue console. Maintenant, c’est un prérequis pour l’utilisation de la fonctionnalité Serial Console.

clip_image002

Disposer au minimum du rôle VM Contributor

Heureusement que cette fonctionnalité n’est pas accessible à tout le monde. Effectivement, on peut utiliser le rôle « Built-In » Virtual Machine Contributor. Juste un bémol. Bien faire attention au scope lorsqu’on va assigner ce rôle et bien le limiter aux machines virtuelles pour lesquelles la fonctionnalité sera nécessaire.

Disposer d’un OS pour lequel la fonctionnalité a été préalablement activée.

La fonctionnalité est nativement disponible dans Windows et dans les principales distributions Linux du marché. Pour certaines, des actions supplémentaires sont nécessaire pour activer la prise en charge du Single user Mode.

Utilisation

Quand nos prérequis sont en place, voilà à quoi cela ressemble depuis le portail Azure pour une machine virtuelle de type Windows.

clip_image003

 

C’est maintenant que cela devient un peu plus subtil. La première chose, c’est de se créer un canal de communication avec la commande CMD. Celle-ci retourne à la fois un identifiant et un nom pour ce canal.

clip_image004

 

Mon canal identifiant 0001 a été créé avec le nom Cmd0001, ne reste plus qu’à nous y connecter avec la commande suivante :

CH -SN Cmd0001

clip_image005

 

Ne nous reste plus qu’à nous authentifier. Subtilité des systèmes d’exploitation Windows non raccordés au domaine, comment spécifier qu’on va s’authentifier avec un compte de la base SAM locale ? Réponse ci-dessous :

clip_image006

 

Si l’authentification est acceptée, nous devrions avoir une console comme illustré ci-dessous :

clip_image007

 

Conclusion

Le principal scénario d’usage concerne Active Directory. Maintenant qu’on dispose d’un mode console, on peut enfin reconfigurer un contrôleur de domaine pour démarrer en mode restauration d’annuaire et procéder à une restauration autoritaire de tout ou partie de l’Active Directory.

BenoitS – Simple and Secure by design but Business compliant (with disruptive flag enabled)

Azure Automation en panne de certificats?

Azure Automation, quand ça fonctionne, on ne s’en occupe plus. C’est un service que nous avons provisionné voilà presque un an, nous avons maintenant quantité de Runbooks qui s’exécutent régulièrement. C’est peut-être un service qui fonctionne tout seul mais de temps en temps y a un peu de maintenance et un matin, tout s’arrête de fonctionner. Bizarrement, tous les Runbooks semblent avoir le même problème d’authentification avec Azure, …

clip_image001

clip_image002

Tout de suite ça ressemble à un problème de certificat. Normalement, cela devrait faire tilt. Azure Automation référence des certificats (au moins deux) comme méthodes d’authentifications :

clip_image003

Et oui, même un certificat auto-signé ça expire. Le problème, c’est que ce sont ces certificats qui sont utilisés pour mettre en œuvre les objets connections que nous consommons dans le code PowerShell de nos Runbooks. Le portail Azure ne nous prévient pas (ou tout du moins pas encore) de l’imminence de la date fatidique. C’est une fois les certificats expirés qu’on constate le message suivant dans notre instance Azure Automation.

clip_image004

La solution la plus simple, c’est de suivre le processus pour renouveler les certificats pour chaque RunAs Accounts. Le portail vous proposera de renouveler les deux certificats.

clip_image005

C’est bien mais on peut faire mieux. Renouveler des certificats auto-signés, c’est prendre le risque d’oublier que l’année prochaine on va encore les oublier. Il est temps de reprendre en main le sujet et d’imposer nos propres dates de renouvellement de certificats auto-signés. Pour rappel, c’est un sujet que j’avais abordé dans le billet : Parlons d’identité avec Azure Automation. On peut même faire mieux, demander à notre équipe sécurité de nous fournir un certificat. Si leurs process sont bien faits, ils doivent vous prévenir de l’expiration des certificats qu’ils vous ont mis à disposition.

BenoitS – Simple and Secure by design but Business compliant (with disruptive flag enabled)

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)