PowerShell

Architecture, Automatisation & Orchestration

Licence ASR

1. Qu'est-ce que PowerShell ?

Bien plus qu'un terminal.

La Genèse

De l'âge de pierre à l'Open Source.

Le problème (Avant 2002)

Windows était "point-and-click". L'automatisation était un enfer.

CMD.exe

Héritage MS-DOS.
Trop basique.

vs

VBScript

Puissant mais complexe.
Faille de sécurité ambulante.

Pendant ce temps, Linux avait Bash...

Le "Monad Manifesto" (2002)

Jeffrey Snover propose une idée radicale.

"Sur Unix, tout est fichier texte, donc Bash parse du texte. Sur Windows, tout est API et .NET. Nous avons besoin d'un Shell qui parse des Objets."

Nom de code du projet : Monad.

L'Évolution du langage

  • 2006 : PowerShell 1.0
    Sortie avec Windows XP/Server 2003. Révolution, mais incomplet.
  • 2016 : Le Grand Virage (Open Source)
    PowerShell devient Core (6.0). Il tourne sur Linux et macOS. Microsoft s'ouvre au monde.
  • 2021+ : PowerShell 7
    La réunification. Une seule version pour tout le monde (Windows, Linux, Cloud).

La Philosophie "Objet"

La différence fondamentale avec Bash/Linux.

Bash

Manipule du TEXTE.

ls -l | awk '{print $9}'
Nécessite du parsing (awk, sed, cut, regex). Si l'affichage change, le script casse.

PowerShell

Manipule des OBJETS .NET.

Get-ChildItem | Select-Object Name
On accède aux propriétés (Name, Length, LastWriteTime). Robuste et structuré.

L'Environnement de Développement

🚫 PowerShell ISE : Déprécié. Ne plus utiliser (pas de support PS 7, pas de Git).
✅ Visual Studio Code :
  • Extension PowerShell officielle.
  • Intégration Git, Debugging, Snippets.
  • IA (Copilot) pour l'assistance.

1-A. PowerShell vs Python

Guerre des langages ou alliance stratégique ?

Deux Philosophies distinctes

PowerShell

  • Cible : Admins Système, Ops.
  • Natif : Intégré au cœur de Windows (WMI, COM, AD).
  • Flux : Manipule des Objets .NET.

Python

  • Cible : Développeurs, Data Scientists.
  • Universel : Cross-platform par excellence.
  • Flux : Manipule du Texte / Structures de données.

Quand utiliser quoi ?

Critère PowerShell (Le Gestionnaire) Python (Le Constructeur)
Administration Windows Roi absolu (AD, Exchange, O365) Possible mais via des wrappers complexes
Performance Calcul Lent (Surcharge Objets .NET) Très rapide (Bibliothèques C/C++)
Linux / Mac Possible (PowerShell Core 7) Natif partout (Installé par défaut)
Complexité du code Verbeux (Verb-Noun) mais lisible Concis, syntaxe stricte

Exemple : Récupérer une info Web

Python (Nécessite souvent des librairies externes comme requests)

import requests
r = requests.get('https://api.github.com')
print(r.json()['current_user_url'])

PowerShell (Natif, pas d'installation)

$r = Invoke-RestMethod -Uri 'https://api.github.com'
Write-Host $r.current_user_url

En PowerShell, le JSON est converti implicitement en objet navigable.

Le verdict Sécurité & Réseaux

  • Utilisez Python pour : Le Pentest (Scapy), l'IA, le traitement de données massives (Big Data), les outils Cross-platform.
  • Utilisez PowerShell pour : L'administration de parc, l'automatisation Cloud (Azure), l'Incident Response (Live Forensics), l'Active Directory.

En 2026, un Admin doit connaître les deux.

2. Syntaxe & Commandes de Base

Verbe-Nom : La grammaire de PowerShell.

Cmdlets Essentielles

Structure : Verbe-Nom (Singulier)

# Processus (Gestionnaire des tâches)
Get-Process -Name "chrome"
Stop-Process -Name "notepad" -Force

# Services (Daemons)
Get-Service | Where-Object Status -eq 'Stopped'
Restart-Service "Spooler"

# Fichiers
Get-ChildItem -Path "C:\Temp" -Recurse  # équivalent ls -R
New-Item -Path ".\config.json" -ItemType File

Variables & Types

Typage dynamique (mais forçable).

$maChaine = "Bonjour $env:USERNAME"  # Interpolation de variable
$monEntier = 42
[int]$forceType = "100"              # Casting explicite

# Tableaux (Arrays)
$monTableau = @("Rouge", "Vert", "Bleu")
$monTableau[0]  # Rouge

# HashTables (Dictionnaires clé/valeur)
$config = @{
    Serveur = "192.168.1.10"
    Port    = 8080
}
Write-Host $config.Serveur

Opérateurs de Comparaison

Pas de == ou != ici !

Opérateur Description Exemple
-eq / -ne Égal / Différent $a -eq 10
-gt / -lt Plus grand / Plus petit $a -gt 5
-like Wildcard (*) "Test" -like "T*"
-match Regex "A12" -match "[A-Z]\d{2}"
-in / -contains Présence dans une liste 5 -in (1,2,5,8)

Boucles & Conditions

# Condition IF
if ($a -gt 10) { Write-Host "Grand" } else { Write-Host "Petit" }

# Boucle FOREACH (Classique)
foreach ($file in $files) { Write-Host $file.Name }

# Boucle PIPELINE (La méthode PowerShell)
Get-Service | ForEach-Object {
    if ($_.Status -eq 'Stopped') {
        Write-Warning "Service $($_.Name) à l'arrêt"
    }
}
$_ représente l'objet courant dans le pipeline.

3. Mise en Forme & One-Liners

L'art de l'affichage.

Formatage vs Donnée

⚠️ Les commandes Format-* détruisent l'objet pour créer de l'affichage. À utiliser uniquement à la toute fin !

# Tableau propre (pour les yeux)
Get-Process | Sort-Object CPU -Descending | Format-Table Name, CPU -AutoSize

# Liste détaillée
Get-Service "wuauserv" | Format-List *

# GridView : L'outil magique interactif
Get-Process | Out-GridView -PassThru | Stop-Process

Format-Table

Format-List

Out-Gridview

4. Fonctions & Modules

Industrialiser le code.

Créer une Fonction Avancée

function Get-SystemInfo {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string]$ComputerName,
        [int]$Port = 80
    )
    
    Write-Verbose "Connexion à $ComputerName..."
    return [PSCustomObject]@{
        Host = $ComputerName
        Status = "Online"
    }
}

Appel de Fonction

ERREUR CLASSIQUE : Pas de parenthèses pour les arguments !
# ❌ MAUVAIS (Syntaxe C#/Python)
Get-SystemInfo("PC-01", 8080)

# ✅ BON (Syntaxe Shell)
Get-SystemInfo -ComputerName "PC-01" -Port 8080

Modules (.psm1)

Regrouper des fonctions dans un fichier MonOutil.psm1.

# Importation manuelle
Import-Module ".\MonOutil.psm1"

# Lister les commandes du module
Get-Command -Module MonOutil

# Auto-loading :
# Si le module est dans $env:PSModulePath, 
# PS le charge automatiquement si on appelle une fonction.

Execution Policy & Sécurité

Par défaut, Windows bloque les scripts (.ps1).

  • Restricted : Rien ne passe.
  • RemoteSigned : Scripts locaux OK, scripts internet doivent être signés.
  • Bypass : Open bar (Dangereux).
# Vérifier
Get-ExecutionPolicy

# Modifier (Scope CurrentUser recommandé)
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

5. Manipulation de Données

Interopérabilité et Formats.

CSV & JSON

Conversion instantanée Objet <-> Fichier.

# Export
Get-Process | Select Name, Id, CPU | Export-Csv "proc.csv" -NoTypeInformation
Get-Service | ConvertTo-Json | Out-File "services.json"

# Import (Devient immédiatement un objet manipulable)
$users = Import-Csv "users.csv"
Write-Host "Premier user : $($users[0].Nom)"

$config = Get-Content "config.json" | ConvertFrom-Json
Write-Host $config.ApiUrl

Appels API REST

Invoke-RestMethod parse automatiquement le JSON/XML.

$url = "https://api.github.com/users/microsoft/repos"
$repos = Invoke-RestMethod -Uri $url -Method Get

# On peut directement filtrer les résultats de l'API
$repos | Where-Object stargazers_count -gt 1000 | Select name, html_url
Indispensable pour l'orchestration Cloud moderne.

6. Administration Système Avancée

WMI, Jobs et Réseau.

WMI & CIM (Hardware/OS)

Accès bas niveau (BIOS, Disques physiques, Températures).

# La méthode moderne (CIM)
Get-CimInstance -ClassName Win32_OperatingSystem | Select LastBootUpTime

Get-CimInstance -ClassName Win32_LogicalDisk | 
    Where-Object DriveType -eq 3 | 
    Select DeviceID, FreeSpace, Size

Les Jobs (Tâches de fond)

Ne bloquez pas votre console pour un scan long.

# Démarrer un job
$job = Start-Job -ScriptBlock {
    Get-ChildItem -Path C:\ -Recurse -Filter *.log
}

# Vérifier l'état
Get-Job

# Récupérer les résultats
$logs = Receive-Job -Job $job -Keep

Commandes à Distance (WinRM)

Gérer 1 serveur comme 1000.

# 1. Session interactive (comme SSH)
Enter-PSSession -ComputerName "Srv-AD-01"

# 2. Exécution de masse (Invoke-Command)
# Exécute le script sur 3 serveurs EN PARALLÈLE
Invoke-Command -ComputerName "Srv1", "Srv2", "Srv3" -ScriptBlock {
    Get-Service "Spooler" | Restart-Service
}

7. Écosystème Entreprise

Active Directory, Azure & SQL.

Active Directory (RSAT)

# Création
New-ADUser -Name "J.Doe" -SamAccountName "jdoe" -Path "OU=HR,DC=lan"

# Audit : Comptes inactifs depuis 90 jours
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 | 
    Where-Object Enabled -eq $true | 
    Select Name, LastLogonDate

Azure PowerShell (Az)

Connect-AzAccount

# Gestion des ressources Cloud
New-AzResourceGroup -Name "ProjetL3" -Location "WestEurope"
Get-AzVM -Status | Where-Object PowerState -eq "VM running"
Azure Cloud Shell permet de faire ça directement dans le navigateur.

SQL Server

Exécuter des requêtes et récupérer des objets.

# Module SqlServer
$data = Invoke-Sqlcmd -ServerInstance "DB-SRV" -Database "Prod" -Query "SELECT * FROM Users"

# Export direct des résultats SQL vers CSV
$data | Export-Csv "export_sql.csv"

Le Registre Windows

Oubliez regedit.exe.

Pour PowerShell, le registre est un système de fichiers comme les autres.

Le concept de "PSDrive"

PowerShell monte les ruches principales comme des lecteurs.

# Lister les lecteurs disponibles
Get-PSDrive -PSProvider Registry

Naviguer : cd & ls

On se déplace dans le registre comme dans C:\.

# Changer de lecteur (Drive)
Set-Location HKLM: 
# Ou simplement : cd HKLM:

# Aller dans le dossier Run (Démarrage auto)
cd Software\Microsoft\Windows\CurrentVersion\Run

# Lister le contenu
Get-ChildItem # Ou : ls, dir

Lire et Modifier

Les clés sont des "Items", les valeurs sont des "ItemProperties".

# Lire une valeur spécifique
Get-ItemProperty -Path . -Name "SecurityHealth"

# Créer une entrée (Ex: Désactiver une feature)
New-ItemProperty -Path . -Name "7Z" -Value 1 -PropertyType DWORD

# Supprimer une entrée (Nettoyage malware ?)
Remove-ItemProperty -Path . -Name "MaliciousScript"

Attention : Nécessite une console Administrateur pour HKLM.

8. Bonus : UI

Interfaces Graphiques (WinForms)

Créer des petits outils GUI sans Visual Studio.

Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$form.Text = "Outil Admin"
$btn = New-Object System.Windows.Forms.Button
$btn.Text = "Cliquez-moi"
$btn.Add_Click({ [System.Windows.Forms.MessageBox]::Show("Bravo!") })
$form.Controls.Add($btn)
$form.ShowDialog()

Reporting HTML

Module PSWriteHTML (communauté).

New-HTML {
    New-HTMLTable -Title "Processus lourds" -DataTable (Get-Process | Select -First 10)
    New-HTMLChart -Title "CPU Usage" -Type Bar
} -FilePath "report.html" -Show

Bonus Bis : Modules intéressants

Oh My Posh

Rendre le terminal beau et informatif.

Affiche : Branche Git, Version .NET, Temps d'exécution, Erreurs.

winget install JanDeDobbeleer.OhMyPosh
Set-PoshPrompt -Theme atomic

Pester & Tests

Valider votre infrastructure automatiquement.

Pourquoi tester ?

Pester n'est pas que pour les développeurs.

C'est de l'Infrastructure as Code (IaC).

  • Compliance : Vérifier qu'un serveur respecte les normes de sécu.
  • Non-régression : "J'ai patché le serveur, est-ce que le site web répond toujours ?"
  • Syntaxe : Naturelle (Anglais).

On ne teste pas du code, on teste l'état de la machine.


Describe "Vérification du Serveur Web" {

    Context "Sécurité Réseau" {
        It "Le port 443 (HTTPS) doit être ouvert" {
            # Test réel de connexion
            $conn = Test-NetConnection -Port 443 -ComputerName "localhost"
            $conn.TcpTestSucceeded | Should -Be $true
        }
    }
}
        

Si tout est vert, le serveur est conforme. Si c'est rouge, alerte !

Le "Mocking"

Tester sans toucher à la Production.

Le Concept

Le Mocking remplace une commande réelle par une version simulée.

  • Sécurité : Évite de lancer accidentellement Remove-Item ou Stop-Service.
  • Simulation : Permet de tester des cas rares (ex: "Que se passe-t-il si le serveur ne répond pas ?").

Syntaxe : Mock & Assert


Describe "Script de Nettoyage" {
    
    # On 'Mock' la commande dangereuse.
    # Elle ne s'exécutera pas réellement.
    Mock Remove-Item { Write-Host "Fausse suppression !" }

    It "Doit tenter de supprimer les vieux fichiers" {
        # On lance le vrai script
        Invoke-NettoyageLogs -Path "C:\Logs"

        # On vérifie que le script a BIEN essayé de supprimer
        Assert-MockCalled Remove-Item -Times 1
    }
}
        
⚠️ Sans le Mock, le fichier aurait été réellement supprimé du disque !

Simuler des retours (Behavior)

Forcer une commande à renvoyer une valeur spécifique pour tester la logique.

# On force Get-Date à renvoyer une date fixe
# pour tester un calcul d'expiration
Mock Get-Date { return [datetime]"2025-01-01" }

$resultat = MonScript-CalculAge
$resultat | Should -Be 365

Résumé du Cours

  • PowerShell est Orienté Objet (Pipeline riche).
  • Il connecte tout : OS, AD, Cloud, API, SQL.
  • L'avenir est PowerShell 7 (Core) et VS Code.
  • L'automatisation est la compétence clé de l'ingénieur système.

Prochaine étape : Pratiquer sur des VMs !