Logo

TL;DR:

Quick-howto sans explications pour effectuer le déploiement d'un environnement AD minimal pour des tests, constitué de VMs: 3 Domain Controllers, une forêt, 3 domaines, une machine windows, une machine Linux.

Concepts:

Active Directory, forêts, domain, join domain.

Outils:

Windows Server, PowerShell, Ubuntu.

Sommaire

Description du lab

Procédure de déploiement

Client Windows

Client Linux

Peuplement du domaine

Contexte et prérequis

On dispose d'un homelab faisant tourner des machines virtuelles KVM/libvirt (QEMU).

Les templates ont été créés selon cette procédure.

Description du lab

Les 5 VM suivantes sont créées par clonage à partir des templates, puis démarrées:

lab_dc1.lab.local: un contrôleur de domaine pour le domaine lab.local.

lab_dc2.amchit.lab.local: un contrôleur de domaine pour le domaine amchit.lab.local.

lab_dc3.jounieh.lab.local: un contrôleur de domaine pour le domaine jounieh.lab.local.

lab_batroun.lab.local: un serveur Windows qui sera membre du domaine lab.local.

lab_cedar.lab.local: un serveur Linux qui sera membre du domaine lab.local.

Par commodité je nomme les VM avec le fqdn qui leur sera attribué, en ajoutant juste le préfixe "lab_" devant pour les regrouper dans la liste car virt-manager a une interface très rudimentaire.

un lab AD en cinq VM, qui démarre sous KVM/libvirt.
(celle qui boote vite et consomme peu de CPU c'est le Linux)

amchit.lab.local et jounieh.lab.local sont deux domaines de la forêt lab.local:

(image générée par IA)

Plan d'adressage:

serveur IP
dc1.lab.local 192.168.122.101
dc2.amchit.lab.local 192.168.122.102
dc3.jounieh.lab.local 192.168.122.103
batroun.lab.local 192.168.122.104
cedar.lab.local 192.168.122.105

La procédure qui suit consiste à déployer tout ça.

Procédure de déploiement

Ajouter les adresses ip dans /etc/hosts sur l'hôte:

# Lab AD
192.168.122.101 dc1 lab dc1.lab.local
192.168.122.102 dc2 amchit dc2.amchit.lab.local
192.168.122.103 dc3 jounieh dc3.jounieh.lab.local
192.168.122.104 batroun batroun.lab.local
192.168.122.105 cedar cedar.lab.local
1. contrôleur de domaine dc1.lab.local

Dans une session PowerShell, appliquer la conf IP souhaitée:

PS> New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.122.101 -PrefixLength 24 -DefaultGateway 192.168.122.1
PS> Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 192.168.122.1
PS> Rename-Computer -NewName "dc1" -Restart

Le serveur redémarre et le certificat RDP change.

Après le reboot, configurer le domaine:

PS> Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
PS> Install-ADDSForest -DomainName "lab.local" -DomainNetbiosName "LAB" -InstallDNS:$true -Force
SafeModeAdministratorPassword: *********
Confirm SafeModeAdministratorPassword: *********

Le serveur redémarre et le certificat RDP change une nouvelle fois.

Après le reboot, vérifier:

PS> Get-ADForest
PS> Get-ADDomain
PS> nslookup lab.local
2. contrôleur de domaine dc2.amchit.lab.local

Dans une session PowerShell, appliquer la conf IP souhaitée:

PS> New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.122.102 -PrefixLength 24 -DefaultGateway 192.168.122.1
PS> Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 192.168.122.101
PS> Rename-Computer -NewName "dc2" -Restart

Attention:

Ici on met l'adresse du contrôleur de domaine dc1 comme DNS (le serveur doit pouvoir localiser la forêt existante, et donc utiliser temporairement le DNS du premier DC).
Le serveur redémarre et le certificat RDP change.

Après le reboot, configurer le domaine:

PS> Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
PS> $cred = Get-Credential
Entrer le credential LAB\Administrator
PS> Install-ADDSDomain -NewDomainName "amchit" -ParentDomainName "lab.local" -DomainType ChildDomain -InstallDNS:$true -Credential $cred -Force
SafeModeAdministratorPassword: *********
Confirm SafeModeAdministratorPassword: *********

Le serveur redémarre et le certificat RDP change une nouvelle fois.

Vérifications après le reboot:

PS> Get-ADForest
PS> Get-ADDomain
PS> repadmin /replsummary
PS> repadmin /showrepl
PS> dcdiag /test:dns
PS> nslookup lab.local
PS> nslookup amchit.lab.local
3. contrôleur de domaine dc3.jounieh.lab.local

Dans une session PowerShell, appliquer la conf IP souhaitée:

PS> New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.122.103 -PrefixLength 24 -DefaultGateway 192.168.122.1
PS> Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 192.168.122.101
PS> Rename-Computer -NewName "dc3" -Restart

Attention:

Ici on met l'adresse du contrôleur de domaine dc1 comme DNS.
Le serveur redémarre et le certificat RDP change.

Après le reboot, configurer le domaine:

PS> Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
PS> $cred = Get-Credential
Entrer le credential LAB\Administrator
PS> Install-ADDSDomain -NewDomainName "jounieh" -ParentDomainName "lab.local" -DomainType ChildDomain -InstallDNS:$true -Credential $cred -Force
SafeModeAdministratorPassword: *********
Confirm SafeModeAdministratorPassword: *********

Le serveur redémarre et le certificat RDP change une nouvelle fois.

Vérifications après le reboot:

PS> Get-ADForest
PS> Get-ADDomain
PS> repadmin /replsummary
PS> repadmin /showrepl
PS> dcdiag /test:dns
PS> nslookup lab.local
PS> nslookup jounieh.lab.local
4. machine cliente AD batroun.lab.local (Windows)

Cette machine Windows Server va être membre du domaine lab.local (dc1).

Ouvrir une session powershell:

PS> Rename-Computer -NewName "batroun" -Restart
PS> New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.122.104 -PrefixLength 24 -DefaultGateway 192.168.122.1
PS> Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 192.168.122.101
PS> $Domain = "lab.local"
PS> $User   = "LAB\Administrator"
PS> $Pass   = ConvertTo-SecureString "<mot_de_passe>" -AsPlainText -Force
PS> $Cred   = New-Object System.Management.Automation.PSCredential($User, $Pass)
PS> Add-Computer -DomainName $Domain -Credential $Cred -Restart
Note:

Remplacer <mot_de_passe> par le vrai mot de passe :-)
Cet exemple montre une autre façon de renseigner l'objet $Cred, de manière non-interactive, mais devant en contrepartie faire figurer un mot de passe en clair dans une commande.

Vérification:

Sur la DSA du domain controller: la machine cliente est enregistrée

Sur la machine cliente, se connecter en tant que lab\administrator.

PS C:\Users\Administrator.LAB> whoami
lab\administrator
5. machine cliente AD cedar.lab.local (Linux)

Cette machine Linux va aussi être membre du domaine lab.local (dc1).

Sur un Linux récent, la méthode recommandée consiste à utiliser sssd (realmd, Kerberos). Winbind est toujours supporté, mais il est plutôt réservé aux besoins Samba avancés (serveur de fichiers, contrôleur de domaine, etc.).

Ouvrir une session SSH:

# resolvectl status

==> Le serveur doit utiliser le(s) serveur(s) DNS du domaine AD à joindre (dans le cadre du homelab = le domain controller dc1). Si ce n'est pas le cas, modifier et appliquer la configuration DNS cliente.

# apt update
# apt install realmd sssd sssd-tools libnss-sss libpam-sss adcli samba-common-bin oddjob oddjob-mkhomedir packagekit krb5-user
Note:

Lors de l'installation de krb5-user, une tui demande le nom du realm pour l'authent Kerberos. Je mets le nom de mon domaine AD: lab.local. (Sinon realmd le renseignera plus tard)

Ensuite, la tui demande les serveurs associés au realm. Je mets le nom de mon DC: dc1.

Vérifier que le domaine est détecté:

# realm discover lab.local
lab.local
  type: kerberos
  realm-name: LAB.LOCAL
  domain-name: lab.local
  configured: no
  server-software: active-directory
  client-software: sssd
  required-package: sssd-tools
  required-package: sssd
  required-package: libnss-sss
  required-package: libpam-sss
  required-package: adcli
  required-package: samba-common-bin

Vérifier que le temps est bien synchronisé:

# timedatectl status

Joindre le domaine:

# realm join lab.local -U Administrator
Note:

C'est un lab, hein. On est bien d'accord qu'il faut utiliser un autre compte pour ça.

Vérifier sur la DSA du domain controller que la machine cliente est bien enregistrée:

Vérifier depuis la machine Linux:

# realm list
lab.local
  type: kerberos
  realm-name: LAB.LOCAL
  domain-name: lab.local
  configured: kerberos-member
  server-software: active-directory
  client-software: sssd
  required-package: sssd-tools
  required-package: sssd
  required-package: libnss-sss
  required-package: libpam-sss
  required-package: adcli
  required-package: samba-common-bin
  login-formats: %U@lab.local
  login-policy: allow-realm-logins

Check authent Kerberos:

# klist
# kinit utilisateur@lab.local
# klist

Vérification SSSD:

# id utilisateur
# getent passwd utilisateur
# getent group "Domain Users"

Pour autoriser des utilisateurs à se connecter:

# realm permit --all
# realm permit user1 user2
# realm permit -g LinuxAdmins

Pour activer la création automatique du homedir:

# pam-auth-update --enable mkhomedir

Fichier de conf et logs:

# vi /etc/sssd/sssd.conf
# journalctl -u sssd

Pour quitter le domaine (au cas où):

# realm leave lab.local

Population des AD de test

Voici une méthode minimale, rapide et sale pour remplir un domaine AD avec des données de test bidon (comptes utilisateurs et groupes).

Import-Module ActiveDirectory

New-ADOrganizationalUnit -Name "Fake" -Path (Get-ADDomain).DistinguishedName

# Récupération du domaine courant
$domain = (Get-ADDomain).DnsRoot

# Listes de noms/prénoms fictifs
$prenoms = @(
  "Alice","Bob","Charlie","David","Emma","Frank","Grace","Hugo","Isabelle","Jack",
  "Karen","Leo","Mona","Nicolas","Olivia","Paul","Quentin","Rita","Sophie","Thomas",
  "Ursula","Victor","Wendy","Xavier","Yasmine","Zoe"
)
$noms = @(
  "Martin","Dupont","Durand","Bernard","Petit","Robert","Richard","Moreau","Simon","Laurent",
  "Lefebvre","Michel","Garcia","David","Bertrand","Roux","Vincent","Fournier","Morel","Girard",
  "Andre","Lefevre","Mercier","Blanc","Guerin","Muller"
)

# Listes de noms/prénoms fictifs internationaux
$prenomsIntl = @(
  "John","Michael","Sophia","Daniel","Emily","Carlos","Maria","Hiroshi","Akira","Mei",
  "Wei","Ananya","Raj","Aisha","Fatima","Omar","Amir","Elena","Ivan","Svetlana",
  "Giulia","Luca","Pablo","Diego","Santiago","Alejandro","Marta","Andreas","Greta","Hans",
  "Ingrid","Bjorn","Sofia","Mateusz","Katarzyna","Jakub","Esra","Selim","Leila","Nadia",
  "Sergey","Olga","Petra","Zoltan","Marek","Tomas","Jan","Krzysztof","Hanna","Yuki"
)
$nomsIntl = @(
  "Smith","Johnson","Williams","Brown","Taylor","Wilson","Lopez","Gonzalez","Martinez","Rodriguez",
  "Kumar","Singh","Patel","Gupta","Sharma","Hernandez","Torres","Silva","Costa","Ferreira",
  "Müller","Schmidt","Schneider","Fischer","Weber","Novak","Horvat","Ivic","Popov","Ivanov",
  "Petrov","Sokolov","Kuznetsov","Volkov","Andersen","Hansen","Nielsen","Olsen","Johansson","Karlsson",
  "Svensson","Lindberg","Virtanen","Korhonen","Nieminen","Papadopoulos","Georgiou","Haddad","Khalil","Aziz"
)

$prenoms = $prenoms + $prenomsIntl
$noms    = $noms + $nomsIntl

# Génération de 100 couples prénom/nom
$users = @()
for ($i=1; $i -le 100; $i++) {
  $prenom = Get-Random $prenoms
  $nom    = Get-Random $noms
  $users += [PSCustomObject]@{
    Prenom = $prenom
    Nom    = $nom
  }
}

# Création des utilisateurs
foreach ($u in $users) {
  $sam = ($u.Nom + $u.Prenom.Substring(0,1)).ToUpper()
  $upn = ($u.Prenom + "." + $u.Nom + "@" + $domain).ToLower()
  $pwd = ConvertTo-SecureString "LabPassword123!" -AsPlainText -Force
  $name = "$($u.Prenom) $($u.Nom)"

  try {
    New-ADUser `
      -Name $name `
      -GivenName $u.Prenom `
      -Surname $u.Nom `
      -SamAccountName $sam `
      -UserPrincipalName $upn `
      -AccountPassword $pwd `
      -Office "fake" `
      -Path "OU=Fake,$((Get-ADDomain).DistinguishedName)" `
      -PasswordNeverExpires $true `
      -Enabled $true

    Write-Host "Created user $name ($sam)"
  }
  catch {
    Write-Warning "Failed to create user $name : $_"
  }
}

# Noms de groupes
$groupNames = @(
  "App_CRM_Users",
  "App_ERP_Administrators",
  "App_Intranet_Editors",
  "Service_Finance",
  "Service_RH",
  "Service_IT_Support",
  "Service_Production",
  "Service_Marketing",
  "App_Mail_Distribution",
  "App_Tickets_Access",
  "App_BI_Analysts",
  "Service_Compliance",
  "Service_Logistique",
  "App_DevOps_Pipeline",
  "App_VPN_Users"
)

# Création des groupes
$groupes = @()
foreach ($gname in $groupNames) {
  try {
    New-ADGroup -Name $gname -GroupScope Global -GroupCategory Security -Path "OU=Fake,$((Get-ADDomain).DistinguishedName)"
    $groupes += $gname
    Write-Host "Created group $gname"
  }
  catch {
    Write-Warning "Failed to create group $gname : $_"
  }
}

# Répartition aléatoire des comptes dans les groupes
foreach ($u in $users) {
  $sam = ($u.Nom + $u.Prenom.Substring(0,1)).ToUpper()
  $grp = Get-Random $groupes
  try {
    Add-ADGroupMember -Identity $grp -Members $sam
    Write-Host "Added $sam to $grp"
  }
  catch {
    Write-Warning "Failed to add $sam to $grp : $_"
  }
}

Et voilà le travail: l'annuaire AD est rempli en 30 secondes avec des données de test basiques.

Données de test injectées par le script

--
TG - 07/2026

Cet article a été généré par un humain