Aller au contenu principal
adminsysAutomatiser : PowerShell et scripts Linux

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.
Où on va
« Plusieurs techniciens interviennent quotidiennement sur le parc. Chacun applique ses propres habitudes. » C'est la dernière plainte de NeoLink, et c'est celle qui explique toutes les autres : sans procédure exécutable, la procédure n'existe pas. Ce chapitre traite de l'automatisation, non pas comme un gain de temps, mais comme le seul moyen de rendre une opération reproductible. On y voit PowerShell côté Windows, bash et cron côté Linux, et surtout ce qu'un script doit garantir pour être digne de confiance.

Pourquoi automatiser

Définition

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.

RaisonPortée
Gagner du tempsréelle, mais la moins importante
Réduire les erreursun script ne se trompe pas de case à cocher
Standardiser les opérationsla raison décisive chez NeoLink
Simplifier les tâches répétitivesconséquence des précédentes
Le vrai apport est la reproductibilité
Une procédure écrite dans un document dérive : chacun l'interprète, l'adapte, en saute une étape un jour de rush. Une procédure écrite dans un script s'exécute à l'identique, par tout le monde, y compris à trois heures du matin.
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

Définition

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"
Ces blocs ne s'exécutent pas dans cette page
La plateforme n'exécute que Python et SQL dans le navigateur. Les extraits PowerShell et bash sont donnés à lire et à reproduire sur une machine, exactement comme le MicroPython du parcours Arduino.
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.

Terminal3 commandes
# Les cinq processus qui consomment le plus de memoire
$Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 5 Name, WorkingSet
# Les services arretes dont le demarrage est automatique : une anomalie
$Get-Service | Where-Object { $_.StartType -eq 'Automatic' -and $_.Status -ne 'Running' }
# Exporter vers un fichier exploitable
$Get-Service | Where-Object { $_.Status -eq 'Stopped' } | Export-Csv services.csv -NoTypeInformation
Objets contre texte, la différence pratique
Sous Linux, une commande rend du texte, et l'on découpe ce texte avec 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.

BesoinCmdlet
Créer un compteNew-ADUser
Chercher des comptesGet-ADUser -Filter
Modifier un attributSet-ADUser
Ajouter à un groupeAdd-ADGroupMember
DésactiverDisable-ADAccount
Déplacer dans une OUMove-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
La requête qui répond à la plainte de la direction
« Il devient compliqué de vérifier que tous les accès d'un partant ont bien été supprimés. » La seconde requête ci-dessus produit, en une commande, la liste des comptes actifs et inutilisés depuis trois mois.
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.

main.py
Sortie
>_ Prêt à exécuter…
Les trois cas que les scripts de création oublient
Les accents, qui produisent des identifiants illisibles ou refusés. Les homonymes, qui font échouer la création du second compte, ou pire, écrasent le premier. Et la longueur maximale de 20 caractères, qui tronque silencieusement et crée des collisions inattendues.
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
Lire une ligne de cron
De gauche à droite : minute, heure, jour du mois, mois, jour de la semaine. L'étoile signifie « toutes les valeurs ».
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.

Les trois garanties

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.

Un script est plus dangereux qu'un humain
Un technicien qui se trompe crée un mauvais compte. Un script qui se trompe en crée trois cents, ou en désactive trois cents, en quelques secondes et sans hésiter.
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

  1. Écris la règle avant le script. Nommage, cas particuliers, ce qui se passe si l'objet existe déjà.
  2. Éprouve la logique sur des données de test qui contiennent les cas tordus : accents, homonymes, noms trop longs.
  3. Commence par une simulation sur un périmètre réduit, et relis la sortie ligne à ligne.
  4. Journalise chaque action avec sa date, son auteur et son résultat.
  5. Rends le script idempotent : il doit pouvoir être relancé sans dégât.
  6. Automatise la détection, fais valider la destruction.
  7. 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.

Automatiser : PowerShell et scripts Linux | Plateforme ETS