Archives de catégorie : Azure Policy

Gestion de la sauvegarde de vos VM Azure avec des tags.

Après l’automatisation du Patch Management, nous allons nous attaquer au sujet de la sauvegarde. Si on doit raisonner de manière industrielle, on va continuer avec les Tags. Cette fois, le Tag se nommera BackupPolicy. Tout comme pour la gestion des Patchs, on va imposer :

  • La présence d’un Tag BackupPolicy avec une valeur par défaut
  • Deux valeurs autorisées (Yes/No)

La subtilité, c’est que dans Azure Site Recovery, nous n’avons pas de fonctionnalité équivalente à Dynamic group. Nous devrons donc gérer cela nous même. On y reviendra plus tard dans ce billet. Première étape : Imposer des valeurs par défaut pour notre Tag BackupPolicy.

 

Imposer les valeurs pour le Tag BackupPolicy

Je vais repartir sur une Azure Policy que j’ai déjà utilisée dans le billet Automatiser Azure Update Management avec Azure Policy. On va donc faire un peu de réuse. On pourrait penser qu’il serait une bonne idée d’assigner l’Azure Policy au niveau du Management Group et non de chaque souscription mais en fait, il n’en est rien. Il y a un ordre d’évaluation des Azure Policies : layering-policies. Assigné au niveau du Management group, elle obligera les consommateurs à déployer leurs machines virtuelles avec le tag BackupPolicy configuré. Assigné au niveau de la souscription, les consommateurs pourront ignorer la configuration et tag (et cependant avoir une valeur par défaut) et le reconfigurer plus tard. L’Azure Policy est disponible ici : AZ-ALLOWEDTAGVALUES. Le code PowerShell pour importer l’Azure Policy est sensiblement identique à celui utilisé dans le billet Automatiser Azure Update Management avec Azure Policy

[String]$ManagementGroupName = « MGMT01 »

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

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

[String]$PolicyName = « AllowedValues4BackupPolicy »

New-AzPolicyDefinition -Name $PolicyName `

-DisplayName $PolicyName `

-Policy $PolicyDefinitionFileURI `

-Parameter $PolicyParameterFileURI `

-ManagementGroupName $ManagementGroupName `

-Mode All

clip_image002

Pour l’assignation, nous allons travailler au niveau d’une souscription.

[String]$ManagementGroupName = « MGMT01 »

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

[String]$BackupPolicyTagName = « BackupPolicy »

[String]$DefaultTagValue = « No »

[String]$PolicyName = « AllowedValues4BackupPolicy »

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

[array]$AllowedValues = @(« Yes », « No »)

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

$PolicyDefinition = Get-AzPolicyDefinition -ManagementGroupName $ManagementGroupName -Name $PolicyName

$AssignParameters = @{

‘BackupPolicyTagName’ = $BackupPolicyTagName;

‘BackupPolicyTagAllowedValues’= ($AllowedValues)

}

New-AzPolicyAssignment -Name $PolicyAssignname `

-PolicyDefinition $PolicyDefinition `

-Scope $Scope `

-PolicyParameterObject $AssignParameters

clip_image004


Imposer une valeur par défaut pour le tag BackupPolicy

Notre Tag BackupPolicy accepte maintenant deux valeurs. Il faut maintenant imposer sa présence à l’aide d’un Azure Policy de Type Append. La Policy AZ-DEFAULTTAG va permettre d’imposer notre valeur par défaut. Rien de bien compliqué dans le code PowerShell ci-dessous :

[String]$ManagementGroupName = « MGMT01 »

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

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

[String]$PolicyName = « DefaultValue4BackupPolicy »

New-AzPolicyDefinition -Name $PolicyName `

-DisplayName $PolicyName `

-Policy $PolicyDefinitionFileURI `

-Parameter $PolicyParameterFileURI `

-ManagementGroupName $ManagementGroupName `

-Mode All

clip_image006

Ne reste plus qu’à assigner. Réaliser l’assignation par défaut au niveau du Management Group impose la même valeur par défaut pour le tag BackupPolicy que la souscription soit de type DEV, UAT ou PROD. Or, ce n’est pas logique. Pour un environnement de production, il est logique de vouloir imposer la sauvegarde.

$SubscriptionID = (Get-AzContext).Subscription.id

[String]$ManagementGroupName = « MGMT01 »

[String]$BackupPolicyTagName = « BackupPolicy »

[String]$DefaultTagValue = « No »

[String]$PolicyName = « DefaultValue4BackupPolicy »

[String]$PolicyAssignName = « MGMT01-VM-P2 »

[String]$AllowedValues = « Yes »

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

$PolicyDefinition = Get-AzPolicyDefinition -ManagementGroupName $ManagementGroupName -Name $PolicyName

$AssignParameters = @{

‘BackupPolicyTagName’ = $BackupPolicyTagName;

‘DefaultTagValue’=($AllowedValues)

}

New-AzPolicyAssignment -Name $PolicyAssignname `

-PolicyDefinition $PolicyDefinition `

-Scope $Scope `

-PolicyParameterObject $AssignParameters

clip_image008

 

Un peu de travail avec Azure Automation

Contrairement à Update Management, ce ne sera pas automatique, on doit donc un peu aider. Deux Runbooks vont être mis à disposition :

Le fonctionnement des deux Runbooks est sensiblement identique, à savoir parcourir la liste des machines virtuelles de la souscription pour identifier la valeur du tag BackupPolicy. Si le tag est configuré à « Yes » et que la machine virtuelle n’est pas inscrite à un plan de protection, alors elle sera ajoutée. Si le tag est configuré à « No », alors on s’assure que la machine virtuelle n’est plus inscrite au plan de protection. On va mettre tout cela en place avec une exécution planifiée toutes les quatre heures. Commençons par l’import dans une instance Azure Automation nommé » « ManagementAutomation » contenue dans le groupe de ressources « Management” :

[String]$ResourceGroupName = « Management »

[String]$AutomationAccountName = « ManagementAutomation »

Import-AzAutomationRunbook -ResourceGroupName $ResourceGroupName `

-AutomationAccountName $AutomationAccountName `

-Path « C:\localgit\BackupPolicy\Runbooks\AutomaticBackupVMS-ON.PS1 » `

-Type PowerShell `

-Published

Import-AzAutomationRunbook -ResourceGroupName $ResourceGroupName `

-AutomationAccountName $AutomationAccountName `

-Path « C:\localgit\BackupPolicy\Runbooks\AutomaticBackupVMS-OFF.PS1 » `

-Type PowerShell `

-Published

clip_image010

Dernière étape, la planification de ces deux runbooks pour une exécution toutes les quatre heures :

[String]$ScheduleName = « FOUR_HOURS »

[DateTime]$StartTime = ((Get-date).date).AddDays(1)

[Int]$SchedulePeriodInHours = 4

[String]$TimeZoneName = ([System.TimeZoneInfo]::Local).Id

New-AzAutomationSchedule -ResourceGroupName $ResourceGroupName `

-AutomationAccountName $AutomationAccountName `

-Name $ScheduleName `

-StartTime $StartTime `

-HourInterval $SchedulePeriodInHours `

-TimeZone $TimeZoneName

Register-AzAutomationScheduledRunbook -ResourceGroupName $ResourceGroupName `

-AutomationAccountName $AutomationAccountName `

-RunbookName « AutomaticBackupVMS-ON » `

-ScheduleName $ScheduleName

Register-AzAutomationScheduledRunbook -ResourceGroupName $ResourceGroupName `

-AutomationAccountName $AutomationAccountName `

-RunbookName « AutomaticBackupVMS-OFF » `

-ScheduleName $ScheduleName

clip_image012

Note : Pour que les Runbooks fonctionnent, il est essentiel que votre instance Azure Automation fonctionne uniquement avec des modules AZ et non ARM : https://aka.ms/azps-migration-guide. Ci-dessous le résultat de l’exécution du runbook AutomaticBackupVMS-ON.

clip_image014

 

Conclusion

Ça demande un peu plus de travail mais cela contribue à réduire la charge de support sur la gestion du IaaS. Il aurait été possible de configurer la sauvegarde pendant le déploiement de la machine virtuelle mais ce choix implique que celui qui déploie dispose de permissions sur l’instance Azure Site Recovery, ce qui n’est pas nécessaire dans mon implémentation. C’est de l’exploitation « sans-couture », transparente pour vos consommateurs Azure.

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.