Archives de catégorie : Powershell

Azure BluePrint Import/Export

Le principe des BluePrints est intéressant pour industrialiser la mise en place de différents artefacts (Azure Policies, Templates ARM, Custom Roles, …). On ne peut le consommer que dans le scope dans lequel ils ont été créés ou dans un scope inférieur (Management Group de niveau inférieur, souscription et même groupe de ressources). Problème, comment reproduire cet élément dans une souscription qui ne dépend pas de la même hiérarchie de Management Groups et donc du même Tenant Azure AD.

Historiquement, j’utilisais le script Manage-AzureRMBluePrint car le module Az.Blueprint (à installer manuellement) ne proposait pas d’équivalent. Ce n’est plus le cas depuis quelques jours

clip_image001

 

Après mise à jour, on constate qu’on a bien des commandes pour prendre en charge l’import / export des BluePrints sous forme JSON.

clip_image003

 

Bref, à vos updates de modules. Après, c’est à tester, BluePrint est toujours en Preview à cette heure.

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

Automatiser Azure Update Management avec Azure Policy

Avoir de nombreuses machines virtuelles dans Azure implique de les gérer au niveau Patch Management. Sur le papier, on a un service nommé « Update Management » dans Azure Automation. Le problème, c’est que c’est nous qui devons associer chaque machine virtuelle à une politique de Patch Management. C’est une tâche rébarbative dont on se passerait bien. L’idéal serait que le propriétaire puisse inscrire lui-même sa machine virtuelle dans une politique de Patch Management sous forme de choix imposé.

 

Utilisation des tags dans le Patch Management des VM

Les tags permettent de gérer les ressources manière industrielle. Nous allons introduire un tag obligatoire sur les objets machines virtuelles nommé UpdatePolicy. Nous allons utiliser Azure Policy pour imposer deux règles :

  • La présence d’un tag UpdatePolicy
  • Les valeurs associées au tag UpdatePolicy doivent correspondre à une liste établie.

 

La première règle permet de m’assurer que toute machine virtuelle nouvellement créée ou mise à jour sera automatiquement associée à une politique de Patch Management. La seconde permet de s’assurer que seules les valeurs autorisées sont utilisées. Puis, nous allons réutiliser ces tags pour inscrire les machines virtuelles dans des Dynamic Groups au sein d’Update Management.

 

Imposer une politique de patching par défaut

Pour imposer une politique de Patching, nous avons besoin de mettre en place une Azure Policy en mode Append qui va vérifier que le tag UpdatePolicy est bien présent sur les ressources de Type VirtualMachines. Si ce n’est pas le cas, nous allons proposer une valeur par défaut. Une Azure Policy, c’est composé de deux parties. La première partie, c’est la règle en elle-même. La Policy en elle-même repose sur une double condition, à la fois sur le type de ressource impliquée (Microsoft.Compute/VirtualMachines) et l’absence d’un tag particulier dont son nom est précisé en paramètre. Si cette condition est remplie, un tag est ajouté avec une valeur par défaut.

clip_image002

 

Jusqu’à maintenant, on voit bien que la règle est générique, il nous manque des paramètres. C’est l’objectif du second fichier référençant les paramètres. Pas grand-chose à dire à son sujet.

clip_image003

 

Ne reste plus qu’à importer notre Policy au niveau du scope de notre souscription avec la commande New-AzPolicyDefinition

[String]$SubscriptionID = (Get-AzContext).Subscription.id

[String]$Scope = « /subscriptions/$SubscriptionID/ »

[String]$PolicyDefinitionFileURI = « https://raw.githubusercontent.com/Benoitsautierecellenza/DemoPolicy/master/Policies/AZ-DEFAULTTAG/AZ-DEFAULTTAG-01-RULE.json »

[String]$PolicyParameterFileURI = « https://raw.githubusercontent.com/Benoitsautierecellenza/DemoPolicy/master/Policies/AZ-DEFAULTTAG/AZ-DEFAULTTAG-01-PARAMETERS.json »

[String]$PolicyName = « DefautltValue4UpdatePolicy »

[String]$PolicyDisplayName = « $PolicyName »

New-AzPolicyDefinition -Name $PolicyName `

-DisplayName $PolicyDisplayName `

-Policy $PolicyDefinitionFileURI `

-Parameter $PolicyParameterFileURI `

-Subscription $SubscriptionID `

-Mode All

clip_image005

 

Notre Azure Policy est maintenant être à être assignée au niveau de la souscription (ou resource group au sein de la souscription) avec la commande New-AzPolicyAssignment.

[String]$UpdatePolicyTagName = « UpdatePolicy »

[String]$DefaultTagValue = « AlwaysReboot »

[String]$PolicyName = « DefautltValue4UpdatePolicy »

[String]$PolicyAssignname = « MGMT01-VM-P1 »

[String]$Scope = « /subscriptions/$SubscriptionID/ »

$PolicyDefinition = Get-AzPolicyDefinition -SubscriptionId $SubscriptionID -Custom | Where-Object {$_.name -eq $PolicyName}

$AssignParameters = @{

‘UpdatePolicyTagName’ = $UpdatePolicyTagName;

‘DefaultTagValue’=$DefaultTagValue

}

New-AzPolicyAssignment -Name $PolicyAssignname `

-PolicyDefinition $PolicyDefinition `

-Scope $Scope `

-PolicyParameterObject $AssignParameters

clip_image007

 

C’est lors de l’assignation qu’on renseigne les valeurs des paramètres que nous allons utiliser. Dans notre contexte, nous avons deux paramètres :

  • UpdatePolicyTagName : UpdatePolicy
  • DefaultTagValue : AlwaysReboot

 

Imposer un choix de politique de Patching

Si on laisse faire les consommateurs, ils peuvent renseigner une valeur pour notre tag UpdatePolicy mais encore faut-il que celle-ci correspondre à une liste de valeur préétablies que l’on pourra reconnaître. Problème, les valeurs des tags sont sensibles à la case, donc « AlwaysReboot » est différent de « Alwaysreboot ». Pour éviter ce type de problème, nous allons utiliser une seconde Azure Policy pour imposer une des valeurs ci-dessous pour notre tag « UpdatePolicy » :

  • AlwaysReboot
  • RebootIfRequired
  • OnlyReboot
  • NeverReboot

 

Notre Azure Policy reprend le même principe que pour la première avec la double condition. La subtilité, c’est que cette fois, nous savons que le tag existe forcément. Nous devons refuser toute mise à jour de celui-ci qui ne contiendrait pas une des valeurs correspondant à cette autorisée (d’où l’usage du « In »). Si les deux conditions sont remplies alors on refuse l’opération.

clip_image009

 

Le fichier de réponse correspond à peu de choses près à la Policy précédente, si ce n’est l’utilisation du type « Array » pour décrire non pas une chaine de caractère mais une liste.

clip_image011

 

Le processus d’importation de notre Azure Policy ne change pas.

[String]$SubscriptionID = (Get-AzContext).Subscription.id

[String]$Scope = « /subscriptions/$SubscriptionID/ »

[String]$PolicyDefinitionFileURI = « https://raw.githubusercontent.com/Benoitsautierecellenza/DemoPolicy/master/Policies/AZ-ALLOWEDTAGVALUES/AZ-ALLOWEDTAGVALUES-02-RULE.json »

[String]$PolicyParameterFileURI = « https://raw.githubusercontent.com/Benoitsautierecellenza/DemoPolicy/master/Policies/AZ-ALLOWEDTAGVALUES/AZ-ALLOWEDTAGVALUES-02-PARAMETERS.json »

[String]$PolicyName = « AllowedTagValues4UpdatePolicy »

[String]$PolicyDisplayName = « $PolicyName »

New-AzPolicyDefinition -Name $PolicyName `

-DisplayName $PolicyDisplayName `

-Policy $PolicyDefinitionFileURI `

-Parameter $PolicyParameterFileURI `

-Subscription $SubscriptionID `

-Mode All

clip_image013

Tout comme son assignation. La seule subtilité à ce niveau concerne le passage de la liste des valeurs autorisées pour notre tag.

[String]$PolicyAssignname = « Assign-$PolicyName »

$UpdatePolicyTagName = « UpdatePolicy »

$AllowedValues = @(« AlwaysReboot », »RebootIfRequired », »OnlyReboot », »NeverReboot »)

$PolicyDefinition = Get-AzPolicyDefinition -SubscriptionId $SubscriptionID | Where-Object {$_.Properties.displayname -eq $PolicyDisplayName}

$AssignParameters = @{

‘UpdatePolicyTagName’ = $UpdatePolicyTagName;

‘UpdatePolicyTagAllowedValues’=($AllowedValues)

}

New-AzPolicyAssignment -Name $PolicyAssignname `

-PolicyDefinition $PolicyDefinition `

-Scope $Scope `

-PolicyParameterObject $AssignParameters

clip_image015

 

Associer nos machines virtuelles à des groupes dynamiques

Maintenant, cela se passe dans Azure Automation. Je pars du principe que la fonctionnalité Update Management a été activée sur l’instance Automation. Nous allons créer des Deployment Schedules pour chaque type d’OS et chaque type de Policy. Finalement, on doit créer huit Deployment Schedules. Vu que c’est toujours les mêmes opérations, j’ai industrialisé avec le scripts CreateDeploymentSchedules.ps1. Je vous laisse le personnaliser mais dans l’ensemble, il fait le job et on obtient le résultat ci-dessous :

clip_image017

 

A ce stade, nous n’avons plus qu’à patienter un peu que les groupes dynamiques se peuplent

clip_image019

 

Conclusion

Félicitation, vous avez un exemple fonctionnel de service Patching as A Service. Le procédé est déclinable pour imposer la sauvegarde, il faudra juste un peu d’huile de coude et de Runbooks pour gérer l’enregistrement dans Azure Backup mais c’est le même principe. Ce sera certainement le thème du prochain billet.

Consommer un Storage Account avec une authentification Azure AD

Dans Azure, le service Storage Account est certainement le plus ancien de tous. En plus, il est consommé par tous les autres services. Dans Azure, c’est un service dit « Ring 0 », nécessaire à l’ouverture de toute nouvelle région Azure. Introduire des nouveautés pour ce service est extrêmement complexe. Pourtant, ça arrive de temps en temps. C’est jours-ci, c’est le support d’Azure AD pour l’authentification pour les Storage Accounts. C’est une évolution essentielle car elle nous permet de nous passer des clés primaires et secondaires. Vous savez, c’est celles qu’on obtient avec la commande Get-AzStorageAccountKey :

Get-AzStorageAccountKey -ResourceGroupName $ResourceGroupName -Name $StorageAccountName

clip_image002

Pour accéder à un Storage Account, nous avons besoin d’un contexte que nous allons négocier avec la commande New-AzStorageContext pour laquelle nous allons préciser le paramètre « -UseConnectedAccount » comme illustré ci-dessous :

$Context = New-AzStorageContext -StorageAccountName $storageaccountname -UseConnectedAccount

$Context | Gm

clip_image004

 

Donc plus besoin d’avoir une clé primaire / secondaire pour générer un contexte d’accès au stockage. Pour preuve, je consomme ce contexte immédiatement pour lister les conteneurs de mon Storage Account.

Get-AzStorageContainer -Context $context -Name *

clip_image006

 

Pour être complet, nous avons de nouveaux rôles Azure en relation avec le stockage :

Get-AzRoleDefinition | Where-Object {$_.name -Like « *Storage* »} | Select-Object name

clip_image008

 

Lorsqu’on détaille le rôle « Storage Blob Data Contributor », on découvre de nouvelles permissions liées aux données : DataActions & NotDataActions. C’est grâce à ces permissions que l’on va pouvoir déléguer l’accès au stockage.

clip_image010

 

Voilà, maintenant, plus d’excuse pour utiliser les clés primaires / secondaires pour accéder à vos Storage Accounts.

 

BenoîtS – Simple and Secure by design but Business compliant.

Migrer une machine virtuelle entre régions Azure

Voilà un cas client qui m’a occupé un certain temps. Mon client déploie une application basée sur des services IaaS à l’aide d’images préalablement générées. Mes images « sources » sont localisées dans la région Azure France Central et doivent être mise à disposition dans la région Brazil South. Voilà pour le besoin de base.

Mon premier réflexe a été de rechercher si un service de réplication d’images n’existait pas. On a bien un repository pour les images pour les conteneurs (Azure Contrainer Registry), on doit donc avoir le même type de service pour le IaaS. C’est effectivement le cas, cela se nomme Shared Image Gallery. Mais, j’ai tout de suite exclu ce choix car :

  • Service actuellement en Preview
  • Pas encore disponible dans les régions Azure qui me concernent

Second réflexe, Azure Site Recovery. Cela fait quelques temps que l’on peut utiliser le service pour « cloner » une machine virtuelle existante pour assurer un DRP vers une autre région Azure. Très rapidement, j’ai dû abandonner cette option car les régions Azure source et destination ne dépendent pas du même cluster géographique.

clip_image001

Source : https://docs.microsoft.com/en-us/azure/site-recovery/azure-to-azure-support-matrix

Pire, le cas de la région Azure Brazil South est un peu particulier car au sein de son Géo, il n’a pas de région Azure associée. Bref, pas la bonne solution.

En dernier ressort, je suis tombé sur cet article : Synchronously copy all managed disks of an Azure Virtual Machine to Azure Storage Accounts in multiple Azure regions. C’est presque ce qu’il me faut car il faudra reconstruire une image après. A mes yeux, la démarche proposée avait quelques défauts :

  • On paie une VM pour faire la copie avec AZCopy alors qu’on peut faire un job de copie
  • Elle est un peu salée la VM en SKU E pour de la copie de fichiers
  • Les opérations sont réalisées en séquentielle alors qu’on se contente de suivre un job.

J’avais déjà publié un billet pour cloner des machines virtuelles dans Azure. J’ai donc juste poussé la logique d’industrialisation jusqu’au bout. Cela va se dérouler en plusieurs étapes :

  • Etape n°1 : Initialisation
  • Etape n°2 : Génération des clés SAS pour les VHD
  • Etape n°3 : Initialisation des opérations de copie
  • Etape n°4 : Suivi des opérations de copie
  • Etape n°5 : Reconstruction des Managed Disks

 

Etape n°1 : Initialisation

Avant de commencer, on va poser quelques bases. J’ai déployé une machine virtuelle en utilisant mon image dans le groupe de ressources « FranceCentral ». L’objectif est d’obtenir des Managed Disks dans le groupe de ressources « BrazilSouth » dans lequel on va préalablement avoir créé un Storage Account qui va être utilisé pour réceptionner les VHD à copier.

$SourceResourceGroup = « FranceCentral »

$SourceVMName = « MASTER »

$dataDiskNames = New-Object System.Collections.ArrayList

$dataDiskSASes = New-Object System.Collections.ArrayList

$SasKeyDuration = 36000

$DestinationResourceGroup = « BrazilSouth »

$DestinationStorageAccount = « brazilreplication »

$Accounttype = ‘Standard_LRS’

$VM = Get-AzureRmVM -ResourceGroupName $SourceResourceGroup -Name $SourceVMName -Verbose

clip_image002

 

Etape n°2 : Génération des clés SAS pour les VHD

Pour chaque disque composant notre machine virtuelle, nous devons générer une clé SAS. J’ai volontairement configuré une durée de vie assez longue, ne voulant pas tomber dans une situation ou les clés SAS auraient échouées pour cause d’une copie beaucoup trop longue.

$osDiskName = $VM.StorageProfile.OsDisk.Name

$osDiskSAS = (Grant-AzureRmDiskAccess -Access Read -DiskName $osDiskName -ResourceGroupName $SourceResourceGroup -DurationInSecond $SasKeyDuration -Verbose).AccessSAS

foreach($dataDisk in $VM.StorageProfile.DataDisks)

{

$dataDiskNames.Add($dataDisk.Name) | Out-Null

}

foreach($dataDiskName in $dataDiskNames)

{

$dataDiskSASes.Add((Grant-AzureRmDiskAccess -Access Read -DiskName $dataDiskName -ResourceGroupName $SourceResourceGroup -DurationInSecond $SasKeyDuration -Verbose).AccessSAS) | Out-Null

}

clip_image003

 

A ce stade, si on observe un des objets Managed Disks dans le portail, on peut constater qu’une clé SAS a bien été générée pour chacun d’eux.

clip_image004

 

Etape n°3 : Initialisation des opérations de copie

C’est en ce point que je me suis différencié de l’article Synchronously copy all managed disks of an Azure Virtual Machine to Azure Storage Accounts in multiple Azure regions. Mon besoin n’étant pas de répliquer mes disques dans de multiples régions, pas besoin d’autant d’instance de la machine virtuelle Ubuntu pour réaliser les opérations de copies. En plus, on n’a pas besoin d’attendre. Ça fait bien longtemps qu’AZCopy.EXE supporte la notion de job pour les opérations de copies. En PowerShell, AZCOPY.EXE, c’est Start-AzureStorageBlobCopy. A ce stade, du contenu va commencer à apparaître dans le contenu prévu à cet effet dans le Storage Account localisé dans la région cible.

$DestStorageAccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $DestinationResourceGroup -Name $DestinationStorageAccount

$DestStorageContext = New-AzureStorageContext -StorageAccountName $DestinationStorageAccount -StorageAccountKey $DestStorageAccountKeys[0].Value

Start-AzureStorageBlobCopy -AbsoluteUri $osDiskSAS -DestContainer $SourceVMName.ToLower() -DestContext $DestStorageContext -DestBlob $($osDiskName + « .VHD »)

$DatadiskCount = 0

foreach($dataDiskSAS in $dataDiskSASes)

{

Start-AzureStorageBlobCopy -AbsoluteUri $dataDiskSAS -DestContainer $SourceVMName.ToLower() -DestContext $DestStorageContext -DestBlob $(« datadisk-$DatadiskCount » + « .VHD »)

$DatadiskCount +=1

}

clip_image005

 

Etape n°4 : Suivi des opérations de copie

La commande PowerShell Start-AzureStorageBlobCopy initié un job que l’on va suivre. Avantage, on va paralléliser toutes les opérations de copie. Pour suivre cela, on dispose de la commande PowerShell Get-AzureStorageBlobCopyState. La durée des opérations de copie dépendra principalement de la volumétrie de données à répliquer. Pour mes tests, quarante-neuf minutes étaient nécessaires pour répliquer un Managed Disk SATA de 127Go et un autre de 1To.

$StartTime = Get-Date

$StorageOperations = Get-AzureStorageBlob -Container master -Context $DestStorageContext | Get-AzureStorageBlobCopyState

While ($StorageOperations | Where-Object {$_.status -eq « Pending »})

{

$StorageOperations | select-Object Copyid, Status

Start-Sleep -Seconds 10

$StorageOperations = Get-AzureStorageBlob -Container master -Context $DestStorageContext | Get-AzureStorageBlobCopyState

}

$CopyTimeSpan = New-TimeSpan -Start $StartTime -End (Get-Date)

$Totalcopyoperations ='{0:N0}’ -f $($CopyTimeSpan.TotalMinutes)

Write-Host « Copy operation completed in $Totalcopyoperations minutes. »

clip_image006

 

Etape n°5 : Reconstruction des Managed Disks

Il ne nous reste plus qu’à reconstruire des Managed Disks en commençant par construire un objet de type Managed Disk à l’aide de la commande PowerShell New-AzureRmDiskConfig. De, là, il n’y a plus qu’à créer la ressource Azure à l’aide de la commande PowerShell New-AzureRmDisk.

$Container = Get-AzureStorageContainer -Container master -Context $DestStorageContext

$ContainerBaseURI = ($Container.CloudBlobContainer).uri.absoluteuri

$ListVHDs = Get-AzureStorageBlob -Container master -Context $DestStorageContext

ForEach ($VHD in $ListVHDs)

{

$Disksize = ($vhd.Length/1GB) +1

$Vhduri = $ContainerBaseURI + « / » + $vhd.name

$diskName = ($vhd.name).Substring(0, ($vhd.name).lastindexof(« . »))

Write-Host « Creating Managed Disk $diskName in Resource Group $DestinationResourceGroup. »

$diskConfig = New-AzureRmDiskConfig -AccountType $Accounttype -Location ((get-azurermresourcegroup -Name $DestinationResourceGroup).location) -DiskSizeGB $Disksize -SourceUri $vhdUri -CreateOption Import

New-AzureRmDisk -DiskName $diskName -Disk $diskConfig -ResourceGroupName $DestinationResourceGroup

}

clip_image007

 

Maintenant, il y a plus qu’à reconstruire l’image de référence au brésil et supprimer les fichiers VHD.

 

Conclusion

La solution n’est pas parfaite, elle peut encore être améliorée. Si vous être plus de culture Linux, allez lire ce billet : Copy custom vm images on azure. L’approche est sensiblement identique.

 

Benoît – Simple and Secure by design but Business compliant.

Générer un certificat auto-signé avec Key-Vault

Pour ceux qui comme moi génèrent des certificats depuis longtemps, je suis passé par toutes les étapes (OpenSSL, New-SelfSignedCertificate). Avec Azure, il était logique que je regarde comment générer un certificat auto-signé. Le problème des solutions citées précédemment, c’était que le certificat était généré localement, dans le magasin personnel de la machine. Combien de fois avez-vous oublié le certificat et sa clé privée sur un serveur ou pire sur votre portable.

Avec Azure, l’usage des certificats s’est banalisé. On associe des Service Principals aux applications déclarées dans Azure AD que l’on consomme ensuite dans différents services (Azure Automation aujourd’hui par exemple). Pour cette raison, j’avais rapidement cherché un moyen de générer mes certificats auto-signés directement dans Azure. Logiquement, j’ai commencé par regarder le KeyVault. Une recherche rapide dans le module PowerShell associé me confirme que c’est bien prévu dans les scénarios du produit.

clip_image001

J’ai donc creusé un peu le sujet et voilà la version courte. On commence par préparer un objet CertificatePolicy :

$AutomationcertificateName = « LabAutomation »

$AutomationcertSubjectName = « cn= » + $AutomationcertificateName

$AutomationCertificateLifetimePolicy = 36

$Policy = New-AzureKeyVaultCertificatePolicy -SecretContentType « application/x-pkcs12 » -SubjectName $AutomationcertSubjectName -IssuerName « Self » -ValidityInMonths $AutomationCertificateLifetimePolicy -ReuseKeyOnRenewal

$Policy

clip_image002

 

Vous l’avez bien compris, on peut personnaliser avec beaucoup d’autres paramètres, mais on va faire court. Pour la suite, cela se passe avec la commande Add-AzureKeyVaultCertificate. Point de détail, la commande retourne un status, à nous de suivre jusqu’à ce que le certificat soit délivré :

$AddAzureKeyVaultCertificateStatus = Add-AzureKeyVaultCertificate -VaultName ‘mykeyvaultforcert’ -Name $AutomationcertificateName -CertificatePolicy $Policy

$AddAzureKeyVaultCertificateStatus.status

While ($AddAzureKeyVaultCertificateStatus.Status -eq « inProgress »)

{

Start-Sleep -Seconds 10

$AddAzureKeyVaultCertificateStatus = Get-AzureKeyVaultCertificateOperation -VaultName ‘mykeyvaultforcert’ -Name $AutomationcertificateName

$AddAzureKeyVaultCertificateStatus.status

}

$AddAzureKeyVaultCertificateStatus

clip_image003

 

Notre certificat auto-signé est maintenant dans le KeyVault, pour l’utiliser, ne nous reste plus qu’à l’exporter. La ça se complique un peu, il faut en passer par un peu de Dot.Net avec la classe X509Certificate2Collection. Dans le code ci-dessous, nous générons un fichier PFX contenant, le certificat, sa clé privée, le tout sécurité par un mot de passe (merci de fermer la session PowerShell après usage !)

$PfxCertPathForRunAsAccount = « C:\TEMP\CERTIFICATE.PFX »

$PfxCertPlainPasswordForRunAsAccount = « P@ssw0rd12345 »

$secretRetrieved = Get-AzureKeyVaultSecret -VaultName ‘mykeyvaultforcert’ -Name $AutomationcertificateName

$pfxBytes = [System.Convert]::FromBase64String($secretRetrieved.SecretValueText)

$certCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection

$certCollection.Import($pfxBytes, $null, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)

$protectedCertificateBytes = $certCollection.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $PfxCertPlainPasswordForRunAsAccount)

[System.IO.File]::WriteAllBytes($PfxCertPathForRunAsAccount, $protectedCertificateBytes)

Get-ChildItem -Path « c:\temp\cert*.* »

clip_image004

 

Ne reste plus qu’à consommer. Avantage de cette approche, le certificat est préservé dans notre KeyVault. Dans mon contexte, Azure Automation est partie intégrante d’une solution en cours de développement, nous réinstancions donc plusieurs fois par jour nos instances.

 

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

Ma session au Powershell Saturday 2018

Ce samedi s’est déroulé l’édition française du PowerShell Saturday dans les locaux de Cellenza. Pendant, cette édition, j’ai eu l’occasion de présenter l’avancement sur Resource Group As a Service. Resource Group As a Service est un sujet que j’avais déjà présenté lors du Global Azure Bootcamp de 2018.

clip_image001

A l’époque, on était plus proche du PoC of Concept, entre temps, le développement a beaucoup avancé. Aujourd’hui, nous sommes maintenant plus proche du Minimum Viable Product. L’objectif de cette session n’était pas de présenter la solution en elle-même mais ce que son développement m’a permis d’apprendre sur Azure Function, Azure Automation et sur PowerShell lui-même. C’est donc plus une session de retour sur expérience.

Pour ceux que cela intéresse, la présentation ainsi que les exemples PowerShell présentés sont disponibles à cette URL.

 

Benoît – Simple and Secure by Design but Business compliant

PoShKeePass un module PowerShell pour KeePass

Je suis un adepte de KeePass depuis longtemps. La solution présente pas mal d’avantages dont d’être certifié par l’ANSSI. Travaillant pour plusieurs clients simultanément, je manipule donc beaucoup de credentials permettant d’accéder aux souscriptions Azure (Avec Multi-Factor authentification cela s’entend). Pour travailler avec le portail pas de problème. Pour les scripts PowerShell, j’ai fini par découvrir le module PowerShell PoShKeePass qui propose un certain nombre de commandes pour manipuler le contenu de notre base de données :

clip_image001

 

En quelques commandes, on peut rapidement accéder à nos secrets :

Import-module PoShKeePass

Get-KeePassDatabaseConfiguration -DatabaseProfileName Personnal

Get-KeePassEntry -DatabaseProfileName Personnal -KeePassEntryGroupPath MyKeePass2018/MyAzure -AsPlainText | format-list

clip_image002

 

Maintenant plus d’excuses pour ne pas sécuriser ses comptes Azure AD à privilèges.

 

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

Arretons de stocker os tokens Azure avec le module Powershell

Ca faisait quelques temps que j’avais remarqué un comportement « étrange » de certains de mes scripts Azure. Pour beaucoup d’entre eux, je commence par m’assurer avec un Get-AzuremContext que je suis bien authentifié. A ma grande surprise, je découvre que oui, pourtant, je n’ai renseigné aucun credential. Magie ? Nan. J’ai creusé un peu plus le sujet pour redécouvrir le module AzureRM.Profile. Ma recherche m’a amenée sur cette page : Automatic-Context-Autosave avec la découverte de quelques commandes inconnues :

clip_image001

 

Trois commandes ont attiré mon attention :

  • Disable-AzureRmContexteAutoSave
  • Enable-AzurermContextAutosave
  • Get-AzureRmContextAutoSaveSettings

J’ai donc commencé par Get-AzureRmContextAutoSaveSettings avec une surprise. Mes tokens sont bien conservés dans mon profil, c’est la configuration par défaut.

clip_image002

 

En ce qui me concerne, d’un point de vue sécurité, c’est moche. D’une part, je me balade avec les tokens de mes clients (MFA n’est pas encore chez tous et cela ne résout pas toujours le problème). C’est dommage qu’on fasse attention à utiliser des navigateurs en mode privé pour se connecter à Azure si le module PowerShell ignore le même ce concept. D’autre part, cela induit un risque. J’ai tendance à utiliser beaucoup de scripts chez mes différents clients. Avec cette fonctionnalité, je risque de travailler sur la mauvaise souscription sans m’en rendre compte avec un impact tout aussi industriel que le script.

Pour cette raison, j’ai pris l’habitude de désactiver cette fonctionnalité avec la commande Disable-AzureRmContextAutoSave comme illustré ci-dessous :

clip_image003

 

Maintenant, il n’y a plus de risque pour moi.

clip_image004

 

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