Initiation aux scripts Microsoft Powershell
/// Ressources utilisées :
L’objectif de cet atelier est d’apprendre les principes fondamentaux de l’écriture de scripts dans Microsoft Powershell :
-
Écriture et exécution de scripts
-
Utilisation de variables et fonctions pour rendre les scripts flexibles
-
Utilisation de structures de contrôle (tests, boucles) pour déterminer les bons traitements à appliquer et/ou les effectuer de manière répétitive
-
Gestion des erreurs pour apporter plus de robustesse aux scripts
Pour cela, on va s’appuyer sur l’écriture d’un script Microsoft Powershell dont le rôle sera de détecter l’état — activé ou désactivé — du pare-feu Windows sur les différents profils (Privé/Domaine/Public) et proposer de le ré-activer le cas échéant.
💻 Travail n° 1 Écriture et exécution de scripts depuis VSCode
🕮 Apport de connaissances :
Il est possible d’écrire des scripts Microsoft Powershell avec un simple éditeur de texte comme le Bloc-notes Windows ou Notepad++ mais VSCode est doté de fonctions qui en facilitent l’écriture :
-
coloration syntaxique
-
auto-complétion
-
détection d’erreurs
-
organisation des scripts en projets
-
…
VSCode permet enfin d’exécuter les scripts sans quitter l’éditeur.
🎯 Travail à faire :
-
Télécharger en local depuis le NAS l’extension “Powershell” (→
\\Diskstation\install\vscode\extensions\ms-vscode.PowerShell-<version>.vsix
) -
L’installer depuis VSCode et recharger l’IDE comme proposé
-
Créer un fichier
test.ps1
dans votre répertoire de travail (ex. :~/Documents
) avec la cmdlet suivante :Write-Host -ForegroundColor green "Youpi ! ça marche !"
…puis l’exécuter pour vérifier le bon fonctionnement
À retenir :
Un script Microsoft Powershell porte l’extension |
💻 Travail n° 2 Stratégies d’exécution
🕮 Apport de connaissances :
Pour éviter tant que possible l’exécution de scripts malveillants, Windows met en place des stratégies d’exécution qui vont autoriser plus ou moins de choses :
-
AllSigned
-
Bypass
-
Default
-
RemoteSigned
-
Restricted
-
Undefined
-
UnRestricted
Voir Stratégies d’exécution PowerShell pour une description de ces différentes stratégies d’exécution.
On a de plus la possibilité de définir une stratégie d’exécution pour une étendue particulière :
-
l’ordinateur local (→ LocalMachine)
-
pour l’utilisateur actuel (→ CurrentUser)
-
pour une session particulière (→ Process)
-
les ordinateurs d’un domaine (→ MachinePolicy)
-
les utilisateurs d’un domaine (→ UserPolicy).
🎯 Travail à faire :
-
Exécuter la cmdlet
Get-ExecutionPolicy -List
pour afficher la statégie d’exécution en cours sur chacune des étendues. -
Se référer à l’aide de la cmdlet
Set-ExecutionPolicy
et mettre en place une stratégie d’exécution RemoteSigned sur l’étendue LocalMachine
💻 Travail n° 3 Boucles
🕮 Apport de connaissances :
Microsoft Powershell propose plusieurs instructions pour faire des boucles :
-
for (…) {…}
Exemple :For ($i = 0; $i -le 10; $i++) { Write-Host "'i' vaut $i" }
-
ForEach(…) {…}
Exemple :$heros = ("superman", "batman") ForEach($hero in $heros) { Write-Host "Nom Super-Héro : $hero" }
-
Do {…} While(…)
Exemple :Do { Write-Host "!! Risque de verglas !!" } While(temperature -lt 3)
🎯 Travail à faire :
-
Créer un fichier
firewall.ps1
dans lequel vous afficherez dans une boucle les propriétésname
etEnabled
de chaque objet retourné par la cmdletGet-NetFirewallProfile
sachant que celle-ci retourne un tableau parcourable grâce à l’instructionForEach.
Pour afficher une propriété d’une variable au sein d’une chaîne de caractères on doit utiliser l’opérateur de sous-expression (→
$()
).ExemplePS > $today = Get-Date PS > Write-Host "Jour de la semaine : $today.DayOfWeek" (1) Jour de la semaine : 11/27/2023 12:37:38.DayOfWeek # NOK (2) PS > Write-Host "Jour de la semaine : $($today.DayOfWeek)" (3) Jour de la semaine : Monday # OK (4)
1 En écrivant $today.DayOfWeek
on pense qu’on va afficher la propriétéDayOfWeek
de la variable$today
…2 … or on voit que DayOfWeek
n’a pas été interprété comme le nom d’une propriété mais comme du texte littéral (c-à-d sans signification particulière). On affiche donc la date complète suivi de “.DayOfWeek”3 On utilise cette fois-ci l’opérateur de sous-expression $()
pour demander à Microsoft Powershell d’interpréter tout ce qu’il y a entre parenthèses et là…4 …on vérifie qu’on affiche bien le jour de la semaine Voir How can you use an object’s property in a double-quoted string?
pour un résumé des règles d’interpolation des variables dans les chaînes entre guillemets doubles.
PS > .\ctrl-firewall.ps1
Parefeu du profil " Domain " -> True
Parefeu du profil " Private " -> True
Parefeu du profil " Public " -> True
💻 Travail n° 4 Structures conditionnelles
🕮 Apport de connaissances :
Dans les scripts, on devra souvent tester des conditions pour décider si certaines commandes doivent être exécutées ou pas.
Microsoft Powershell propose, comme dans la plupart des langages de programmation, une instruction If … ElseIf … Else …
pour faire des tests.
Les opérateurs de comparaison mis à disposition par Microsoft Powershell diffèrent cependant quelque peu de ceux des langages C++ ou Javascript par exemple :
-
-eq
→ “… égal à …” -
-le
→ “… inférieur ou égal à …” -
-ge
→ “… supérieur ou égal à …” -
-gt
→ “… supérieur à …” -
-lt
→ “… inférieur à …”
$Age = 21
If ($Age -ge 18)
{
Write-Host "Vous êtes majeur"
} Else
{
Write-Host "Vous êtes mineur"
}
L’opérateur -not
permet d’inverser le sens de l’opérateur de comparaison :
$vitesse = 75
If (-not ($vitesse -lt 80) )
{
Write-Host "Dépassement vitesse autorisée"
}
Il est possible de combiner plusieurs tests avec les opérateurs :
-
-or
-
-and
-
-xor
If (($pH -ge 7) -and ($pH -le 7.4))
{
Write-Host "Le Ph de la piscine est OK"
}
Enfin, pour tester si une condition est vraie ou fausse, Microsoft Powershell dispose de 2 constantes : $True
et $False
.
If( ($allumageAuto -eq $True) -and ($luminosite -lt 15) )
{
Write-Host "Allumage des feux de croisement"
}
🎯 Travail à faire :
-
Faire évoluer le script
firewall.ps1
pour qu’il affiche en couleur l’état d’activation du firewall.Voir pour cela les options “-ForegroundColor"` et/ou "`-BackgroundColor” de la cmdlet
Write-Host
.Exemple de résultat attenduPS > .\firewall.ps1 Parefeu du profil "Domain" : Activé Parefeu du profil "Private" : Désactivé Parefeu du profil "Public" : Activé
-
Modifier le script pour qu’il propose de réactiver — via la cmdlet
Set-NetFirewallProfile
— le parefeu sur le(s) profil(s) sur le(s)quel(s) il est désactivé. Ceci nécessite d’exécuter Microsoft Powershell en tant qu’administrateur.La cmdlet
Read-Host
permet à l’utilisateur de faire une saisie depuis la console.Exemple de résultat attenduPS > .\firewall.ps1 Parefeu du profil "Domain" : Activé Parefeu du profil "Private" : Désactivé Parefeu du profil "Public" : Désactivé Voulez-vous réactiver le parefeu pour le profil " Private " ? [Y/n] : Y Parefeu du profil "Private" : Activé Voulez-vous réactiver le parefeu pour le profil " Public " ? [Y/n] : Y Parefeu du profil "Public" : Activé PS > .\firewall.ps1 Parefeu du profil "Domain" : Activé Parefeu du profil "Private" : Activé Parefeu du profil "Public" : Activé
💻 Travail n° 5 Paramètres d’un script
🕮 Apport de connaissances :
Il est possible de fournir aux scripts des paramètres comme on le fait pour les cmdlets de façon à les rendre plus flexibles.
Pour déclarer un paramètre, on utilise un “bloc” Param()`.
Dans ce bloc, les paramètres seront représentés par des variables dont le nom est défini par l’utilisateur. Le nom des paramètres à saisir lors de l’appel du script dépendra alors directement du nom de la variable qui lui est associée.
Param(
[Parameter(Mandatory, HelpMessage = "Saisir un code de pays (en majuscules) SVP")]
[ValidateNotNullOrEmpty()]
[string]$IsoCode, (1)
[Parameter(HelpMessage = "Force l'intitulé de la question en majuscules")]
[switch]$Upper (2)
)
Switch($IsoCode) { (3)
'EN' {$question = "Input your name"}
'FR' {$question = "Saisir votre nom"}
}
if($Upper) { (3)
$question = $question.ToUpper()
}
$input = Read-Host $question
Switch($IsoCode) { (3)
'EN' { Write-Host "Hello $input !"}
'FR' { Write-Host "Bonjour $input !"}
}
1 | On définit un paramètre (→ -IsoCode ) obligatoire (→ Mandatory ) de type chaîne (→ string ) |
2 | On définit un paramètre (→ -Upper ) optionnel à bascule (→ switch ) |
3 | On adapte le traitement aux valeurs fournies aux paramètres lors de l’appel du script |
PS > .\welcome.ps1 -IsoCode EN -Upper
INPUT YOUR NAME: Ragnar (1)
Hello Ragnar !
PS > .\welcome.ps1 -IsoCode EN
Input your name: Ragnar (2)
Hello Ragnar !
PS > .\welcome.ps1 -IsoCode FR -Upper
SAISIR VOTRE NOM: Ragnar (3)
Bonjour Ragnar !
PS > .\welcome.ps1 -Upper (4)
cmdlet welcome.ps1 at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
IsoCode: EN
INPUT YOUR NAME: Ragnar
Hello Ragnar !
1 | Intitulé question en anglais et majuscules |
2 | Intitulé question en anglais et minuscules |
3 | Intitulé question en français et majuscules |
4 | Comportement quand le paramètre obligatoire (→ -IsoCode ) n’est pas fourni |
🎯 Travail à faire :
-
S’inspirer de l’exemple de script
welcome.ps1
pour compléter le scriptfirewall.ps1
pour qu’il accepte un paramètre-Force
de type “switch” dont le rôle sera de forcer l’activation du parefeu sur le(s) profil(s) sur le(s)quel(s) il est désactivé sans devoir passer par une confirmation de l’utilisateur
🞄 🞄 🞄