Archives mensuelles : février 2018

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 -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)