Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 1118 minIntermédiaire

Automatiser Windows Server et Active Directory

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • installer des rôles et des mises à jour sur Windows Server ;
  • créer un partage et ses droits NTFS selon AGDLP ;
  • gérer des réservations DHCP et des enregistrements DNS ;
  • créer des OU, des groupes et des comptes Active Directory ;
  • choisir entre un module win_* et un script PowerShell.

2 exercices corrigés

Automatiser Windows Server avec Ansible, c'est installer ses rôles, gérer ses partages, ses droits NTFS, son DHCP et son DNS, et créer les comptes Active Directory à partir de listes versionnées, avec les modules des collections ansible.windows et microsoft.ad. Ce chapitre suppose que la connexion WinRM ou SSH fonctionne (chapitre 10) ; il automatise le serveur de fichiers, le DHCP et le DNS des contrôleurs, puis le cycle de vie des comptes de Sorbier.

Exemple : le serveur de fichiers

Le playbook fichiers.yml installe les rôles du serveur de fichiers sur srv-fichiers, crée le dossier et le partage de la comptabilité avec les droits de la stratégie AGDLP du cours Windows Server, ouvre le port de l'agent de supervision et installe les mises à jour de sécurité.

yaml
---
- name: Configurer le serveur de fichiers
  hosts: fichiers

  tasks:
    - name: Installer le serveur de fichiers et le gestionnaire de ressources
      ansible.windows.win_feature:
        name:
          - FS-FileServer
          - FS-Resource-Manager
        include_management_tools: true
        state: present
      register: roles_fichiers

    - name: Redémarrer si l'installation l'exige
      ansible.windows.win_reboot:
      when: roles_fichiers.reboot_required

    - name: Créer le dossier de la comptabilité
      ansible.windows.win_file:
        path: D:\Partages\Compta
        state: directory

    - name: Donner la modification au groupe DL_Compta_M (NTFS)
      ansible.windows.win_acl:
        path: D:\Partages\Compta
        user: SORBIER\DL_Compta_M
        rights: Modify
        type: allow
        inherit: ContainerInherit, ObjectInherit
        state: present

    - name: Donner la lecture au groupe DL_Compta_L (NTFS)
      ansible.windows.win_acl:
        path: D:\Partages\Compta
        user: SORBIER\DL_Compta_L
        rights: ReadAndExecute
        type: allow
        inherit: ContainerInherit, ObjectInherit
        state: present

    - name: Partager le dossier
      ansible.windows.win_share:
        name: Compta
        path: D:\Partages\Compta
        description: Partage de la comptabilité
        change: SORBIER\DL_Compta_M
        read: SORBIER\DL_Compta_L
        list: false
        state: present

    - name: Autoriser l'agent de supervision depuis srv-journaux
      ansible.windows.win_firewall_rule:
        name: Agent de supervision (srv-journaux)
        localport: "10050"
        protocol: tcp
        direction: in
        action: allow
        remoteip: 192.168.10.180
        profiles: domain
        state: present
        enabled: true

    - name: Installer les mises à jour critiques et de sécurité
      ansible.windows.win_updates:
        category_names:
          - CriticalUpdates
          - SecurityUpdates
        reboot: true
  • win_feature renvoie reboot_required : le redémarrage n'a lieu que si Windows le demande.
  • win_acl ajoute une entrée à la liste de contrôle d'accès NTFS ; inherit la propage aux sous-dossiers et aux fichiers. Les droits réels passent par les groupes de domaine local, comme le veut AGDLP ; les autorisations du partage reprennent les mêmes groupes.
  • list: false active l'énumération basée sur l'accès : un utilisateur ne voit pas le partage s'il n'y a pas accès.
  • win_updates avec reboot: true redémarre autant de fois que nécessaire et reprend l'installation. Pour un contrôleur de domaine, on traite les deux contrôleurs l'un après l'autre (serial: 1) pour que le domaine reste toujours disponible.
  • La règle du pare-feu Windows n'ouvre le port 10050 qu'au serveur de supervision, et seulement sur le profil domaine ; l'agent Zabbix lui-même est expliqué dans le cours Supervision.

Les noms des fonctionnalités sont ceux de Get-WindowsFeature (colonne Name) : AD-Domain-Services, DHCP, DNS, FS-FileServer, RSAT-AD-Tools…

Exemple : DHCP et DNS sur les contrôleurs

Une réservation DHCP pour la nouvelle imprimante des ressources humaines, dans l'étendue du VLAN 10 (192.168.10.64) :

yaml
    - name: Réserver l'adresse de l'imprimante des RH
      ansible.windows.win_dhcp_lease:
        type: reservation
        scope_id: 192.168.10.64
        ip: 192.168.10.111
        mac: 00-1B-A9-4C-21-80
        reservation_name: IMP-RH
        description: Imprimante RH
        state: present

Un enregistrement DNS pour le serveur de recette créé au chapitre 13 :

yaml
    - name: Déclarer srv-recette dans la zone du domaine
      ansible.windows.win_dns_record:
        name: srv-recette
        type: A
        value: 192.168.21.186
        zone: ad.sorbier.example
        state: present

Une étendue DHCP, qu'aucun module ne gère : on passe par win_powershell, en écrivant soi-même le test d'idempotence. L'objet $Ansible permet au script de dire s'il a modifié quelque chose. Ici, l'étendue du VLAN 50 de la téléphonie, 192.168.10.160/28, passerelle .174 :

yaml
    - name: Créer l'étendue DHCP de la téléphonie si elle n'existe pas
      ansible.windows.win_powershell:
        parameters:
          ScopeId: 192.168.10.160
          Debut: 192.168.10.161
          Fin: 192.168.10.173
          Masque: 255.255.255.240
          Passerelle: 192.168.10.174
        script: |
          param($ScopeId, $Debut, $Fin, $Masque, $Passerelle)
          $ErrorActionPreference = 'Stop'
          if (Get-DhcpServerv4Scope -ScopeId $ScopeId -ErrorAction SilentlyContinue) {
              $Ansible.Changed = $false
              return
          }
          Add-DhcpServerv4Scope -Name 'VLAN50-TELEPHONIE' -StartRange $Debut -EndRange $Fin `
              -SubnetMask $Masque -LeaseDuration 8.00:00:00 -State Active
          Set-DhcpServerv4OptionValue -ScopeId $ScopeId -Router $Passerelle

Ces tâches vont dans un play qui vise srv-ad seulement (hosts: srv-ad) : le DNS est répliqué par l'annuaire, et l'étendue doit ensuite être ajoutée à la relation de basculement DHCP avec srv-ad2, configurée dans le cours Windows Server.

Créer des comptes Active Directory

C'est un usage typique d'Ansible chez Sorbier : chaque printemps, une vingtaine de saisonniers rejoignent la logistique. (Automatiser la création des comptes ne dispense pas de protéger l'annuaire : mots de passe, comptes de service et durcissement sont dans le cours Sécurité de l'Active Directory.) La liste est un fichier de variables versionné, vars/arrivees.yml :

yaml
---
arrivees:
  - login: lgirard
    prenom: Lucas
    nom: Girard
    service: Logistique
    groupes: [GG_Logistique]
  - login: eberard
    prenom: Élise
    nom: Bérard
    service: Commercial
    groupes: [GG_Commerciaux]

Le playbook comptes_ad.yml crée les OU et les groupes s'ils manquent, puis les comptes. Il vise un seul contrôleur, puisque l'annuaire se réplique :

yaml
---
- name: Créer les comptes Active Directory des arrivées
  hosts: srv-ad
  vars_files:
    - vars/arrivees.yml
  vars:
    base_ou: OU=Sorbier,DC=ad,DC=sorbier,DC=example

  tasks:
    - name: Garantir l'OU de chaque service
      microsoft.ad.ou:
        name: "{{ item }}"
        path: OU=Utilisateurs,{{ base_ou }}
        protect_from_deletion: true
        state: present
      loop: "{{ arrivees | map(attribute='service') | unique }}"

    - name: Garantir les groupes globaux
      microsoft.ad.group:
        name: "{{ item }}"
        scope: global
        category: security
        path: OU=Groupes,{{ base_ou }}
        state: present
      loop: "{{ arrivees | map(attribute='groupes') | flatten | unique }}"

    - name: Lister les comptes qui existent déjà
      microsoft.ad.object_info:
        ldap_filter: (&(objectClass=user)(objectCategory=person))
        search_base: OU=Utilisateurs,{{ base_ou }}
        properties:
          - sAMAccountName
      register: comptes_existants

    - name: Créer ou mettre à jour chaque compte
      microsoft.ad.user:
        name: "{{ item.prenom }} {{ item.nom }}"
        firstname: "{{ item.prenom }}"
        surname: "{{ item.nom }}"
        sam_account_name: "{{ item.login }}"
        upn: "{{ item.login }}@ad.sorbier.example"
        path: OU={{ item.service }},OU=Utilisateurs,{{ base_ou }}
        password: "{{ lookup('ansible.builtin.password', 'identifiants/' ~ item.login ~ '.txt', length=16, chars=['ascii_letters', 'digits', '!?#%+']) }}"
        update_password: on_create
        password_expired: "{{ (logins_existants is not contains(item.login)) | ternary(true, omit) }}"
        groups:
          add: "{{ item.groupes }}"
        enabled: true
        state: present
      loop: "{{ arrivees }}"
      loop_control:
        label: "{{ item.login }}"
      vars:
        logins_existants: "{{ comptes_existants.objects | map(attribute='sAMAccountName') | list }}"
      no_log: true

Les points à comprendre :

  • Les boucles calculées. arrivees | map(attribute='service') | unique donne la liste des services sans doublon ; map(attribute='groupes') | flatten | unique aplatit les listes de groupes de chaque personne en une seule liste.
  • Le mot de passe initial. Le lookup password génère un mot de passe aléatoire de 16 caractères et l'enregistre dans identifiants/<login>.txt, sur le nœud de contrôle : relancé, le playbook relit le même fichier au lieu d'en générer un autre. update_password: on_create ne pose le mot de passe qu'à la création du compte.
  • Changer le mot de passe à la première connexion. password_expired n'est mis à true que pour les comptes absents de l'annuaire avant l'exécution : le test contains vérifie si la liste logins_existants contient le login, et le filtre ternary choisit entre deux valeurs. Pour les comptes existants, la valeur spéciale omit retire l'option : le module ne touche pas à ce réglage, et un salarié qui a déjà changé son mot de passe n'est pas forcé de recommencer.
  • groups.add ajoute les groupes sans retirer ceux que le compte a déjà ; set remplacerait toute la liste.
  • no_log: true empêche le mot de passe d'apparaître dans la sortie (en 2.22, le masquage automatique le cacherait déjà, mais no_log couvre aussi les journaux et les versions antérieures).

Pour le départ d'un salarié, la même logique s'applique : une liste departs et une tâche microsoft.ad.user avec enabled: false et un déplacement vers une OU d'archives, plutôt qu'une suppression immédiate (cycle de vie des comptes dans le cours Windows Server).

Exercices

Exercice 1 sur 2 Le module ou le script ? Réussi À revoir

Pour chaque besoin, donne le module à utiliser, ou explique pourquoi il faut win_powershell.

  1. Installer le rôle DHCP et ses outils d'administration sur srv-ad2.
  2. Vérifier que le service « Spouleur d'impression » (Spooler) est arrêté et désactivé sur les contrôleurs de domaine.
  3. Créer le groupe de domaine local DL_RH_M dans l'OU Groupes.
  4. Ajouter un enregistrement CNAME intranet vers srv-web.ad.sorbier.example.
  5. Configurer l'option DHCP « serveur NTP » (option 042) sur une étendue.
Voir la réponseMasquer la réponse de l'exercice 1
  1. ansible.windows.win_feature avec name: DHCP, include_management_tools: true.
  2. ansible.windows.win_service avec name: Spooler, state: stopped, start_mode: disabled. Désactiver le spouleur sur les contrôleurs de domaine est une recommandation de durcissement classique : il a été la cible de vulnérabilités graves.
  3. microsoft.ad.group avec scope: domainlocal, category: security, path: OU=Groupes,OU=Sorbier,DC=ad,DC=sorbier,DC=example.
  4. ansible.windows.win_dns_record avec name: intranet, type: CNAME, value: srv-web.ad.sorbier.example, zone: ad.sorbier.example.
  5. Aucun module de la collection ne gère les options d'étendue : win_powershell avec Get-DhcpServerv4OptionValue pour tester, puis Set-DhcpServerv4OptionValue -ScopeId … -OptionId 42 -Value …, et $Ansible.Changed = $false quand la valeur est déjà la bonne.

Tu avais trouvé ?

Exercice 2 sur 2 Un départ Réussi À revoir

Lucas Girard (lgirard) quitte Sorbier à la fin de la saison. Écris la tâche qui désactive son compte, le déplace dans l'OU OU=Archives,OU=Sorbier,DC=ad,DC=sorbier,DC=example et le retire du groupe GG_Logistique, sans supprimer le compte.

Voir la réponseMasquer la réponse de l'exercice 2
yaml
    - name: Désactiver et archiver le compte de Lucas Girard
      microsoft.ad.user:
        identity: lgirard
        path: OU=Archives,OU=Sorbier,DC=ad,DC=sorbier,DC=example
        enabled: false
        groups:
          remove:
            - GG_Logistique
        state: present

identity retrouve le compte par son sAMAccountName, quel que soit son emplacement ; path le déplace. Garder le compte désactivé quelques mois permet de retrouver ses droits et de transférer ses fichiers ; la suppression vient ensuite, selon la procédure de départ. Pour un traitement en série, on met les départs dans une liste et on boucle.

Tu avais trouvé ?

Chapitre terminé !

Fais les 2 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Automatiser les équipements réseau : Cisco et pfSenseRevoir le sommaire du cours