Automatiser : PowerShell et scripts Linux
Ce que ce chapitre apporte
- Expliquer ce que l'automatisation apporte au-delà du gain de temps.
- Lire un script PowerShell : cmdlets, pipeline, variables, conditions, boucles.
- Reconnaître les cmdlets d'administration de l'annuaire.
- Automatiser la création de comptes à partir d'un fichier, avec règle de nommage.
- Écrire un script de maintenance Linux et le planifier.
- Rendre un script sûr : mode simulation, journalisation, idempotence.
Pourquoi automatiser
L'automatisation est l'exécution d'une tâche sans intervention humaine permanente. Un script en est le support : une suite d'instructions exécutées par un interpréteur.
Le document du bloc en donne quatre raisons. Elles ne se valent pas.
| Raison | Portée |
|---|---|
| Gagner du temps | réelle, mais la moins importante |
| Réduire les erreurs | un script ne se trompe pas de case à cocher |
| Standardiser les opérations | la raison décisive chez NeoLink |
| Simplifier les tâches répétitives | conséquence des précédentes |
Et elle se relit. « Comment crée-t-on un compte ici ? » a alors une réponse unique et vérifiable : le script.
PowerShell, les bases
PowerShell est le langage de scripting et d'administration de Microsoft. Sa particularité tient en un point : il manipule des objets, pas du texte.
Une commande PowerShell s'appelle une cmdlet et suit toujours la forme Verbe-Nom : Get-Service, New-ADUser, Set-Content. La convention rend le vocabulaire devinable.
# Une variable commence par $
$Nom = "Dupont"
$Age = 22
# Une condition. Les operateurs sont textuels : -gt, -lt, -eq, -ne
if ($Age -gt 18) {
Write-Host "Majeur"
} else {
Write-Host "Mineur"
}
# Une boucle sur une collection
$Utilisateurs = @("marie", "marc", "melanie")
foreach ($User in $Utilisateurs) {
Write-Host "Traitement de $User"
}
# Une fonction
function Get-EspaceLibre {
param([string]$Lecteur = "C")
$Disque = Get-PSDrive $Lecteur
return [math]::Round($Disque.Free / 1GB, 2)
}
Write-Host "Espace libre : $(Get-EspaceLibre 'C') Go"
Les blocs Python de ce chapitre, eux, tournent : ils servent à éprouver la logique d'un script, ce qui est la partie qu'on rate le plus souvent.
Le pipeline
C'est la construction qui donne sa puissance au langage : la sortie d'une cmdlet devient l'entrée de la suivante, sous forme d'objets et non de texte.
awk ou cut pour en extraire une colonne. Le script casse le jour où la mise en forme change.En PowerShell,
$_.Status désigne une propriété de l'objet. Il n'y a rien à découper, et rien à casser. C'est ce qui rend les scripts d'administration Windows plus robustes qu'on ne s'y attend.
Administrer l'annuaire par script
Le module Active Directory fournit les cmdlets qui recouvrent tout le cycle de vie d'un compte.
| Besoin | Cmdlet |
|---|---|
| Créer un compte | New-ADUser |
| Chercher des comptes | Get-ADUser -Filter |
| Modifier un attribut | Set-ADUser |
| Ajouter à un groupe | Add-ADGroupMember |
| Désactiver | Disable-ADAccount |
| Déplacer dans une OU | Move-ADObject |
# Creer un compte dans la bonne unite d'organisation
New-ADUser -Name "Marie Dupont" `
-SamAccountName "m.dupont" `
-UserPrincipalName "m.dupont@neolink.local" `
-Path "OU=Comptabilite,OU=Utilisateurs,DC=neolink,DC=local" `
-AccountPassword (Read-Host -AsSecureString "Mot de passe") `
-ChangePasswordAtLogon $true `
-Enabled $true
Add-ADGroupMember -Identity "GG_Comptabilite" -Members "m.dupont"
# Les comptes inactifs depuis plus de 90 jours : la revue que personne ne fait
$Limite = (Get-Date).AddDays(-90)
Get-ADUser -Filter { LastLogonDate -lt $Limite -and Enabled -eq $true } `
-Properties LastLogonDate |
Select-Object Name, SamAccountName, LastLogonDate |
Export-Csv comptes-inactifs.csv -NoTypeInformation
Ce n'est pas un exploit technique : c'est ce que permet un annuaire correctement alimenté. Sans annuaire, la question n'avait pas de réponse. Avec un annuaire et une cmdlet, elle en a une, tous les lundis matin.
La logique d'un script de création de comptes
La partie délicate n'est pas la cmdlet, c'est la règle de nommage et ce qu'elle doit gérer : les accents, les homonymes, la longueur maximale d'un identifiant. C'est cette logique que le bloc Python ci-dessous éprouve, avant de l'écrire en PowerShell.
Ces trois cas n'apparaissent jamais lors du test avec « Jean Dupont ». Ils apparaissent en production, la semaine de la rentrée.
Côté Linux
Les mêmes besoins, avec d'autres outils. Un script bash, planifié par cron.
#!/bin/bash
# Surveillance de l'espace disque, alerte au-dela d'un seuil
SEUIL=85
DESTINATAIRE="admin@neolink.local"
df -h --output=pcent,target | tail -n +2 | while read pourcent point; do
valeur=${pourcent%\%}
valeur=${valeur// /}
if [ "$valeur" -ge "$SEUIL" ]; then
echo "$(date '+%F %T') ALERTE $point est a ${valeur}%" >> /var/log/espace.log
echo "$point occupe a ${valeur}%" | mail -s "Disque plein" "$DESTINATAIRE"
fi
done
La planification se lit dans cinq champs : minute, heure, jour du mois, mois, jour de la semaine.
# m h jm mois js commande
0 6 * * * /opt/scripts/espace-disque.sh
0 2 * * 0 /opt/scripts/sauvegarde-complete.sh
0 2 * * 1-6 /opt/scripts/sauvegarde-differentielle.sh
*/15 * * * * /opt/scripts/verifie-services.sh
La deuxième ligne se lit donc : à 2 h 00, tous les jours du mois, tous les mois, le dimanche seulement. C'est la sauvegarde complète hebdomadaire du chapitre 5, et les six lignes suivantes en sont les différentielles.
Rendre un script digne de confiance
Un script qui modifie l'annuaire ou supprime des fichiers mérite trois garanties. Aucune n'est optionnelle.
Mode simulation : le script sait afficher ce qu'il ferait, sans le faire. En PowerShell, -WhatIf sur les cmdlets qui le supportent.
Journalisation : chaque action écrite dans un fichier daté, avec qui, quoi, et le résultat. C'est ce qui permet de comprendre après coup, et c'est la traçabilité du chapitre 3.
Idempotence : exécuter deux fois le script produit le même état qu'une fois. Un script qui ajoute un utilisateur à un groupe doit vérifier qu'il n'y est pas déjà, plutôt que d'échouer ou de dupliquer.
D'où la règle : tout script destructeur commence par une exécution en simulation, sur un périmètre réduit, dont on relit la sortie. Et il journalise, pour qu'on puisse défaire.
Exercices type
Que fait `Get-Service | Where-Object { $_.Status -eq 'Stopped' }` ?
Get-Service produit la liste des services sous forme d'objets. Le pipeline la transmet à Where-Object, qui filtre.
$_ désigne l'objet en cours de traitement, et $_.Status sa propriété d'état. La commande rend donc les services arrêtés.
Le point de méthode : on n'a rien découpé ni analysé textuellement. Si le format d'affichage de Get-Service change demain, le filtre continue de fonctionner, parce qu'il porte sur une propriété et non sur une colonne.
Deux salariés s'appellent Dupont. Que doit faire le script de création ?
Détecter la collision avant de créer, et dériver un identifiant distinct : m.dupont puis m.dupont2.
Ce qu'il ne doit surtout pas faire : échouer en laissant la moitié du traitement fait, ou créer un doublon qui rendra les droits impossibles à suivre.
Deux précautions supplémentaires que montre le bloc Python : normaliser les accents, car Mélanie ne doit pas produire un identifiant différent selon l'encodage ; et respecter la limite de 20 caractères, en tronquant avant d'ajouter le suffixe, sinon le suffixe se fait couper.
Pourquoi journaliser un script qui fonctionne bien ?
Parce que la question ne se pose jamais pendant qu'il fonctionne bien.
Elle se pose trois semaines plus tard : « qui a désactivé ce compte ? », « quand ce dossier a-t-il été supprimé ? », « le script a-t-il tourné dimanche ? ». Sans journal, la réponse est « on ne sait pas ».
Un journal utile contient la date, le compte qui a exécuté, l'action tentée, le résultat, et les éléments concernés. Il se conserve avec une durée décidée, comme l'audit du chapitre 3.
Qu'est-ce qu'un script idempotent, et pourquoi est-ce important ?
Un script dont la deuxième exécution produit le même état que la première.
Contre-exemple : un script qui ajoute une ligne à un fichier de configuration. Exécuté trois fois, il produit trois lignes, et une configuration invalide.
Version idempotente : vérifier si la ligne existe déjà, et ne l'ajouter que sinon.
Cela compte parce qu'un script est relancé plus souvent qu'on ne le prévoit : après une interruption, par erreur, ou parce que personne ne sait s'il a déjà tourné. L'idempotence rend la relance sans danger, et c'est ce qui permet d'automatiser sereinement.
Lire `0 2 * * 1-6 /opt/scripts/sauvegarde-differentielle.sh`
À 2 h 00, tous les jours du mois, tous les mois, du lundi au samedi.
Combinée à la ligne 0 2 * * 0 qui lance la sauvegarde complète le dimanche, on obtient exactement la politique du chapitre 5 : une complète hebdomadaire, six différentielles.
Une vérification à faire : que les deux tâches ne se chevauchent pas, et que la fenêtre de 2 h suffit à la complète. Sinon, la différentielle du lundi démarre pendant que la complète du dimanche tourne encore.
Faut-il automatiser la suppression des comptes inactifs ?
La détection, oui, et sans hésiter : c'est une requête, elle est sans risque, et elle produit la liste que personne ne prend le temps d'établir.
La suppression, non. Une suppression automatique de comptes est irréversible et se trompera un jour : un congé de longue durée, un compte de service qui n'ouvre jamais de session, un salarié en mission.
La démarche raisonnable est graduée : détecter automatiquement, désactiver après validation humaine, et supprimer après un délai de conservation, une fois les données personnelles traitées conformément au chapitre 6.
Le principe général : automatiser ce qui se vérifie, faire valider ce qui se défait mal.
La méthode
- Écris la règle avant le script. Nommage, cas particuliers, ce qui se passe si l'objet existe déjà.
- Éprouve la logique sur des données de test qui contiennent les cas tordus : accents, homonymes, noms trop longs.
- Commence par une simulation sur un périmètre réduit, et relis la sortie ligne à ligne.
- Journalise chaque action avec sa date, son auteur et son résultat.
- Rends le script idempotent : il doit pouvoir être relancé sans dégât.
- Automatise la détection, fais valider la destruction.
- Range le script quelque part de partagé et versionné. Un script sur le poste d'un technicien n'est pas une procédure d'entreprise.
En résumé
- L'automatisation apporte surtout la reproductibilité : une procédure écrite dans un script ne dérive pas.
- PowerShell manipule des objets, pas du texte. Cmdlets en
Verbe-Nom, composées par le pipeline. - Le module Active Directory couvre tout le cycle de vie :
New-ADUser,Get-ADUser,Add-ADGroupMember,Disable-ADAccount. - Une règle de nommage doit gérer les accents, les homonymes et la longueur maximale.
- Sous Linux, bash et cron en cinq champs : minute, heure, jour du mois, mois, jour de la semaine.
- Trois garanties : simulation, journalisation, idempotence.
- Un script se trompe plus vite et plus largement qu'un humain. Il se teste en conséquence.
Et ensuite ? Il reste une question à laquelle rien de tout cela ne répond : comment prouver qu'un serveur est bien celui qu'il prétend être, et comment protéger ce qui circule entre deux sites ? Le dernier chapitre traite des certificats, de TLS et des accès distants.