Initial lab release: Docker-based Active Directory lab

Complete Active Directory teaching environment based on dockurr/windows:
- Windows Server domain controller, Windows 11 client, Debian 12 client
- docker-compose orchestration, env-driven configuration
- Bilingual documentation (FR + EN) for students
- Dual approach (GUI + PowerShell) in every procedure
- Instructor course plan and reference scripts
- RDP launcher scripts for Linux, macOS and Windows

Made by AcadéNice - https://acadenice.fr/
This commit is contained in:
Corentin JOGUET 2026-04-17 11:29:49 +02:00
commit 8e1b06e090
38 changed files with 3299 additions and 0 deletions

31
.env.example Normal file
View file

@ -0,0 +1,31 @@
# lab_AD_Complet - configuration locale
# Copiez ce fichier en .env et adaptez les valeurs avant le premier lancement.
# Fait par AcadéNice - https://acadenice.fr/
AD_DOMAIN=corp.lab
AD_DOMAIN_NETBIOS=CORP
AD_ORG_NAME=CORP
# Doit respecter la politique AD : 10+ caractères, majuscule, minuscule, chiffre, spécial.
AD_ADMIN_PASSWORD=AdminP@ss!2026
AD_DEMO_PASSWORD=UserP@ss!2026
DC_RAM=6G
DC_CPU=2
DC_DISK=64G
CLIENT_RAM=4G
CLIENT_CPU=2
CLIENT_DISK=40G
DC_WINDOWS_VERSION=2022
CLIENT_WINDOWS_VERSION=11
DC_WEB_PORT=8006
DC_RDP_PORT=3389
CLIENT_WEB_PORT=8009
CLIENT_RDP_PORT=3391
VM_LANGUAGE=French
VM_REGION=fr-FR
VM_KEYBOARD=fr-FR

21
.gitignore vendored Normal file
View file

@ -0,0 +1,21 @@
# Secrets / configuration locale
.env
# Storage des VMs Windows (plusieurs Go)
storage/
storage-*/
# Dossier partage RDP
shared/*
!shared/.gitkeep
# Artefacts OS
.DS_Store
Thumbs.db
*.swp
*.swo
*~
# IDE
.vscode/
.idea/

22
LICENSE Normal file
View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2026 AcadéNice - https://acadenice.fr/
and lab_AD_Complet contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

131
README.md Normal file
View file

@ -0,0 +1,131 @@
# lab_AD_Complet
Lab Active Directory reproductible, basé sur Docker, pour la formation et l'auto-apprentissage.
> English version : [README_EN.md](README_EN.md)
## Contenu du lab
Un environnement Active Directory complet, isolé, comprenant :
- **DC01** : contrôleur de domaine Windows Server (AD DS + DNS)
- **PC01** : poste client Windows 11 destiné à être joint au domaine
- **linux01** : poste client Debian 12 destiné à être joint au domaine (realmd + SSSD)
Tout est orchestré via un seul `docker-compose.yml`, entièrement configurable par variables d'environnement.
## Pré-requis
Le lab exige un accès à la virtualisation matérielle (KVM sous Linux, WSL2 + nested virt sous Windows).
| Système | Supporté | Remarques |
|---|---|---|
| Linux (kernel >= 5.x avec KVM) | Oui | Configuration la plus simple |
| Windows 10/11 Pro + Docker Desktop | Oui | Activer la virtualisation imbriquée dans `.wslconfig` |
| macOS Intel | Partiel | Performances dégradées, non recommandé |
| macOS Apple Silicon (M1/M2/M3) | Non | Utilisez une VM Linux (UTM) - voir `docs/etudiant/fr/00-prerequis.md` |
Ressources minimales :
- 16 Go de RAM recommandés (12 Go minimum)
- 80 Go d'espace disque libre (installation Windows + snapshots)
- Processeur avec VT-x / AMD-V activé dans le BIOS
Scripts de vérification fournis :
```bash
./scripts/check-prereqs.sh # Linux, macOS
.\scripts\check-prereqs.ps1 # Windows
```
## Démarrage rapide
```bash
git clone <url-du-repo> lab_AD_Complet
cd lab_AD_Complet
cp .env.example .env # adaptez les variables
./scripts/check-prereqs.sh
docker compose up -d dc01
```
L'installation de Windows Server se fait automatiquement en arrière-plan (20 à 40 minutes selon votre connexion). Suivez l'avancement via :
- Interface web : http://localhost:8006
- Logs : `docker compose logs -f dc01`
Une fois Windows installé, la configuration AD (promotion, OU, utilisateurs, GPO, partages) reste à la charge de l'apprenant. Les guides détaillés sont dans `docs/etudiant/fr/`.
## Accès aux postes
Deux méthodes disponibles :
### Interface web (noVNC)
- DC : http://localhost:8006
- PC Windows : http://localhost:8009
- Utile pour observer le boot / l'installation, mais lente et sans copier-coller.
### RDP (recommandé)
```bash
./scripts/rdp-dc.sh # ouvre une session RDP sur DC01
./scripts/rdp-client.sh # ouvre une session RDP sur PC01
```
Sous Windows :
```powershell
.\scripts\rdp-dc.ps1
```
RDP fournit un copier-coller natif, un partage de dossier (`\\tsclient\shared`) et de bien meilleures performances.
## Structure du projet
```
lab_AD_Complet/
docker-compose.yml Définit les 3 conteneurs
.env.example Variables configurables
linux-client/ Image Debian pré-équipée (SSSD/realmd)
scripts/ Vérification de prérequis + lancement RDP
shared/ Dossier partagé avec les VMs Windows via RDP
docs/
etudiant/ Guides d'apprentissage (FR + EN)
formateur/ Supports et corrigés (non distribués aux étudiants)
```
## Documentation
- `docs/etudiant/fr/00-prerequis.md` : installation de Docker et vérifications
- `docs/etudiant/fr/01-installation-lab.md` : premier démarrage du lab
- `docs/etudiant/fr/02-promotion-dc.md` : promotion d'un contrôleur de domaine (GUI + PowerShell)
- `docs/etudiant/fr/03-ou-utilisateurs-groupes.md` : arborescence OU, utilisateurs, groupes, AGDLP
- `docs/etudiant/fr/04-gpo.md` : création et liaison de GPO
- `docs/etudiant/fr/05-partages-ntfs.md` : partages SMB et permissions NTFS
- `docs/etudiant/fr/06-jonction-poste-windows.md` : rejoindre PC01 au domaine
- `docs/etudiant/fr/07-jonction-poste-linux.md` : rejoindre linux01 au domaine
- `docs/etudiant/fr/troubleshooting.md` : problèmes fréquents
Chaque procédure est documentée en double approche : **interface graphique** (Server Manager, ADUC, GPMC) et **scripting PowerShell**.
## Arrêter le lab
```bash
docker compose stop # arrêt sans perte d'état
docker compose down # arrêt et suppression des conteneurs
docker compose down -v # suppression complète y compris les disques VM
```
Les disques Windows sont stockés dans `./storage-dc01/` et `./storage-pc01/` à la racine du projet. Supprimer ces dossiers revient à repartir d'une installation vierge.
## Licence
MIT - voir [LICENSE](LICENSE).
## Contribuer
Les contributions sont bienvenues (corrections, traductions, nouveaux exercices). Ouvrez une issue ou proposez un merge request.
---
Fait par [AcadéNice](https://acadenice.fr/).

131
README_EN.md Normal file
View file

@ -0,0 +1,131 @@
# lab_AD_Complet
Reproducible Active Directory lab, based on Docker, for training and self-study.
> Version française : [README.md](README.md)
## Lab content
A complete, isolated Active Directory environment comprising:
- **DC01**: Windows Server domain controller (AD DS + DNS)
- **PC01**: Windows 11 client workstation to join the domain
- **linux01**: Debian 12 client to join the domain (realmd + SSSD)
Everything is orchestrated via a single `docker-compose.yml`, fully configurable via environment variables.
## Prerequisites
The lab requires hardware virtualization access (KVM on Linux, WSL2 + nested virt on Windows).
| System | Supported | Notes |
|---|---|---|
| Linux (kernel >= 5.x with KVM) | Yes | Simplest setup |
| Windows 10/11 Pro + Docker Desktop | Yes | Enable nested virtualization in `.wslconfig` |
| macOS Intel | Partial | Degraded performance, not recommended |
| macOS Apple Silicon (M1/M2/M3) | No | Use a Linux VM (UTM) - see `docs/etudiant/en/00-prerequisites.md` |
Minimum resources:
- 16 GB RAM recommended (12 GB minimum)
- 80 GB free disk space (Windows install + snapshots)
- CPU with VT-x / AMD-V enabled in BIOS
Check scripts provided:
```bash
./scripts/check-prereqs.sh # Linux, macOS
.\scripts\check-prereqs.ps1 # Windows
```
## Quick start
```bash
git clone <repo-url> lab_AD_Complet
cd lab_AD_Complet
cp .env.example .env # adapt variables
./scripts/check-prereqs.sh
docker compose up -d dc01
```
Windows Server installation runs automatically in the background (20 to 40 minutes depending on your connection). Monitor progress via:
- Web UI: http://localhost:8006
- Logs: `docker compose logs -f dc01`
Once Windows is installed, AD configuration (promotion, OUs, users, GPOs, shares) is left to the learner. Detailed guides are in `docs/etudiant/en/`.
## Accessing the hosts
Two methods available:
### Web UI (noVNC)
- DC: http://localhost:8006
- Windows client: http://localhost:8009
- Useful to observe boot / installation, but slow and no clipboard sync.
### RDP (recommended)
```bash
./scripts/rdp-dc.sh # opens RDP session on DC01
./scripts/rdp-client.sh # opens RDP session on PC01
```
On Windows:
```powershell
.\scripts\rdp-dc.ps1
```
RDP provides native clipboard, folder redirection (`\\tsclient\shared`) and much better performance.
## Project structure
```
lab_AD_Complet/
docker-compose.yml Defines the 3 containers
.env.example Configurable variables
linux-client/ Debian image pre-equipped (SSSD/realmd)
scripts/ Prerequisite checks + RDP launchers
shared/ Folder shared with Windows VMs via RDP
docs/
etudiant/ Learning guides (FR + EN)
formateur/ Instructor materials and solutions (not distributed)
```
## Documentation
- `docs/etudiant/en/00-prerequisites.md`: Docker install and checks
- `docs/etudiant/en/01-lab-startup.md`: first lab startup
- `docs/etudiant/en/02-dc-promotion.md`: domain controller promotion (GUI + PowerShell)
- `docs/etudiant/en/03-ou-users-groups.md`: OU tree, users, groups, AGDLP
- `docs/etudiant/en/04-gpo.md`: GPO creation and linking
- `docs/etudiant/en/05-shares-ntfs.md`: SMB shares and NTFS permissions
- `docs/etudiant/en/06-join-windows-client.md`: joining PC01 to the domain
- `docs/etudiant/en/07-join-linux-client.md`: joining linux01 to the domain
- `docs/etudiant/en/troubleshooting.md`: common issues
Each procedure is documented with a dual approach: **graphical interface** (Server Manager, ADUC, GPMC) and **PowerShell scripting**.
## Stop the lab
```bash
docker compose stop # stop without losing state
docker compose down # stop and remove containers
docker compose down -v # remove everything including VM disks
```
Windows disks are stored in `./storage-dc01/` and `./storage-pc01/` at the project root. Removing these directories resets everything to a fresh install.
## License
MIT - see [LICENSE](LICENSE).
## Contributing
Contributions are welcome (fixes, translations, new exercises). Open an issue or submit a merge request.
---
Made by [AcadéNice](https://acadenice.fr/).

83
docker-compose.yml Normal file
View file

@ -0,0 +1,83 @@
services:
dc01:
image: dockurr/windows
container_name: lab-dc01
hostname: DC01
environment:
VERSION: "${DC_WINDOWS_VERSION:-2022}"
RAM_SIZE: "${DC_RAM:-6G}"
CPU_CORES: "${DC_CPU:-2}"
DISK_SIZE: "${DC_DISK:-64G}"
USERNAME: "Administrator"
PASSWORD: "${AD_ADMIN_PASSWORD:-AdminP@ss!2026}"
LANGUAGE: "${VM_LANGUAGE:-French}"
REGION: "${VM_REGION:-fr-FR}"
KEYBOARD: "${VM_KEYBOARD:-fr-FR}"
devices:
- /dev/kvm
- /dev/net/tun
cap_add:
- NET_ADMIN
ports:
- "${DC_WEB_PORT:-8006}:8006"
- "127.0.0.1:${DC_RDP_PORT:-3389}:3389/tcp"
- "127.0.0.1:${DC_RDP_PORT:-3389}:3389/udp"
volumes:
- ./storage-dc01:/storage
- ./shared:/shared:ro
networks:
- adlan
stop_grace_period: 2m
restart: unless-stopped
pc01:
image: dockurr/windows
container_name: lab-pc01
hostname: PC01
environment:
VERSION: "${CLIENT_WINDOWS_VERSION:-11}"
RAM_SIZE: "${CLIENT_RAM:-4G}"
CPU_CORES: "${CLIENT_CPU:-2}"
DISK_SIZE: "${CLIENT_DISK:-40G}"
USERNAME: "LocalAdmin"
PASSWORD: "${AD_ADMIN_PASSWORD:-AdminP@ss!2026}"
LANGUAGE: "${VM_LANGUAGE:-French}"
REGION: "${VM_REGION:-fr-FR}"
KEYBOARD: "${VM_KEYBOARD:-fr-FR}"
devices:
- /dev/kvm
- /dev/net/tun
cap_add:
- NET_ADMIN
ports:
- "${CLIENT_WEB_PORT:-8009}:8006"
- "127.0.0.1:${CLIENT_RDP_PORT:-3391}:3389/tcp"
- "127.0.0.1:${CLIENT_RDP_PORT:-3391}:3389/udp"
volumes:
- ./storage-pc01:/storage
networks:
- adlan
stop_grace_period: 2m
restart: unless-stopped
linux01:
build: ./linux-client
container_name: lab-linux01
hostname: linux01
environment:
AD_DOMAIN: "${AD_DOMAIN:-corp.lab}"
AD_DOMAIN_NETBIOS: "${AD_DOMAIN_NETBIOS:-CORP}"
AD_ADMIN_USER: "Administrator"
AD_ADMIN_PASSWORD: "${AD_ADMIN_PASSWORD:-AdminP@ss!2026}"
DC_CONTAINER_IP: "lab-dc01"
cap_add:
- SYS_ADMIN
networks:
- adlan
depends_on:
- dc01
restart: unless-stopped
networks:
adlan:
driver: bridge

View file

@ -0,0 +1,72 @@
# Prerequisites
Before starting the lab, make sure your workstation can run several VMs in
parallel. The domain controller and the Windows client are full Windows VMs
(Server and Windows 11).
## Hardware
| Resource | Recommended | Minimum |
|---|---|---|
| RAM | 16 GB | 12 GB |
| CPU | 4 cores | 2 cores |
| Free disk | 150 GB | 80 GB |
| CPU virtualization | VT-x or AMD-V enabled in BIOS | required |
## Software
- Recent Docker Engine (>= 24) with Compose v2 plugin
- An RDP client (optional but strongly recommended)
Install Docker according to your OS:
- Linux: `docker` and `docker-compose-plugin` packages
- Windows: Docker Desktop with WSL2 backend
- macOS Intel: Docker Desktop
- macOS Apple Silicon: not supported (see the dedicated section below)
## macOS Apple Silicon
M1/M2/M3/M4 chips do not expose an x86 `/dev/kvm`. The `dockurr/windows` image
refuses to start without KVM, and full x86 emulation via QEMU TCG is too slow
to be usable.
Workaround: install a Linux VM with Docker inside, then clone and run the lab
from there. [UTM](https://mac.getutm.app/) works well. You get a Debian or
Ubuntu VM that hosts the whole lab, and you access the lab VMs via RDP from
your Mac.
## Automated check
A script validates the critical items:
```
./scripts/check-prereqs.sh # Linux, macOS
.\scripts\check-prereqs.ps1 # Windows PowerShell
```
It reports `[ OK ]`, `[WARN]`, `[FAIL]` for each check.
## Windows-specific setup
Nested virtualization must be enabled in WSL2. Create
`%USERPROFILE%\.wslconfig` with:
```
[wsl2]
nestedVirtualization=true
memory=16GB
processors=4
```
Then restart WSL:
```
wsl --shutdown
```
Docker Desktop will restart with nested virt available.
## Next
Once prerequisites check out, continue to `01-lab-startup.md`.

View file

@ -0,0 +1,75 @@
# Lab startup
Goal: clone the project, adapt its configuration, then start the domain
controller. Clients (PC01 and linux01) will be started later in the journey.
## Get the project
```
git clone <repo-url> lab_AD_Complet
cd lab_AD_Complet
```
## Adapt the configuration
`.env.example` lists every variable (names, passwords, VM resources). Copy it:
```
cp .env.example .env
```
At minimum, change:
- `AD_DOMAIN` and `AD_DOMAIN_NETBIOS` if you want something else than `corp.lab`
- `AD_ADMIN_PASSWORD`: must match the default AD policy (10+ chars, uppercase,
lowercase, digit, special)
Other variables (RAM, CPU, ports) can stay as-is.
## Check prerequisites
```
./scripts/check-prereqs.sh
```
Fix any `[FAIL]` before continuing.
## Start the domain controller
`docker-compose.yml` defines three services:
- `dc01`: Windows Server (domain controller)
- `pc01`: Windows 11 (client)
- `linux01`: Debian 12 (client)
For now, only `dc01`:
```
docker compose up -d dc01
```
The `dockurr/windows` image downloads (~1 GB), then fetches the Windows Server
ISO and runs an unattended install. Depending on your connection, allow 20 to
45 minutes.
## Track progress
- Logs: `docker compose logs -f dc01`
- Web console: [http://localhost:8006](http://localhost:8006)
## Accessing DC01
Once Windows is up:
- Web: http://localhost:8006 (slow, unreliable clipboard)
- RDP: `./scripts/rdp-dc.sh` (recommended)
Default credentials for first login:
- User: `Administrator`
- Password: value of `AD_ADMIN_PASSWORD` in your `.env`
## Next
The server is installed but not yet a DC. Promotion happens in
`02-dc-promotion.md`.

View file

@ -0,0 +1,110 @@
# Promoting the server to a domain controller
Goal: turn the freshly installed Windows Server into the first DC of a new
Active Directory forest. We also install the DNS role, required by AD.
## What we create
An Active Directory forest is a logical structure containing one or more
domains. Here we create:
- a new forest with the configured domain at its root (`corp.lab` by default)
- a first domain controller (`DC01`) hosting the AD database and DNS
A DC is critical: it handles authentication, GPOs, internal DNS. Production
setups use at least two for redundancy. One is enough for this lab.
## Preparation
Rename the machine first. Once promoted, a DC cannot be renamed without being
demoted.
### GUI
1. `Settings > System > About > Rename this PC` (or `Win + Pause` > "Change settings")
2. New name: `DC01`
3. Restart
### PowerShell
```
Rename-Computer -NewName "DC01" -Restart
```
If `Rename-Computer` refuses authentication on a fresh install, use the GUI
or the registry approach (see `troubleshooting.md`).
## Install the roles
After the reboot, open a session as Administrator.
### GUI
1. Open `Server Manager`
2. `Manage > Add Roles and Features`
3. Select:
- `AD DS`
- `DNS Server`
4. Leave defaults, install
5. When done, click the warning flag > `Promote this server to a domain controller`
### PowerShell
```
Install-WindowsFeature -Name AD-Domain-Services, DNS -IncludeManagementTools
```
## Promote to domain controller
### GUI
1. In the AD DS configuration wizard:
2. `Add a new forest` > Root name: `corp.lab`
3. Functional levels: keep the suggested value
4. Check `DNS Server` and `Global Catalog`
5. Set a DSRM password (Directory Services Restore Mode)
6. Ignore DNS warnings (normal on a brand new DC)
7. Validate, let the machine reboot
### PowerShell
```
$dsrmPwd = Read-Host -AsSecureString "DSRM password"
Install-ADDSForest `
-DomainName "corp.lab" `
-DomainNetbiosName "CORP" `
-InstallDns `
-SafeModeAdministratorPassword $dsrmPwd `
-Force
```
Key cmdlets:
- `Install-ADDSForest` creates a new forest
- `Install-ADDSDomainController` adds a DC to an existing forest
## Validation
After reboot, log back in (account is now `CORP\Administrator`):
```
Get-ADDomain
Get-ADForest
dcdiag
```
The first two return domain/forest info. `dcdiag` runs integrity tests.
Minor DNS warnings are normal on a standalone DC.
## Notes
- The DSRM password is independent of Administrator's. It is used in AD
recovery mode. Keep it in your password manager.
- Once promoted, a DC cannot be renamed without demotion first
(`Uninstall-ADDSDomainController`).
- Fresh dockur installs come with an auto-generated hostname (`WIN-xxxx`).
Renaming **before** promotion is crucial.
## Next
AD is live but empty. Create OUs, users and groups in `03-ou-users-groups.md`.

View file

@ -0,0 +1,146 @@
# Organizational Units, users, groups
Goal: build the AD tree (OUs), populate it with users and groups, apply the
AGDLP nesting recommended by Microsoft.
## What is an OU
An Organizational Unit is a logical container for AD objects (users,
computers, groups). OUs are used to apply policies, delegate admin, or just
structure the directory.
An OU grants no permission by itself. It is purely a structuring tool.
## Proposed tree
```
corp.lab
└── CORP
├── Users
│ ├── Direction
│ ├── Teaching
│ ├── IT
│ ├── Admin
│ └── Students
├── Computers
│ └── (same sub-OUs)
├── Groups
└── Services
```
Mirror or adapt to your context.
## Creating OUs
### GUI
1. Open `Active Directory Users and Computers` (`dsa.msc`)
2. Right-click domain > `New > Organizational Unit`
3. Name it `CORP`
4. Inside, create `Users`, `Computers`, `Groups`, `Services`
5. Create department sub-OUs under `Users` and `Computers`
### PowerShell
Key cmdlet: `New-ADOrganizationalUnit`.
```
New-ADOrganizationalUnit -Name "CORP" -Path "DC=corp,DC=lab"
New-ADOrganizationalUnit -Name "Users" -Path "OU=CORP,DC=corp,DC=lab"
```
Loop for departments:
```
$deps = @("Direction","Teaching","IT","Admin","Students")
foreach ($d in $deps) {
New-ADOrganizationalUnit -Name $d -Path "OU=Users,OU=CORP,DC=corp,DC=lab"
}
```
## Creating users
### GUI
1. Right-click a department OU > `New > User`
2. Fill in the fields (First, Last, SamAccountName, UPN)
3. Initial password, tick `User must change password at next logon`
### PowerShell
Key cmdlet: `New-ADUser`.
```
New-ADUser `
-Name "Paul Martin" `
-GivenName "Paul" `
-Surname "Martin" `
-SamAccountName "pmartin" `
-UserPrincipalName "pmartin@corp.lab" `
-Path "OU=Teaching,OU=Users,OU=CORP,DC=corp,DC=lab" `
-AccountPassword (ConvertTo-SecureString "UserP@ss!2026" -AsPlainText -Force) `
-Enabled $true `
-ChangePasswordAtLogon $true
```
## Creating groups
Two group types:
- **Global groups (GG)**: group users by department/role. `GG_Teaching`, `GG_Students`.
- **Domain local groups (DL)**: hold permissions on resources.
`DL_Share_Common_R`, `DL_Share_Teaching_RW`.
### GUI
1. Right-click `OU=Groups` > `New > Group`
2. Scope: `Global` or `Domain local` as needed
3. Type: `Security`
### PowerShell
Key cmdlet: `New-ADGroup`.
```
New-ADGroup -Name "GG_Teaching" -GroupScope Global -GroupCategory Security `
-Path "OU=Groups,OU=CORP,DC=corp,DC=lab"
New-ADGroup -Name "DL_Share_Common_R" -GroupScope DomainLocal -GroupCategory Security `
-Path "OU=Groups,OU=CORP,DC=corp,DC=lab"
```
## Apply AGDLP nesting
AGDLP is a Microsoft convention:
- **A**ccount in
- **G**lobal group (department) member of
- **D**omain **L**ocal group (resource) holding the
- **P**ermission
Concretely:
1. Add users to matching global groups
2. Add global groups to matching domain local groups
3. Put NTFS/share permissions on domain local groups
Key cmdlet: `Add-ADGroupMember`.
```
Add-ADGroupMember -Identity "GG_Teaching" -Members "pmartin"
Add-ADGroupMember -Identity "DL_Share_Common_R" -Members "GG_Teaching","GG_Students"
```
## Validation
```
Get-ADUser -Filter * -SearchBase "OU=CORP,DC=corp,DC=lab" | Select Name, SamAccountName
Get-ADGroup -Filter * -SearchBase "OU=Groups,OU=CORP,DC=corp,DC=lab" | Select Name, GroupScope
Get-ADGroupMember -Identity "GG_Teaching"
```
`dsa.msc` should show your hierarchy, users in their OUs, groups with members.
## Next
`04-gpo.md` for Group Policy.

121
docs/etudiant/en/04-gpo.md Normal file
View file

@ -0,0 +1,121 @@
# Group Policy Objects (GPO)
Goal: create and link a few representative GPOs.
## What is a GPO
A Group Policy Object is a set of settings applied to users or computers. It
is stored in `SYSVOL` (on DCs) and replicated to all domain-joined machines.
Two main scopes:
- `Computer configuration`: applied at boot
- `User configuration`: applied at logon
A GPO is **linked** to a container (site, domain, OU). Objects in that
container and its descendants inherit the GPO. You thus use OUs as scoping
targets: link a GPO to `Students` OU and it will only apply to those users.
## Lab scenarios
Three GPOs:
1. Strengthen the domain password policy
2. Force a wallpaper on students
3. Restrict Control Panel access for students
## Password policy
Lives in the `Default Domain Policy`, applied domain-wide.
### GUI
1. Open `Group Policy Management` (`gpmc.msc`)
2. Domain > `Default Domain Policy` > right-click > `Edit`
3. `Computer Configuration > Policies > Windows Settings > Security Settings > Account Policies > Password Policy`
4. Tune minimum length, complexity, history, age
### PowerShell
Key cmdlet: `Set-ADDefaultDomainPasswordPolicy`.
```
Set-ADDefaultDomainPasswordPolicy -Identity corp.lab `
-MinPasswordLength 10 `
-ComplexityEnabled $true `
-PasswordHistoryCount 5 `
-MaxPasswordAge (New-TimeSpan -Days 90) `
-LockoutThreshold 5 `
-LockoutDuration (New-TimeSpan -Minutes 15)
```
## Wallpaper GPO
### GUI
1. `gpmc.msc` > Domain > right-click `OU=Students,OU=Users,OU=CORP` > `Create a GPO in this domain, and link it here`
2. Name it (e.g. `GPO_Students_Wallpaper`)
3. Right-click GPO > `Edit`
4. `User Configuration > Policies > Administrative Templates > Desktop > Desktop`
5. Setting `Desktop Wallpaper` > `Enabled`, set the image path and style
### PowerShell
Key cmdlets: `New-GPO`, `New-GPLink`, `Set-GPRegistryValue`.
```
New-GPO -Name "GPO_Students_Wallpaper"
Set-GPRegistryValue -Name "GPO_Students_Wallpaper" `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "Wallpaper" -Type String -Value "C:\Windows\Web\Wallpaper\Windows\img0.jpg"
New-GPLink -Name "GPO_Students_Wallpaper" `
-Target "OU=Students,OU=Users,OU=CORP,DC=corp,DC=lab"
```
## Control Panel restriction GPO
Same steps via GUI, setting:
`User Configuration > Policies > Administrative Templates > Control Panel > Prohibit access to Control Panel and PC settings > Enabled`
PowerShell:
```
New-GPO -Name "GPO_Students_NoCP"
Set-GPRegistryValue -Name "GPO_Students_NoCP" `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" `
-ValueName "NoControlPanel" -Type DWord -Value 1
New-GPLink -Name "GPO_Students_NoCP" `
-Target "OU=Students,OU=Users,OU=CORP,DC=corp,DC=lab"
```
## Test
On a client machine with a student logged in:
```
gpupdate /force
gpresult /r
```
`gpresult` lists effective GPOs. If yours is missing, check:
- the user is in the right OU
- the GPO is linked to the right OU
- the user has `Apply Group Policy` permission (security filtering)
- no WMI filter blocks it
## Notes
- Don't stuff the `Default Domain Policy`. Always create dedicated GPOs for
anything beyond the password policy.
- GPO precedence: Local > Site > Domain > OU (closer wins on conflicts).
- `Block Inheritance` breaks the chain for a child OU. Use sparingly.
## Next
`05-shares-ntfs.md` for SMB shares and NTFS permissions.

View file

@ -0,0 +1,113 @@
# SMB shares and NTFS permissions
Goal: expose three shares on `DC01`, secure them with the AD groups created
earlier, and verify permissions behave as expected.
Note: in production, shares live on a dedicated file server, not on a DC. We
simplify here.
## Shares to create
| Share | Path | Access |
|---|---|---|
| `Common` | `C:\Shares\Common` | read for everyone, write for Direction/Teaching/Admin |
| `Teaching` | `C:\Shares\Teaching` | restricted to GG_Teaching |
| `Direction` | `C:\Shares\Direction` | restricted to GG_Direction |
## AGDLP reminder
Permissions are **never** placed directly on global groups or users. They go
on a **domain local group**, which contains the matching global groups.
Example for `Common`:
- Global groups: `GG_Teaching`, `GG_Students`, ...
- DL groups: `DL_Share_Common_R` (read), `DL_Share_Common_RW` (write)
- NTFS ACLs: set on `DL_Share_Common_R` and `DL_Share_Common_RW`
- Nesting:
- `GG_Students` member of `DL_Share_Common_R`
- `GG_Teaching` member of `DL_Share_Common_RW`
## Create folders and shares
### GUI
1. Create `C:\Shares\Common` in Explorer
2. Right-click > `Properties > Sharing > Advanced Sharing`
3. Tick `Share this folder`, name the share, click `Permissions`
4. Remove `Everyone`, add the relevant AD groups with appropriate rights
5. `Security` tab > `Edit`: define NTFS ACLs
6. Disable inheritance if you want an explicit ACL
### PowerShell
Key cmdlets: `New-SmbShare`, `Get-Acl`, `Set-Acl`, `FileSystemAccessRule`.
```
New-Item -Path C:\Shares\Common -ItemType Directory -Force
New-SmbShare -Name "Common" -Path "C:\Shares\Common" `
-FullAccess "CORP\Domain Admins" `
-ReadAccess "CORP\DL_Share_Common_R" `
-ChangeAccess "CORP\DL_Share_Common_RW"
```
NTFS permissions:
```
$acl = Get-Acl "C:\Shares\Common"
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"CORP\DL_Share_Common_R", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl "C:\Shares\Common" $acl
```
Repeat per (DL, rights) pair.
## Test from a Windows client
On `PC01`, logged in as an AD user:
```
\\DC01\Common
```
via `Run` (`Win + R`) or the Explorer address bar.
Tests:
- as a `GG_Students` member: read OK, write denied
- as a `GG_Teaching` member: read and write OK
- attempt to access `\\DC01\Teaching` as a student: denied
## Test from Linux
If `linux01` is domain-joined (see `07-join-linux-client.md`):
```
smbclient //DC01/Common -U pmartin%<password>
# then:
ls
put /etc/hostname
```
or mount via `cifs-utils`:
```
mkdir /mnt/common
mount -t cifs //DC01/Common /mnt/common -o username=pmartin,domain=CORP
```
## Notes
- **Both** layers (Share and NTFS) apply. The effective access is the
intersection. Common practice: `Full Control` at share level, then refine
via NTFS.
- An already-connected user does not see group membership changes until
relogon (or `klist purge`).
- Never ACL a user directly. They leave, you are left with cleanup.
## Next
`06-join-windows-client.md` to join `PC01` and test these shares from a
client.

View file

@ -0,0 +1,155 @@
# Join the Windows client to the domain
Goal: start the `pc01` container, install Windows 11, then join the machine
to `corp.lab`.
## Start the container
```
docker compose up -d pc01
```
Windows 11 installs unattended, same as `DC01`. Allow 20 to 40 minutes. Track
via:
- [http://localhost:8009](http://localhost:8009)
- `docker compose logs -f pc01`
Once the desktop is available:
```
./scripts/rdp-client.sh
```
Local credentials: `LocalAdmin` / `AD_ADMIN_PASSWORD` (same value as DC01 in
this lab).
## Step 1: prepare the client
### Rename
Fresh dockurr installs ship with an auto-generated hostname (`WIN-xxxxxxx`).
Rename before joining. GUI: `Settings > System > About > Rename this PC`. Or
PowerShell:
```
Rename-Computer -NewName "PC01" -Restart
```
### Point DNS to the DC
Without correct DNS, the join fails. PC01 must query DC01 to resolve
`corp.lab` and AD SRV records.
GUI: `Settings > Network > Network adapter properties > Edit DNS settings`.
PowerShell:
```
Get-NetAdapter | Format-Table Name, Status
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses <DC_IP>
```
See the docker specifics block below to pick the IP.
### Docker lab specifics
`dockurr/windows` runs Windows inside a VM with internal NAT. The DC
advertises its internal VM IP in DNS, which is not routable from `PC01`. But
the DC container has a DNAT rule forwarding all ports to its VM.
Solution: use the DC **container** IP (visible via `docker inspect lab-dc01`)
and add a `hosts` entry so name resolution lands on it.
In PowerShell on PC01:
```
# Replace <DC_CONTAINER_IP> with the value from:
# docker inspect lab-dc01 --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
Add-Content C:\Windows\System32\drivers\etc\hosts "`n<DC_CONTAINER_IP> corp.lab dc01.corp.lab dc01"
ipconfig /flushdns
```
Test:
```
Test-NetConnection -ComputerName corp.lab -Port 389
nslookup corp.lab
```
## Step 2: join the domain
### GUI
1. `Settings > System > About > Join a domain`
2. Or `sysdm.cpl > Change`
3. Enter `corp.lab`, confirm
4. Enter `CORP\Administrator` credentials
5. Restart when prompted
### PowerShell
Key cmdlet: `Add-Computer`.
```
$pass = ConvertTo-SecureString "AdminP@ss!2026" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("CORP\Administrator", $pass)
Add-Computer -DomainName corp.lab -Credential $cred -Restart
```
## Step 3: allow an AD user to RDP
By default, only local `Administrators` can RDP. After joining, the local
`Administrators` contains `CORP\Domain Admins`, so a domain admin can RDP.
Standard users must be explicitly added.
### GUI
1. Right-click `This PC > Properties > Remote Desktop settings`
2. `Select users` > add `CORP\pmartin` (or an AD group)
### PowerShell
```
Add-LocalGroupMember -Group "Remote Desktop Users" -Member "CORP\pmartin"
```
In practice, create a dedicated AD group (e.g. `GG_RDPUsers`) and push it via
GPO to the local group on every machine.
## Step 4: test with an AD user
From Linux/macOS host:
```
xfreerdp3 /v:127.0.0.1:3391 /u:pmartin /d:CORP /p:'<pwd>' /cert:ignore +clipboard /size:1600x900 /dynamic-resolution
```
On Windows, use `mstsc` with `CORP\pmartin`.
Once logged in, validate:
```
whoami
whoami /groups
Get-ComputerInfo | Select CsDomain, CsDomainRole
```
You should see `CORP\pmartin`, AD groups, and `CsDomainRole : MemberWorkstation`.
## Notes
- An account with "must change password at next logon" cannot RDP via NLA.
Either unset the flag on the DC
(`Set-ADUser -ChangePasswordAtLogon $false`) or force `/sec:rdp` to get the
change-password screen.
- If `Add-Computer` hits `The mapping between account names and SIDs was not
done`, the PC is in a broken domain state. Switch to workgroup
(`Add-Computer -WorkgroupName "WORKGROUP" -Force`) then retry.
- Clean up stale computer accounts in `CN=Computers` when you recreate a
client.
## Next
`07-join-linux-client.md` for the Linux side.

View file

@ -0,0 +1,136 @@
# Join the Linux client to the domain
Goal: configure the Debian client `linux01` to authenticate against AD, and
validate resolution of AD users and groups.
Standard stack on Debian/Ubuntu/RHEL:
- `realmd`: domain discovery and join
- `sssd`: daemon handling the integration (cache, Kerberos, NSS, PAM)
- `adcli`: low-level AD client
- `krb5`: Kerberos layer
All these packages are baked into the image (see `linux-client/Dockerfile`).
## Start the container
```
docker compose up -d linux01
docker exec -it lab-linux01 bash
```
The entrypoint auto-configures `/etc/resolv.conf` to point at the DC container
IP and adds `hosts` overrides for AD names.
Check:
```
cat /etc/resolv.conf
cat /etc/hosts | tail
ping -c 2 corp.lab
```
## Domain discovery
Key tool: `realm discover`.
```
realm discover corp.lab
```
You should see structured output with `type: kerberos` and
`server-software: active-directory`.
If empty, check DNS: the DC must answer on port 53 at the used IP.
## Join
Key tool: `realm join`.
```
realm join -U Administrator corp.lab
# Enter CORP\Administrator password when asked
```
Under the hood, `realmd`:
1. Creates a `LINUX01` computer account in `CN=Computers`
2. Generates a Kerberos keytab at `/etc/krb5.keytab`
3. Configures `/etc/sssd/sssd.conf`
4. Enables `sssd` as NSS backend and PAM module
## Start sssd
In a container, systemd may be absent. Start sssd directly:
```
sssd --daemon
```
## Validation
NSS resolution:
```
id pmartin@corp.lab
getent passwd pmartin@corp.lab
getent group 'GG_Teaching@corp.lab'
```
You should see:
- a UID assigned by sssd (large number derived from the SID)
- the AD groups of the user, including AGDLP-nested ones
Kerberos auth:
```
kinit pmartin@CORP.LAB
klist
```
`klist` must show a valid TGT.
## SSH with an AD account
If you enabled SSH in the container (default with the provided Dockerfile):
```
ssh pmartin@lab-linux01
# or the container IP
```
The home directory is auto-created on first login via `pam_mkhomedir`
configured by the entrypoint.
## Restrict access to specific AD groups
By default, any AD user can log in. To restrict:
```
realm permit -g "GG_Teaching@corp.lab"
```
Or the opposite (deny-all with exceptions) via `/etc/sssd/sssd.conf`.
## Notes
- `realm join` fails with bad DNS, or if clock drift > 5 minutes vs the DC.
Fresh containers inherit the host clock, that's fine.
- In this lab, DNS resolution is tricky: the DC advertises a non-routable
internal IP. We work around via `/etc/hosts`. In production, the DC is
directly reachable on the network.
- `sssd` caches users for 6h by default. To flush: `sss_cache -E` or restart
`sssd`.
## Leave the domain
```
realm leave corp.lab
```
Removes the computer account on the DC, the keytab, disables sssd.
## Next
The lab is fully operational. See `troubleshooting.md` for issues.

View file

@ -0,0 +1,153 @@
# Troubleshooting
Common issues encountered while setting up the lab.
## Windows installation stuck
Symptom: http://localhost:8006 stays on the ISO download screen.
Causes:
- Slow/interrupted internet (ISO is several GB)
- Not enough host disk space
- `btrfs` filesystem on `/storage` (dockurr warns, rarely blocking)
Check `docker compose logs -f dc01`, restart if needed.
## /dev/kvm not accessible
Symptom: `KVM acceleration not available` in dockurr logs.
Causes:
- Virtualization disabled in BIOS
- Your user not in the `kvm` group
- WSL2 without nested virt (Windows)
Fixes:
- Linux: `sudo usermod -aG kvm $USER`, reconnect
- Windows: edit `%USERPROFILE%\.wslconfig` with `nestedVirtualization=true`
- macOS Apple Silicon: unsupported, use UTM
## Rename-Computer rejects authentication
Symptom: `Rename-Computer : ... The user name or password is incorrect.`
Happens on a fresh install before any domain membership. The cmdlet attempts
a local authentication that fails for obscure reasons.
Fixes:
- Use the GUI: `sysdm.cpl > Change`
- Or the registry:
```
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "Hostname" -Value "NEW"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "NV Hostname" -Value "NEW"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName" -Name "ComputerName" -Value "NEW"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName" -Name "ComputerName" -Value "NEW"
Restart-Computer -Force
```
## Add-Computer: "the computer is already in this domain"
The PC has a partial domain state (DNS suffix, workgroup with the same name
as the domain NetBIOS, prior join). Clean first:
```
Add-Computer -WorkgroupName "WORKGROUP" -Force
Restart-Computer -Force
```
If `Remove-Computer` fails with `The mapping between account names and SIDs
was not done`, force via WMI:
```
$cs = Get-WmiObject Win32_ComputerSystem
$cs.UnjoinDomainOrWorkgroup($null, $null, 0)
Restart-Computer -Force
```
## RDP denies the AD user
Symptom: `ERRCONNECT_CONNECT_TRANSPORT_FAILED` after NLA with freerdp, or
"access denied" with mstsc.
Cause: by default only local `Administrators` can RDP. Domain users aren't
granted.
Fix on the client:
```
Add-LocalGroupMember -Group "Remote Desktop Users" -Member "CORP\pmartin"
```
Push via GPO in production.
## "Password must change" over freerdp
Symptom: `ERRCONNECT_PASSWORD_MUST_CHANGE`.
freerdp with NLA cannot display the change-password screen. Two options:
- Clear the flag on the DC:
```
Set-ADAccountPassword -Identity pmartin -Reset -NewPassword (ConvertTo-SecureString "NewP@ss!2026" -AsPlainText -Force)
Set-ADUser -Identity pmartin -ChangePasswordAtLogon $false
```
- Or bypass NLA:
```
xfreerdp3 /sec:rdp ...
```
## realm discover returns nothing
Causes:
- Wrong DNS on `linux01` (check `/etc/resolv.conf`)
- DC not answering on port 53
- `dbus` not running in the container:
```
dbus-daemon --system --fork
```
## sssd fails to start
Symptom: `Invalid option -f: unknown option` when `realm join` runs
`service sssd restart`.
Context: docker images without full init (no systemd). Start manually:
```
/usr/sbin/sssd --daemon
```
## AD user not resolved on Linux
```
id pmartin@corp.lab
# "no such user"
```
Common causes:
- sssd not running (see above)
- sssd cache out of sync: `sss_cache -E`
- Domain missing from `realm list`: the join silently failed, retry with
`realm join -v`
## Share inaccessible from a client
- User not in the DL group: `Get-ADGroupMember DL_Share_Common_R`
- Kerberos token not refreshed: relogon
- Restrictive NTFS ACL: check via `Get-Acl` or Security tab
## Full lab reset
To start fresh without touching the rest of your system:
```
docker compose down -v
rm -rf ./storage-dc01 ./storage-pc01
docker compose up -d dc01
```

View file

@ -0,0 +1,76 @@
# Prérequis
Avant de lancer le lab, vérifie que ton poste est équipé pour faire tourner
plusieurs machines virtuelles en parallèle. Le contrôleur de domaine et le
client Windows sont deux VMs complètes (Windows Server et Windows 11).
## Ressources matérielles
| Ressource | Recommandé | Minimum |
|---|---|---|
| RAM | 16 Go | 12 Go |
| CPU | 4 cœurs | 2 cœurs |
| Disque libre | 150 Go | 80 Go |
| Virtualisation CPU | VT-x ou AMD-V activés dans le BIOS | obligatoire |
## Logiciels requis
- Docker Engine récent (>= 24) avec le plugin Compose v2
- Un client RDP (facultatif mais fortement recommandé)
Installation de Docker selon ton système :
- Linux : paquets `docker` et `docker-compose-plugin` de ta distribution
- Windows : Docker Desktop avec backend WSL2
- macOS Intel : Docker Desktop
- macOS Apple Silicon : non supporté (voir la section dédiée plus bas)
## Cas spécifique macOS Apple Silicon
Les processeurs M1/M2/M3/M4 n'exposent pas de `/dev/kvm` x86. L'image
`dockurr/windows` refuse de démarrer sans KVM, et l'émulation x86 complète
via QEMU TCG est trop lente pour être exploitable.
Solution proposée : installer une VM Linux avec Docker, puis cloner et lancer
le lab dans cette VM. L'outil [UTM](https://mac.getutm.app/) fonctionne bien
pour ça. Tu obtiens une Debian ou une Ubuntu qui hébergera tout le lab, et tu
accèdes aux VMs du lab via RDP depuis ton Mac.
## Vérification automatique
Un script vérifie les points critiques :
```
./scripts/check-prereqs.sh # Linux, macOS
.\scripts\check-prereqs.ps1 # Windows PowerShell
```
Il remonte, pour chaque critère :
- `[ OK ]` : validé
- `[WARN]` : fonctionnel mais dégradé
- `[FAIL]` : bloquant, à corriger avant de continuer
## Configuration Windows spécifique
La virtualisation imbriquée doit être activée dans WSL2. Crée le fichier
`%USERPROFILE%\.wslconfig` avec :
```
[wsl2]
nestedVirtualization=true
memory=16GB
processors=4
```
Puis relance WSL :
```
wsl --shutdown
```
Docker Desktop repartira avec la nested virt disponible.
## Étape suivante
Une fois les prérequis validés, passe à `01-installation-lab.md`.

View file

@ -0,0 +1,86 @@
# Installation du lab
Objectif : récupérer le projet, adapter sa configuration, puis démarrer le
contrôleur de domaine. Les clients (PC01 et linux01) seront démarrés plus tard
dans le parcours.
## Récupérer le projet
```
git clone <url-du-repo> lab_AD_Complet
cd lab_AD_Complet
```
## Adapter la configuration
Le fichier `.env.example` contient toutes les variables (noms, mots de passe,
ressources allouées aux VMs). Copie-le et ouvre-le :
```
cp .env.example .env
```
Modifie au minimum :
- `AD_DOMAIN` et `AD_DOMAIN_NETBIOS` si tu veux un autre nom que `corp.lab`
- `AD_ADMIN_PASSWORD` : doit respecter la politique AD par défaut
(10+ caractères, majuscule, minuscule, chiffre, caractère spécial)
Les autres variables (RAM, CPU, ports) peuvent rester par défaut.
## Vérifier les prérequis
```
./scripts/check-prereqs.sh
```
Corrige les `[FAIL]` avant de continuer.
## Démarrer le contrôleur de domaine
Le lab expose trois services dans `docker-compose.yml` :
- `dc01` : Windows Server (contrôleur de domaine)
- `pc01` : Windows 11 (poste client)
- `linux01` : Debian 12 (poste client)
On démarre uniquement `dc01` pour l'instant :
```
docker compose up -d dc01
```
L'image `dockurr/windows` se télécharge (~1 Go), puis télécharge l'ISO Windows
Server et lance une installation automatisée. Selon ta connexion, l'ensemble
prend entre 20 et 45 minutes.
## Suivre la progression
Deux moyens complémentaires :
- Via les logs du conteneur :
```
docker compose logs -f dc01
```
- Via l'interface web de dockurr :
[http://localhost:8006](http://localhost:8006)
L'interface web affiche la console graphique de la VM. Tu y vois l'installeur
Windows se dérouler en temps réel.
## Accès à DC01
Une fois Windows démarré et un bureau visible dans l'interface web :
- Session web : [http://localhost:8006](http://localhost:8006) (lent, pas de copier-coller fiable)
- Session RDP : `./scripts/rdp-dc.sh` (recommandé)
Identifiants par défaut pour le premier login :
- Utilisateur : `Administrator`
- Mot de passe : valeur de `AD_ADMIN_PASSWORD` dans ton `.env`
## Étape suivante
Le serveur est installé mais il n'est pas encore contrôleur de domaine. La
promotion se fait dans `02-promotion-dc.md`.

View file

@ -0,0 +1,121 @@
# Promouvoir le serveur en contrôleur de domaine
Objectif : transformer le Windows Server fraîchement installé en premier DC
d'une nouvelle forêt Active Directory. On installera aussi le rôle DNS, requis
par AD.
## Ce qu'est AD DS et ce qu'on crée
Une forêt Active Directory est une structure logique qui contient un ou
plusieurs domaines. On va ici créer :
- une nouvelle forêt dont la racine est le domaine configuré (`corp.lab` par
défaut)
- un premier contrôleur de domaine (`DC01`) qui héberge la base AD et le DNS
Le DC est une machine critique : il gère l'authentification, les stratégies de
groupe, les enregistrements DNS internes. En production, on en déploie toujours
au moins deux pour la redondance. Dans ce lab, un seul suffit.
## Préparation
Avant toute chose, on renomme la machine. C'est un geste obligatoire : une
fois promue DC, elle ne pourra plus être renommée sans dépromotion.
### Approche graphique
1. `Paramètres > Système > À propos > Renommer ce PC` (ou `Win + Pause` puis
"Modifier les paramètres")
2. Nouveau nom : `DC01`
3. Redémarrer
### Approche PowerShell
```
Rename-Computer -NewName "DC01" -Restart
```
Si `Rename-Computer` refuse l'authentification sur une install fraîche, passe
par la GUI ou par le registre (voir `troubleshooting.md`).
## Installation des rôles
Après le redémarrage, ouvre une session Administrator.
### Approche graphique
1. Ouvre le `Gestionnaire de serveur`
2. `Gérer > Ajouter des rôles et fonctionnalités`
3. Sélectionne :
- `Services AD DS`
- `Serveur DNS`
4. Laisse les fonctionnalités par défaut, valide et installe
5. Une fois l'installation terminée, clique sur le drapeau
d'avertissement en haut à droite puis sur
`Promouvoir ce serveur en contrôleur de domaine`
### Approche PowerShell
```
Install-WindowsFeature -Name AD-Domain-Services, DNS -IncludeManagementTools
```
## Promotion en contrôleur de domaine
### Approche graphique
1. Dans l'assistant de configuration des services de domaine Active Directory :
2. `Ajouter une nouvelle forêt` > Nom racine : `corp.lab`
3. Niveaux fonctionnels : laisse `Windows Server 2016` (ou la valeur proposée)
4. Coche `Serveur DNS`, `Catalogue global`
5. Saisis un mot de passe DSRM (mode restauration des services d'annuaire)
6. Ignore les avertissements DNS (normaux sur un DC tout neuf)
7. Valide et laisse la machine redémarrer
### Approche PowerShell
```
$dsrmPwd = Read-Host -AsSecureString "Mot de passe DSRM"
Install-ADDSForest `
-DomainName "corp.lab" `
-DomainNetbiosName "CORP" `
-InstallDns `
-SafeModeAdministratorPassword $dsrmPwd `
-Force
```
Cmdlets clés :
- `Install-ADDSForest` crée une nouvelle forêt
- `Install-ADDSDomainController` joint un DC existant à une forêt
(utile quand tu ajoutes un second DC)
## Validation
Après redémarrage, reconnecte-toi (compte `CORP\Administrator` désormais) et
lance :
```
Get-ADDomain
Get-ADForest
dcdiag
```
Les deux premières commandes renvoient les infos du domaine. `dcdiag` exécute
une batterie de tests d'intégrité. Des avertissements DNS mineurs sont normaux
sur un DC isolé.
## Points d'attention
- Le mot de passe DSRM est indépendant de celui d'Administrator. Il sert en
mode de récupération si AD est corrompu. Note-le dans ton gestionnaire de
mots de passe.
- Une fois la machine promue DC, elle ne peut plus être renommée sans d'abord
être dépromotée (`Uninstall-ADDSDomainController`).
- Sur une installation fraîche dockur, la VM a parfois un nom généré
automatiquement (`WIN-xxxx`). Rename **avant** la promotion est crucial.
## Étape suivante
Le DC est prêt, AD est vide. On passe à la création des OU, utilisateurs et
groupes dans `03-ou-utilisateurs-groupes.md`.

View file

@ -0,0 +1,149 @@
# Unités d'organisation, utilisateurs, groupes
Objectif : construire l'arborescence AD (OU), peupler le domaine avec des
utilisateurs et des groupes, et appliquer l'imbrication AGDLP recommandée par
Microsoft.
## Qu'est-ce qu'une OU
Une unité d'organisation (Organizational Unit) est un conteneur logique qui
permet de regrouper des objets AD (utilisateurs, ordinateurs, groupes) pour
leur appliquer des stratégies, déléguer leur administration, ou les organiser.
Une OU n'accorde aucun droit en soi. C'est un outil de structuration.
## Arborescence proposée
```
corp.lab
└── CORP
├── Utilisateurs
│ ├── Direction
│ ├── Pedagogie
│ ├── Informatique
│ ├── Administration
│ └── Etudiants
├── Ordinateurs
│ └── (mêmes sous-OU)
├── Groupes
└── Services
```
Tu peux calquer cette structure ou l'adapter à ton contexte.
## Création des OU
### Approche graphique
1. Ouvrir `Utilisateurs et ordinateurs Active Directory` (`dsa.msc`)
2. Clic droit sur le domaine > `Nouveau > Unité d'organisation`
3. Nommer `CORP`
4. Dans `CORP`, créer les sous-OU `Utilisateurs`, `Ordinateurs`, `Groupes`, `Services`
5. Créer les OU départementales sous `Utilisateurs` et `Ordinateurs`
### Approche PowerShell
Cmdlet clé : `New-ADOrganizationalUnit`.
```
New-ADOrganizationalUnit -Name "CORP" -Path "DC=corp,DC=lab"
New-ADOrganizationalUnit -Name "Utilisateurs" -Path "OU=CORP,DC=corp,DC=lab"
```
Boucle pour créer les départements :
```
$deps = @("Direction","Pedagogie","Informatique","Administration","Etudiants")
foreach ($d in $deps) {
New-ADOrganizationalUnit -Name $d -Path "OU=Utilisateurs,OU=CORP,DC=corp,DC=lab"
}
```
## Création des utilisateurs
### Approche graphique
1. Clic droit sur l'OU département > `Nouveau > Utilisateur`
2. Remplir les champs (Nom, Prénom, SamAccountName, UPN)
3. Mot de passe initial, cocher `L'utilisateur doit changer de mot de passe à la prochaine ouverture de session`
### Approche PowerShell
Cmdlet clé : `New-ADUser`.
```
New-ADUser `
-Name "Paul Martin" `
-GivenName "Paul" `
-Surname "Martin" `
-SamAccountName "pmartin" `
-UserPrincipalName "pmartin@corp.lab" `
-Path "OU=Pedagogie,OU=Utilisateurs,OU=CORP,DC=corp,DC=lab" `
-AccountPassword (ConvertTo-SecureString "UserP@ss!2026" -AsPlainText -Force) `
-Enabled $true `
-ChangePasswordAtLogon $true
```
## Création des groupes
Deux types de groupes vont nous servir :
- **Groupes globaux (GG)** : regroupent des utilisateurs par département,
projet, fonction. Exemples : `GG_Pedagogie`, `GG_Etudiants`.
- **Groupes de domaine locaux (DL)** : se voient attribuer les permissions
sur les ressources. Exemples : `DL_Partage_Commun_R`, `DL_Partage_Pedago_RW`.
### Approche graphique
1. Clic droit sur `OU=Groupes` > `Nouveau > Groupe`
2. Portée : `Global` ou `Domaine local` selon le cas
3. Type : `Sécurité`
### Approche PowerShell
Cmdlet clé : `New-ADGroup`.
```
New-ADGroup -Name "GG_Pedagogie" -GroupScope Global -GroupCategory Security `
-Path "OU=Groupes,OU=CORP,DC=corp,DC=lab"
New-ADGroup -Name "DL_Partage_Commun_R" -GroupScope DomainLocal -GroupCategory Security `
-Path "OU=Groupes,OU=CORP,DC=corp,DC=lab"
```
## Appliquer l'imbrication AGDLP
AGDLP est une convention Microsoft :
- **A**ccount (utilisateur) dans
- **G**lobal group (département) membre de
- **D**omain **L**ocal group (ressource) qui détient la
- **P**ermission
Concrètement :
1. Ajoute les utilisateurs aux groupes globaux correspondants
2. Ajoute les groupes globaux aux groupes de domaine local correspondants
3. Pose les permissions NTFS/partages sur les groupes de domaine local
Cmdlet clé : `Add-ADGroupMember`.
```
Add-ADGroupMember -Identity "GG_Pedagogie" -Members "pmartin"
Add-ADGroupMember -Identity "DL_Partage_Commun_R" -Members "GG_Pedagogie","GG_Etudiants"
```
## Validation
```
Get-ADUser -Filter * -SearchBase "OU=CORP,DC=corp,DC=lab" | Select Name, SamAccountName
Get-ADGroup -Filter * -SearchBase "OU=Groupes,OU=CORP,DC=corp,DC=lab" | Select Name, GroupScope
Get-ADGroupMember -Identity "GG_Pedagogie"
```
Côté graphique, la console `dsa.msc` doit afficher la hiérarchie créée, les
utilisateurs dans leurs OU, et les membres des groupes.
## Étape suivante
L'AD est peuplé. On passe aux stratégies de groupe dans `04-gpo.md`.

130
docs/etudiant/fr/04-gpo.md Normal file
View file

@ -0,0 +1,130 @@
# Stratégies de groupe (GPO)
Objectif : créer et lier quelques GPO représentatives d'un cas réel.
## Ce qu'est une GPO
Une stratégie de groupe (Group Policy Object) est un ensemble de paramètres
qui s'appliquent aux utilisateurs ou aux ordinateurs. Elle s'écrit dans
`SYSVOL` (stocké sur les DC) et se synchronise sur toutes les machines jointes
au domaine.
Deux portées principales :
- `Configuration ordinateur` : s'applique quand la machine démarre
- `Configuration utilisateur` : s'applique quand un utilisateur ouvre session
Une GPO est **liée** à un conteneur (site, domaine, OU). Les objets situés dans
ce conteneur et ses descendants héritent de la GPO. On utilise donc les OU
pour cibler : tu peux lier une GPO à l'OU `Etudiants` et elle ne s'appliquera
qu'aux utilisateurs de cette OU.
## Scénarios à mettre en place
Pour ce lab, on va créer trois GPO typiques :
1. Durcir la politique de mot de passe du domaine
2. Imposer un fond d'écran aux étudiants
3. Restreindre l'accès au Panneau de configuration pour les étudiants
## Politique de mot de passe
Stockée dans la `Default Domain Policy`, elle s'applique à tout le domaine.
### Approche graphique
1. Ouvrir la console `Gestion des stratégies de groupe` (`gpmc.msc`)
2. Domaine > `Default Domain Policy` > clic droit > `Modifier`
3. `Configuration ordinateur > Stratégies > Paramètres Windows > Paramètres de sécurité > Stratégies de compte > Stratégie de mot de passe`
4. Ajuste les paramètres : longueur minimale, complexité, historique, durée
### Approche PowerShell
Cmdlet clé : `Set-ADDefaultDomainPasswordPolicy`.
```
Set-ADDefaultDomainPasswordPolicy -Identity corp.lab `
-MinPasswordLength 10 `
-ComplexityEnabled $true `
-PasswordHistoryCount 5 `
-MaxPasswordAge (New-TimeSpan -Days 90) `
-LockoutThreshold 5 `
-LockoutDuration (New-TimeSpan -Minutes 15)
```
## GPO "fond d'écran imposé"
### Approche graphique
1. `gpmc.msc` > Domaine > clic droit sur `OU=Etudiants,OU=Utilisateurs,OU=CORP` > `Créer un objet GPO dans ce domaine et le lier ici`
2. Nomme la GPO (ex : `GPO_Etudiants_FondEcran`)
3. Clic droit sur la GPO > `Modifier`
4. `Configuration utilisateur > Stratégies > Modèles d'administration > Bureau > Bureau`
5. Paramètre `Papier peint du bureau` > `Activé`, renseigne le chemin de
l'image (ex: `C:\Windows\Web\Wallpaper\Windows\img0.jpg`) et le style
### Approche PowerShell
Cmdlets clés : `New-GPO`, `New-GPLink`, `Set-GPRegistryValue`.
```
New-GPO -Name "GPO_Etudiants_FondEcran"
Set-GPRegistryValue -Name "GPO_Etudiants_FondEcran" `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "Wallpaper" -Type String -Value "C:\Windows\Web\Wallpaper\Windows\img0.jpg"
New-GPLink -Name "GPO_Etudiants_FondEcran" `
-Target "OU=Etudiants,OU=Utilisateurs,OU=CORP,DC=corp,DC=lab"
```
## GPO "restriction du Panneau de configuration"
### Approche graphique
Même démarche que ci-dessus, paramètre :
`Configuration utilisateur > Stratégies > Modèles d'administration > Panneau de configuration > Interdire l'accès au Panneau de configuration et aux paramètres du PC > Activé`
### Approche PowerShell
```
New-GPO -Name "GPO_Etudiants_RestrictionsPC"
Set-GPRegistryValue -Name "GPO_Etudiants_RestrictionsPC" `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" `
-ValueName "NoControlPanel" -Type DWord -Value 1
New-GPLink -Name "GPO_Etudiants_RestrictionsPC" `
-Target "OU=Etudiants,OU=Utilisateurs,OU=CORP,DC=corp,DC=lab"
```
## Tester l'application
Sur un poste client où un étudiant est connecté :
```
gpupdate /force
gpresult /r
```
`gpresult` liste les GPO effectivement appliquées. Si ta GPO n'apparaît pas,
vérifie :
- l'utilisateur est bien dans la bonne OU ?
- la GPO est liée à la bonne OU ?
- l'utilisateur a `ApplyGroupPolicy` comme droit (filtrage de sécurité) ?
- la GPO n'est pas filtrée par WMI ?
## Points d'attention
- Évite de modifier la `Default Domain Policy` au-delà de la politique de mot
de passe. Pour le reste, crée toujours une GPO dédiée.
- L'ordre d'application des GPO est : Local > Site > Domaine > OU
(la plus proche l'emporte en cas de conflit).
- Le blocage d'héritage (`Block Inheritance`) sur une OU fille casse la chaîne.
Utilise-le avec parcimonie.
## Étape suivante
`05-partages-ntfs.md` pour les partages SMB et les permissions NTFS.

View file

@ -0,0 +1,120 @@
# Partages SMB et permissions NTFS
Objectif : exposer trois partages réseau sur `DC01`, les sécuriser avec les
groupes AD créés précédemment, et vérifier que les permissions s'appliquent
bien selon l'utilisateur connecté.
Note : dans un environnement de production on héberge les partages sur un
serveur de fichiers dédié, pas sur un DC. Dans ce lab on simplifie.
## Partages à créer
| Partage | Chemin | Accès |
|---|---|---|
| `Commun` | `C:\Partages\Commun` | lecture pour tout le monde, écriture pour Direction/Pédago/Admin |
| `Pedago` | `C:\Partages\Pedago` | accès restreint à GG_Pedagogie |
| `Direction` | `C:\Partages\Direction` | accès restreint à GG_Direction |
## Rappel AGDLP
Les permissions ne sont **jamais** posées sur des groupes globaux ou sur des
utilisateurs directement. Elles sont attribuées à un **groupe de domaine
local**, dans lequel on ajoute les groupes globaux concernés.
Exemple pour le partage `Commun` :
- Groupes globaux : `GG_Pedagogie`, `GG_Etudiants`, ...
- Groupes DL : `DL_Partage_Commun_R` (lecture), `DL_Partage_Commun_RW` (écriture)
- Permissions NTFS : posées sur `DL_Partage_Commun_R` et `DL_Partage_Commun_RW`
- Imbrication :
- `GG_Etudiants` membre de `DL_Partage_Commun_R`
- `GG_Pedagogie` membre de `DL_Partage_Commun_RW`
## Création des dossiers et partages
### Approche graphique
1. Dans l'Explorateur, crée `C:\Partages\Commun`
2. Clic droit > `Propriétés > Partage > Partage avancé`
3. Coche `Partager ce dossier`, nomme le partage, clique `Autorisations`
4. Par défaut, retire `Tout le monde`
5. Ajoute les groupes AD souhaités avec les droits (Lecture, Modifier, Contrôle total)
6. Onglet `Sécurité` > `Modifier` : définis les ACL NTFS
7. Décoche l'héritage si tu veux une ACL explicite
### Approche PowerShell
Cmdlets clés : `New-SmbShare`, `Get-Acl`, `Set-Acl`, `FileSystemAccessRule`.
```
# Dossiers
New-Item -Path C:\Partages\Commun -ItemType Directory -Force
# Partage SMB avec droits de partage
New-SmbShare -Name "Commun" -Path "C:\Partages\Commun" `
-FullAccess "CORP\Domain Admins" `
-ReadAccess "CORP\DL_Partage_Commun_R" `
-ChangeAccess "CORP\DL_Partage_Commun_RW"
```
Permissions NTFS :
```
$acl = Get-Acl "C:\Partages\Commun"
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"CORP\DL_Partage_Commun_R", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl "C:\Partages\Commun" $acl
```
Reproduis pour chaque couple (DL, droits).
## Tester depuis un client Windows
Sur `PC01`, connecté en tant qu'utilisateur AD :
```
\\DC01\Commun
```
via `Exécuter` (`Win + R`) ou la barre d'adresse de l'Explorateur.
Tests à faire :
- avec un membre de `GG_Etudiants` : lecture OK, écriture refusée
- avec un membre de `GG_Pedagogie` : lecture et écriture OK
- tentative d'accès à `\\DC01\Pedago` depuis un étudiant : refus attendu
## Tester depuis le client Linux
Si `linux01` est joint au domaine (voir `07-jonction-poste-linux.md`) :
```
smbclient //DC01/Commun -U pmartin%<mot_de_passe>
# une fois connecté :
ls
put /etc/hostname
```
ou via `cifs-utils` pour un montage :
```
mkdir /mnt/commun
mount -t cifs //DC01/Commun /mnt/commun -o username=pmartin,domain=CORP
```
## Points d'attention
- Les **deux** couches de permissions (Partage et NTFS) s'appliquent. L'accès
effectif est l'intersection (la plus restrictive l'emporte). Bonne pratique :
mettre `Contrôle total` au niveau du partage, puis affiner via NTFS.
- Un utilisateur déjà connecté ne "voit" pas immédiatement une modification
d'appartenance à un groupe AD. Il doit se déconnecter / reconnecter (ou
relancer `klist purge`).
- Ne pose jamais d'ACL directement sur un utilisateur. Si la personne quitte,
les ACL deviennent du ménage à faire à la main.
## Étape suivante
`06-jonction-poste-windows.md` pour joindre `PC01` au domaine et tester ces
partages depuis un poste client.

View file

@ -0,0 +1,166 @@
# Joindre le poste Windows au domaine
Objectif : démarrer le conteneur `pc01`, installer Windows 11, puis joindre la
machine au domaine `corp.lab`.
## Démarrer le conteneur
```
docker compose up -d pc01
```
L'installation Windows 11 se déroule en automatique, même principe que pour
`DC01`. Compte 20 à 40 minutes. Suis la progression via :
- [http://localhost:8009](http://localhost:8009) (port web de `pc01`)
- `docker compose logs -f pc01`
Une fois le bureau accessible, utilise RDP pour la suite :
```
./scripts/rdp-client.sh
```
Identifiants locaux : `LocalAdmin` / `AD_ADMIN_PASSWORD` (même valeur que pour
DC01 dans ce lab).
## Étape 1 : préparer le client
### Renommer la machine
Les installs dockurr partent avec un hostname généré (`WIN-xxxxxxx`). On le
change avant de joindre. Approche graphique via `Paramètres > Système > À
propos > Renommer ce PC`, ou PowerShell :
```
Rename-Computer -NewName "PC01" -Restart
```
### Pointer le DNS vers le DC
Sans DNS correct, la jonction échoue. PC01 doit interroger `DC01` pour
résoudre `corp.lab` et les enregistrements SRV d'AD.
Approche graphique : `Paramètres > Réseau > Propriétés de la carte réseau >
Modifier les paramètres DNS`.
Approche PowerShell :
```
Get-NetAdapter | Format-Table Name, Status
# Remplace "Ethernet" par le nom de ta carte
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses <IP_du_DC>
```
Pour déterminer l'IP à utiliser, voir le bloc "Spécificité du lab Docker"
ci-dessous.
### Spécificité du lab Docker
`dockurr/windows` fait tourner Windows dans une VM avec NAT interne. L'IP que
le DC annonce dans son DNS est son IP interne VM (non routable depuis
`PC01`). Mais le conteneur DC dispose d'une règle DNAT qui forwarde tous les
ports vers la VM.
Solution : utilise l'IP du **conteneur** `DC01` (celle visible via
`docker inspect lab-dc01`) et ajoute une entrée `hosts` pour que la résolution
retombe dessus.
Dans PowerShell (PC01) :
```
# Remplacer <IP_CONTAINER_DC> par celle retournée côté hôte par :
# docker inspect lab-dc01 --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
Add-Content C:\Windows\System32\drivers\etc\hosts "`n<IP_CONTAINER_DC> corp.lab dc01.corp.lab dc01"
ipconfig /flushdns
```
Test :
```
Test-NetConnection -ComputerName corp.lab -Port 389
nslookup corp.lab
```
## Étape 2 : joindre au domaine
### Approche graphique
1. `Paramètres > Système > À propos > Joindre un domaine`
2. Ou via `sysdm.cpl > Modifier`
3. Saisir `corp.lab`, valider
4. Entrer les identifiants `CORP\Administrator`
5. Redémarrer quand demandé
### Approche PowerShell
Cmdlet clé : `Add-Computer`.
```
$pass = ConvertTo-SecureString "AdminP@ss!2026" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("CORP\Administrator", $pass)
Add-Computer -DomainName corp.lab -Credential $cred -Restart
```
## Étape 3 : autoriser un utilisateur AD à se connecter en RDP
Par défaut, seuls les membres du groupe local `Administrateurs` peuvent
ouvrir une session RDP. Après jonction au domaine, le groupe local
`Administrateurs` contient `CORP\Domain Admins`, donc un admin de domaine
peut RDP. Mais les utilisateurs standards doivent être ajoutés explicitement.
### Approche graphique
1. Clic droit sur `Ce PC > Propriétés > Paramètres d'utilisation à distance`
2. `Sélectionner les utilisateurs` > Ajouter `CORP\pmartin` (ou un groupe AD)
### Approche PowerShell
```
Add-LocalGroupMember -Group "Utilisateurs du Bureau à distance" -Member "CORP\pmartin"
```
En pratique, crée un groupe AD dédié (par exemple `GG_UtilisateursRDP`) et
ajoute-le via GPO au groupe local de toutes les machines.
## Étape 4 : tester la connexion en utilisateur AD
Depuis l'hôte Linux/macOS :
```
xfreerdp3 /v:127.0.0.1:3391 /u:pmartin /d:CORP /p:'<mdp>' /cert:ignore +clipboard /size:1600x900 /dynamic-resolution
```
Sous Windows, utilise `mstsc` et saisis `CORP\pmartin`.
Une fois connecté, valide :
```
whoami
whoami /groups
Get-ComputerInfo | Select CsDomain, CsDomainRole
```
Tu dois voir :
- `CORP\pmartin`
- les groupes AD de l'utilisateur
- `CsDomainRole : MemberWorkstation`
## Points d'attention
- Un compte avec l'option "changement de mot de passe au prochain login" ne
peut pas se connecter via RDP avec NLA. Soit tu désactives l'option côté DC
(`Set-ADUser -ChangePasswordAtLogon $false`), soit tu forces un premier
login via `/sec:rdp` pour afficher la page de changement.
- Si tu rencontres `Le mappage entre les noms de compte et les ID de sécurité
n'a pas été effectué` lors d'un `Add-Computer`, le PC a un état AD corrompu.
Repasse en workgroup via `Add-Computer -WorkgroupName "WORKGROUP" -Force`
puis recommence.
- Ne laisse pas traîner des comptes d'ordinateur orphelins : quand tu
recrées `PC01`, pense à supprimer l'entrée dans `CN=Computers`.
## Étape suivante
`07-jonction-poste-linux.md` pour faire la même chose côté Linux.

View file

@ -0,0 +1,144 @@
# Joindre le poste Linux au domaine
Objectif : configurer le client Debian `linux01` pour qu'il s'authentifie
auprès de l'AD, et valider la résolution des utilisateurs et groupes AD.
La stack utilisée est la stack standard sur Debian/Ubuntu/RHEL :
- `realmd` : outil de découverte et d'adhésion à un domaine
- `sssd` : démon qui gère l'intégration (cache, Kerberos, NSS, PAM)
- `adcli` : client de bas niveau pour AD
- `krb5` : couche Kerberos
Tous ces paquets sont déjà présents dans l'image (voir
`linux-client/Dockerfile`).
## Démarrer le conteneur
```
docker compose up -d linux01
docker exec -it lab-linux01 bash
```
Le point d'entrée configure automatiquement `/etc/resolv.conf` pour pointer
vers l'IP du conteneur `DC01` et ajoute des entrées `hosts` pour les noms AD.
Vérifie :
```
cat /etc/resolv.conf
cat /etc/hosts | tail
ping -c 2 corp.lab
```
## Découverte du domaine
Cmdlet clé : `realm discover`.
```
realm discover corp.lab
```
Tu dois voir une réponse structurée indiquant `type: kerberos` et
`server-software: active-directory`.
Si tu n'as rien, vérifie la résolution DNS : le DC doit répondre au port 53
sur l'IP utilisée.
## Jonction au domaine
Cmdlet clé : `realm join`.
```
realm join -U Administrator corp.lab
# Saisir le mot de passe de CORP\Administrator quand demandé
```
Sous le capot, `realmd` :
1. Crée un compte ordinateur `LINUX01` dans `CN=Computers`
2. Génère un keytab Kerberos dans `/etc/krb5.keytab`
3. Configure `/etc/sssd/sssd.conf`
4. Active `sssd` pour les bases NSS (passwd, group) et PAM
## Démarrer sssd
Dans un conteneur, systemd n'est pas toujours disponible. On lance sssd
directement :
```
sssd --daemon
```
## Validation
Résolution NSS :
```
id pmartin@corp.lab
getent passwd pmartin@corp.lab
getent group 'GG_Pedagogie@corp.lab'
```
Tu dois voir :
- un UID attribué par sssd (grosse valeur, dérivée du SID)
- la liste des groupes AD de l'utilisateur, incluant l'imbrication AGDLP
Authentification Kerberos :
```
kinit pmartin@CORP.LAB
klist
```
`klist` doit afficher un TGT (Ticket Granting Ticket) valide.
## Se connecter en SSH avec un compte AD
Si tu as activé SSH dans le conteneur (c'est le cas par défaut avec le
Dockerfile fourni), depuis l'hôte :
```
ssh pmartin@lab-linux01
# ou l'IP du conteneur
```
Le home directory est créé automatiquement au premier login grâce au module
`pam_mkhomedir` configuré dans l'entrypoint.
## Limiter l'accès à certains groupes AD
Par défaut, tous les utilisateurs AD peuvent se connecter. Pour restreindre :
```
realm permit -g "GG_Pedagogie@corp.lab"
```
ou l'inverse (tout interdire sauf exception) via le fichier
`/etc/sssd/sssd.conf`.
## Points d'attention
- `realm join` échoue si la résolution DNS est mauvaise ou si l'heure du
client dérive de plus de 5 minutes par rapport au DC. Sur un conteneur
fraîchement démarré, l'heure est celle de l'hôte, ça suffit.
- Dans ce lab, la résolution DNS est rusée : le DC annonce une IP interne
non routable. On contourne via `/etc/hosts`. En production, tu aurais le DC
directement joignable sur le réseau.
- `sssd` cache les utilisateurs pendant 6h par défaut. Si tu modifies un
groupe côté AD et que l'effet ne se voit pas, lance `sss_cache -E` ou
redémarre `sssd`.
## Quitter le domaine
```
realm leave corp.lab
```
Le compte ordinateur est supprimé côté DC, le keytab retiré, sssd désactivé.
## Étape suivante
Le lab est complètement opérationnel. Consulte `troubleshooting.md` en cas de
souci.

View file

@ -0,0 +1,156 @@
# Résolution des problèmes courants
Ce document recense les pièges rencontrés lors de la mise en place du lab.
## Installation Windows bloquée
Symptôme : l'interface http://localhost:8006 reste sur l'écran de
téléchargement de l'ISO.
Causes possibles :
- Connexion internet lente ou coupée (l'ISO pèse plusieurs Go)
- Stockage insuffisant sur le disque hôte
- Filesystem `btrfs` sur le volume `/storage` (dockurr le signale, rarement
bloquant en lab)
Vérifie `docker compose logs -f dc01` et relance si besoin.
## /dev/kvm inaccessible
Symptôme : `KVM acceleration not available` dans les logs dockurr.
Causes :
- Virtualisation désactivée dans le BIOS
- Ton utilisateur pas dans le groupe `kvm`
- WSL2 sans virtualisation imbriquée (Windows)
Solutions :
- Linux : `sudo usermod -aG kvm $USER` puis reconnexion
- Windows : éditer `%USERPROFILE%\.wslconfig` avec `nestedVirtualization=true`
- macOS Apple Silicon : non supporté, utilise UTM
## Rename-Computer refuse l'auth
Symptôme : `Rename-Computer : ... Le nom d'utilisateur ou le mot de passe est incorrect.`
Ça arrive sur une installation fraîche, avant même toute jonction domaine. Le
cmdlet tente une authentification locale qui échoue pour une raison obscure.
Solutions :
- Utiliser la GUI : `sysdm.cpl > Modifier`
- Passer par le registre :
```
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "Hostname" -Value "NOUVEAU"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "NV Hostname" -Value "NOUVEAU"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName" -Name "ComputerName" -Value "NOUVEAU"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName" -Name "ComputerName" -Value "NOUVEAU"
Restart-Computer -Force
```
## Add-Computer : "l'ordinateur se trouve déjà dans ce domaine"
Le PC a un état domaine partiel (suffixe DNS, workgroup portant le même nom
que le NetBIOS du domaine, jonction antérieure). Sort d'abord proprement :
```
Add-Computer -WorkgroupName "WORKGROUP" -Force
Restart-Computer -Force
```
Si `Remove-Computer` échoue avec `Le mappage entre les noms de compte et les
ID de sécurité n'a pas été effectué`, force via WMI :
```
$cs = Get-WmiObject Win32_ComputerSystem
$cs.UnjoinDomainOrWorkgroup($null, $null, 0)
Restart-Computer -Force
```
## RDP refuse l'utilisateur AD
Symptôme : `ERRCONNECT_CONNECT_TRANSPORT_FAILED` après NLA côté freerdp, ou
"accès refusé" côté mstsc.
Cause : par défaut, seul le groupe local `Administrateurs` a le droit RDP.
Les utilisateurs du domaine ne l'ont pas.
Solution sur le poste :
```
Add-LocalGroupMember -Group "Utilisateurs du Bureau à distance" -Member "CORP\pmartin"
```
En production, on le pousse via GPO sur toutes les machines.
## "Le mot de passe doit être changé" via freerdp
Symptôme : `ERRCONNECT_PASSWORD_MUST_CHANGE`.
freerdp avec NLA ne sait pas afficher l'écran de changement. Deux options :
- Désactiver la mention côté DC :
```
Set-ADAccountPassword -Identity pmartin -Reset -NewPassword (ConvertTo-SecureString "NewP@ss!2026" -AsPlainText -Force)
Set-ADUser -Identity pmartin -ChangePasswordAtLogon $false
```
- Ou bypass NLA :
```
xfreerdp3 /sec:rdp ...
```
## realm discover ne répond rien
Causes :
- Le conteneur `linux01` n'a pas le bon DNS (vérifier `/etc/resolv.conf`)
- Le DC ne répond pas sur le port 53
- `dbus` n'est pas démarré dans le conteneur :
```
dbus-daemon --system --fork
```
## sssd ne démarre pas
Symptôme : `Invalid option -f: unknown option` quand `realm join` lance
`service sssd restart`.
Contexte : les images docker sans init complet (pas de systemd). Lance sssd
manuellement :
```
/usr/sbin/sssd --daemon
```
## L'utilisateur AD n'est pas résolu côté Linux
```
id pmartin@corp.lab
# "no such user"
```
Causes fréquentes :
- sssd pas démarré (voir ci-dessus)
- Cache sssd désynchronisé : `sss_cache -E`
- Le domaine n'apparaît pas dans `realm list` : la jonction a échoué
silencieusement, relance `realm join -v`
## Partage inaccessible depuis un client
- L'utilisateur n'est pas membre du groupe DL : `Get-ADGroupMember DL_Partage_Commun_R`
- Le token Kerberos n'a pas été rafraîchi : déconnexion / reconnexion
- ACL NTFS restrictive : vérifier via `Get-Acl` ou onglet Sécurité
## Reset complet du lab
Pour repartir de zéro sans toucher au reste de ton système :
```
docker compose down -v
rm -rf ./storage-dc01 ./storage-pc01
docker compose up -d dc01
```

View file

@ -0,0 +1,71 @@
# Corrigé - création de l'arborescence AD (OU, utilisateurs, groupes, AGDLP)
# Usage formateur uniquement. A executer sur DC01 apres promotion.
# Fait par AcadéNice - https://acadenice.fr/
$Domain = "corp.lab"
$DomainDN = "DC=corp,DC=lab"
$DefaultPw = ConvertTo-SecureString "UserP@ss!2026" -AsPlainText -Force
Import-Module ActiveDirectory
# Racine
New-ADOrganizationalUnit -Name "CORP" -Path $DomainDN -ProtectedFromAccidentalDeletion $false -ErrorAction SilentlyContinue
$Root = "OU=CORP,$DomainDN"
foreach ($sub in @("Utilisateurs","Groupes","Ordinateurs","Services")) {
New-ADOrganizationalUnit -Name $sub -Path $Root -ProtectedFromAccidentalDeletion $false -ErrorAction SilentlyContinue
}
$Departements = @("Direction","Pedagogie","Informatique","Administration","Etudiants")
foreach ($d in $Departements) {
New-ADOrganizationalUnit -Name $d -Path "OU=Utilisateurs,$Root" -ProtectedFromAccidentalDeletion $false -ErrorAction SilentlyContinue
New-ADOrganizationalUnit -Name $d -Path "OU=Ordinateurs,$Root" -ProtectedFromAccidentalDeletion $false -ErrorAction SilentlyContinue
}
# Groupes
$Groupes = @(
@{Name="GG_Direction"; Scope="Global"; Desc="Direction"}
@{Name="GG_Pedagogie"; Scope="Global"; Desc="Pédagogie"}
@{Name="GG_Informatique"; Scope="Global"; Desc="Informatique"}
@{Name="GG_Administration"; Scope="Global"; Desc="Administration"}
@{Name="GG_Etudiants"; Scope="Global"; Desc="Étudiants"}
@{Name="DL_Partage_Commun_R"; Scope="DomainLocal"; Desc="Lecture partage commun"}
@{Name="DL_Partage_Commun_RW"; Scope="DomainLocal"; Desc="Ecriture partage commun"}
@{Name="DL_Partage_Pedago_RW"; Scope="DomainLocal"; Desc="Ecriture partage pédago"}
@{Name="DL_Partage_Direction"; Scope="DomainLocal"; Desc="Accès partage direction"}
)
foreach ($g in $Groupes) {
New-ADGroup -Name $g.Name -GroupScope $g.Scope -GroupCategory Security `
-Path "OU=Groupes,$Root" -Description $g.Desc -ErrorAction SilentlyContinue
}
# Utilisateurs
$Users = @(
@{First="Marie"; Last="Durand"; Dept="Direction"; Title="Directrice"}
@{First="Paul"; Last="Martin"; Dept="Pedagogie"; Title="Responsable pédagogique"}
@{First="Julie"; Last="Leroy"; Dept="Pedagogie"; Title="Formatrice"}
@{First="Admin"; Last="Sys"; Dept="Informatique"; Title="Admin systèmes"}
@{First="Sophie"; Last="Bernard"; Dept="Administration"; Title="Secrétaire"}
@{First="Lucas"; Last="Petit"; Dept="Etudiants"; Title="Étudiant"}
@{First="Emma"; Last="Moreau"; Dept="Etudiants"; Title="Étudiante"}
@{First="Thomas"; Last="Dubois"; Dept="Etudiants"; Title="Étudiant"}
)
foreach ($u in $Users) {
$sam = ($u.First.Substring(0,1) + $u.Last).ToLower()
New-ADUser -Name "$($u.First) $($u.Last)" `
-GivenName $u.First -Surname $u.Last `
-SamAccountName $sam -UserPrincipalName "$sam@$Domain" `
-Title $u.Title -Department $u.Dept `
-Path "OU=$($u.Dept),OU=Utilisateurs,$Root" `
-AccountPassword $DefaultPw -Enabled $true `
-ChangePasswordAtLogon $true -ErrorAction SilentlyContinue
Add-ADGroupMember -Identity "GG_$($u.Dept)" -Members $sam -ErrorAction SilentlyContinue
}
# Imbrications AGDLP
Add-ADGroupMember -Identity "DL_Partage_Commun_R" -Members "GG_Etudiants","GG_Pedagogie","GG_Administration","GG_Direction" -ErrorAction SilentlyContinue
Add-ADGroupMember -Identity "DL_Partage_Commun_RW" -Members "GG_Pedagogie","GG_Administration","GG_Direction" -ErrorAction SilentlyContinue
Add-ADGroupMember -Identity "DL_Partage_Pedago_RW" -Members "GG_Pedagogie" -ErrorAction SilentlyContinue
Add-ADGroupMember -Identity "DL_Partage_Direction" -Members "GG_Direction" -ErrorAction SilentlyContinue
Write-Host "Peuplement AD termine."

View file

@ -0,0 +1,43 @@
# Corrigé - création des GPO du lab.
# Usage formateur uniquement.
# Fait par AcadéNice - https://acadenice.fr/
Import-Module GroupPolicy
Import-Module ActiveDirectory
$DomainDN = (Get-ADDomain).DistinguishedName
$Root = "OU=CORP,$DomainDN"
$Domain = (Get-ADDomain).DNSRoot
# Politique de mot de passe (Default Domain Policy)
Set-ADDefaultDomainPasswordPolicy -Identity $Domain `
-MinPasswordLength 10 `
-PasswordHistoryCount 5 `
-ComplexityEnabled $true `
-MaxPasswordAge (New-TimeSpan -Days 90) `
-MinPasswordAge (New-TimeSpan -Days 1) `
-LockoutThreshold 5 `
-LockoutDuration (New-TimeSpan -Minutes 15) `
-LockoutObservationWindow (New-TimeSpan -Minutes 15)
# Fond d'ecran etudiants
$gpo1 = New-GPO -Name "GPO_Etudiants_FondEcran" -Comment "Fond d'écran imposé aux étudiants" -ErrorAction SilentlyContinue
Set-GPRegistryValue -Name "GPO_Etudiants_FondEcran" `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "Wallpaper" -Type String -Value "C:\Windows\Web\Wallpaper\Windows\img0.jpg"
Set-GPRegistryValue -Name "GPO_Etudiants_FondEcran" `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "WallpaperStyle" -Type String -Value "2"
New-GPLink -Name "GPO_Etudiants_FondEcran" -Target "OU=Etudiants,OU=Utilisateurs,$Root" -LinkEnabled Yes -ErrorAction SilentlyContinue
# Restriction Panneau de configuration
$gpo2 = New-GPO -Name "GPO_Etudiants_RestrictionsPC" -ErrorAction SilentlyContinue
Set-GPRegistryValue -Name "GPO_Etudiants_RestrictionsPC" `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" `
-ValueName "NoControlPanel" -Type DWord -Value 1
Set-GPRegistryValue -Name "GPO_Etudiants_RestrictionsPC" `
-Key "HKCU\Software\Policies\Microsoft\Windows\System" `
-ValueName "DisableCMD" -Type DWord -Value 2
New-GPLink -Name "GPO_Etudiants_RestrictionsPC" -Target "OU=Etudiants,OU=Utilisateurs,$Root" -LinkEnabled Yes -ErrorAction SilentlyContinue
Write-Host "GPO créées. Relance gpupdate /force sur les clients pour appliquer."

View file

@ -0,0 +1,40 @@
# Corrigé - creation des partages SMB et NTFS.
# Usage formateur uniquement.
# Fait par AcadéNice - https://acadenice.fr/
Import-Module SmbShare
$Base = "C:\Partages"
foreach ($p in @("$Base","$Base\Commun","$Base\Pedago","$Base\Direction")) {
New-Item -Path $p -ItemType Directory -Force | Out-Null
}
$Nb = (Get-ADDomain).NetBIOSName
New-SmbShare -Name "Commun" -Path "$Base\Commun" `
-FullAccess "$Nb\Domain Admins" `
-ReadAccess "$Nb\DL_Partage_Commun_R" `
-ChangeAccess "$Nb\DL_Partage_Commun_RW" -ErrorAction SilentlyContinue
New-SmbShare -Name "Pedago" -Path "$Base\Pedago" `
-FullAccess "$Nb\Domain Admins" `
-ChangeAccess "$Nb\DL_Partage_Pedago_RW" -ErrorAction SilentlyContinue
New-SmbShare -Name "Direction" -Path "$Base\Direction" `
-FullAccess "$Nb\Domain Admins","$Nb\DL_Partage_Direction" -ErrorAction SilentlyContinue
function Set-FolderAcl {
param($Path, $Group, $Rights)
$acl = Get-Acl $Path
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"$Nb\$Group", $Rights, "ContainerInherit,ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl -Path $Path -AclObject $acl
}
Set-FolderAcl "$Base\Commun" "DL_Partage_Commun_R" "ReadAndExecute"
Set-FolderAcl "$Base\Commun" "DL_Partage_Commun_RW" "Modify"
Set-FolderAcl "$Base\Pedago" "DL_Partage_Pedago_RW" "Modify"
Set-FolderAcl "$Base\Direction" "DL_Partage_Direction" "Modify"
Write-Host "Partages et ACL appliques."

View file

@ -0,0 +1,22 @@
# Corrigés formateur
Scripts PowerShell complets pour peupler le lab. Utilise-les pour :
- vérifier un TP rendu par un apprenant
- reconstruire rapidement l'état "fin de TP" sur ta propre instance
- démontrer la solution en fin de séance
Ordre d'exécution :
1. `01-Setup-AD.ps1` : OU, utilisateurs, groupes, imbrication AGDLP
2. `02-Setup-GPO.ps1` : politique de mot de passe, GPO étudiants
3. `03-Setup-Partages.ps1` : partages SMB et ACL NTFS
Les scripts utilisent les valeurs par défaut du lab (`corp.lab`, `CORP`,
`UserP@ss!2026`). Si tu as personnalisé `.env`, adapte les variables en début
de chaque script.
Ne pas distribuer aux apprenants : le référentiel attend qu'ils construisent
l'annuaire eux-mêmes.
Fait par [AcadéNice](https://acadenice.fr/).

View file

@ -0,0 +1,87 @@
# Course plan
Instructor-facing document. Provides a session outline based on the lab,
alternating theory, demo, and student practice.
## Audience and prerequisites
- Sysadmin-track students, reskilling learners
- Networking fundamentals required (TCP/IP, DNS, DHCP)
- One workstation per learner, 16 GB RAM minimum, VT-x enabled
## Duration
- Intensive: 2 days (14h)
- Spread: six 3h half-days
## Structure
### Session 1 — Intro and setup (3h)
Goals:
- Understand what a directory is, what AD solves
- Start the lab, install Windows Server
Plan:
1. (45 min) Theory: AD history, vocabulary (forest, domain, DC, OU, GPO)
2. (15 min) Lab presentation (diagram, 3 VMs)
3. (1h30) Hands-on: lab install, start DC01, first login
Student material: `docs/etudiant/en/00-prerequisites.md` and `01-lab-startup.md`.
### Session 2 — Promotion and population (3h)
1. (45 min) Theory: FSMO roles, integrated DNS, functional levels
2. (2h) Hands-on: DC promotion, OUs, users, groups
3. (15 min) AGDLP debrief
Material: `02-dc-promotion.md`, `03-ou-users-groups.md`.
### Session 3 — GPOs (3h)
1. (1h) Theory: GPOs, inheritance, filtering, LSDOU order
2. (1h45) Hands-on: create three GPOs, verify on a client
3. (15 min) Best practices: don't overload Default Domain Policy
Material: `04-gpo.md`.
### Session 4 — Shared resources (3h)
1. (45 min) Theory: SMB, NTFS, share vs NTFS permissions
2. (2h) Hands-on: create shares, ACLs, cross-user tests
3. (15 min) AGDLP in practice
Material: `05-shares-ntfs.md`.
### Session 5 — Joining Windows clients (3h)
1. (45 min) Theory: Kerberos, secure channel, DNS constraints
2. (2h) Hands-on: join PC01, log in as AD user, test shares
3. (15 min) RDP group via GPO
Material: `06-join-windows-client.md`.
### Session 6 — Cross-OS integration (3h)
1. (30 min) Theory: realmd, sssd, Kerberos beyond Windows
2. (2h) Hands-on: join linux01, authentication tests
3. (30 min) Outlook: enterprise use cases (Linux servers joined to AD,
AD-backed ssh/sudo)
Material: `07-join-linux-client.md`.
## Assessment
Three possible formats:
1. Multiple-choice: vocabulary and concepts (30 min, 20 questions)
2. Graded lab: give an OU/group structure to set up, shares with specific
ACLs, grade via login tests
3. Mini-project: add a scenario (new department, new GPO) to the existing lab
## Solutions
Full PowerShell scripts live in `docs/formateur/corriges/`. **Do not
distribute** to learners.

View file

@ -0,0 +1,101 @@
# Déroulé de cours
Document à usage formateur. Propose une trame de session qui s'appuie sur le
lab, en alternant théorie, démonstration, et pratique apprenant.
## Public et pré-requis
- Apprenants de type BTS SIO, titres pro administrateur systèmes, ou
reconversion
- Socle réseau indispensable (TCP/IP, DNS, DHCP)
- Une machine par apprenant avec au moins 16 Go de RAM et VT-x activé
## Durée indicative
- Format intensif : 2 jours (14h)
- Format étalé : 6 demi-journées de 3h
## Structure pédagogique
### Séance 1 — Introduction et mise en place (3h)
Objectifs :
- Comprendre ce qu'est un annuaire et ce que résout AD
- Démarrer le lab, installer Windows Server
Plan :
1. (45 min) Théorie : historique AD, vocabulaire (forêt, domaine, DC, OU, GPO)
2. (15 min) Présentation du lab (schéma, explication des 3 VMs)
3. (1h30) TP : installation du lab, démarrage de DC01, premier login
Support apprenant : `docs/etudiant/fr/00-prerequis.md` et `01-installation-lab.md`.
### Séance 2 — Promotion et peuplement (3h)
1. (45 min) Théorie : rôles FSMO, DNS intégré, niveaux fonctionnels
2. (2h) TP : promotion du DC, création d'OU, d'utilisateurs, de groupes
3. (15 min) Debrief AGDLP
Support : `02-promotion-dc.md`, `03-ou-utilisateurs-groupes.md`.
### Séance 3 — GPO et stratégies (3h)
1. (1h) Théorie : GPO, héritage, filtrage, ordre LSDOU
2. (1h45) TP : création des 3 GPO proposées, vérification sur un poste
3. (15 min) Bonnes pratiques : ne pas surcharger la Default Domain Policy
Support : `04-gpo.md`.
### Séance 4 — Ressources partagées (3h)
1. (45 min) Théorie : SMB, NTFS, différence entre autorisations partage et NTFS
2. (2h) TP : création des partages, ACL, tests croisés par type d'utilisateur
3. (15 min) Debrief sur l'intérêt de AGDLP dans la pratique
Support : `05-partages-ntfs.md`.
### Séance 5 — Jonction de postes (3h)
1. (45 min) Théorie : Kerberos, secure channel, contraintes DNS
2. (2h) TP : jonction de PC01, connexion d'un utilisateur AD, tests partages
3. (15 min) Ajout du groupe RDP (GPO conseillée)
Support : `06-jonction-poste-windows.md`.
### Séance 6 — Intégration multi-OS (3h)
1. (30 min) Théorie : realmd, sssd, Kerberos hors Windows
2. (2h) TP : jonction de linux01, tests d'authentification
3. (30 min) Ouverture : cas d'usage en entreprise (serveurs Linux joints au domaine, ssh AD, sudo AD)
Support : `07-jonction-poste-linux.md`.
## Évaluation suggérée
Trois modalités possibles :
1. QCM sur vocabulaire et concepts (30 min, 20 questions)
2. TP évalué : donner une structure OU/groupes à mettre en place, des
partages à créer avec ACL ciblées, évaluer par tests de connexion
3. Mini-projet : ajouter un scénario (nouveau département, nouvelle GPO) au
lab existant
## Matériel
Chaque apprenant doit pouvoir :
- cloner le dépôt
- exécuter `docker compose up -d dc01`
- accéder en RDP à ses VMs
Un second DC pour la démonstration de réplication est hors scope du lab de
base (le lab utilise du NAT Docker qui ne permet pas la réplication directe).
Tu peux le compléter à part en macvlan ou libvirt.
## Corrigés
Les scripts PowerShell complets se trouvent dans
`docs/formateur/corriges/`. **Ne pas distribuer aux apprenants**, ils doivent
construire eux-mêmes.

24
linux-client/Dockerfile Normal file
View file

@ -0,0 +1,24 @@
# Image cliente Linux pré-équipée pour rejoindre un domaine AD
# (realmd + SSSD + Kerberos). La jonction reste manuelle, côté apprenant.
# Fait par AcadéNice - https://acadenice.fr/
FROM debian:12-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -qq \
&& apt-get install -y -qq --no-install-recommends \
realmd sssd sssd-tools libnss-sss libpam-sss \
adcli samba-common-bin oddjob oddjob-mkhomedir packagekit \
krb5-user dnsutils iputils-ping netcat-openbsd \
dbus openssh-server sudo vim less ca-certificates \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Evite le prompt interactif de krb5-config pendant les installs ulterieures.
RUN echo "krb5-config krb5-config/default_realm string CORP.LAB" | debconf-set-selections
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

43
linux-client/entrypoint.sh Executable file
View file

@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Prépare linux01 sans rejoindre le domaine (geste laissé à l'apprenant).
# Fait par AcadéNice - https://acadenice.fr/
set -euo pipefail
AD_DOMAIN="${AD_DOMAIN:-corp.lab}"
DC_HOST="${DC_CONTAINER_IP:-lab-dc01}"
DC_IP="$(getent hosts "$DC_HOST" | awk '{print $1}' || true)"
if [ -n "$DC_IP" ]; then
cat > /etc/resolv.conf <<EOF
nameserver $DC_IP
search $AD_DOMAIN
EOF
# Override nécessaire : dockurr/windows NAT la VM, l'IP annoncée par DNS
# (ex 172.30.0.2) n'est pas routable depuis ce conteneur. On redirige donc
# les noms clés vers l'IP du conteneur DC, que dockurr DNAT vers la VM.
if ! grep -q "$AD_DOMAIN" /etc/hosts; then
echo "$DC_IP $AD_DOMAIN dc01.$AD_DOMAIN dc01" >> /etc/hosts
fi
fi
mkdir -p /run/dbus
[ -S /run/dbus/system_bus_socket ] || dbus-daemon --system --fork
if [ -x /usr/sbin/sshd ]; then
ssh-keygen -A >/dev/null 2>&1 || true
grep -q pam_mkhomedir /etc/pam.d/common-session || \
echo "session optional pam_mkhomedir.so skel=/etc/skel umask=077" >> /etc/pam.d/common-session
/usr/sbin/sshd -D &
fi
cat <<EOF
linux01 prêt. Prochaine étape (côté apprenant) :
docker exec -it lab-linux01 bash
realm discover $AD_DOMAIN
EOF
exec sleep infinity

44
scripts/check-prereqs.ps1 Normal file
View file

@ -0,0 +1,44 @@
# Vérifie les prérequis locaux avant de lancer le lab (Windows).
# Fait par AcadéNice - https://acadenice.fr/
$ErrorActionPreference = "Continue"
$fail = 0
function OK ($m) { Write-Host "[ OK ] $m" }
function KO ($m) { Write-Host "[FAIL] $m"; $script:fail = 1 }
function WARN ($m) { Write-Host "[WARN] $m" }
Write-Host "Vérification des prérequis"
Write-Host ""
try { $v = docker --version; OK "docker : $v" } catch { KO "docker absent" }
try { docker compose version | Out-Null; OK "docker compose v2 présent" } catch { KO "docker compose v2 absent" }
try { docker info | Out-Null; OK "daemon docker joignable" } catch { KO "daemon docker inaccessible" }
try { wsl --version | Out-Null; OK "WSL2 présent" } catch { WARN "WSL2 non détecté" }
$wslConfig = "$env:USERPROFILE\.wslconfig"
if (Test-Path $wslConfig) {
if ((Get-Content $wslConfig -Raw) -match "nestedVirtualization\s*=\s*true") {
OK ".wslconfig : virtualisation imbriquée activée"
} else {
WARN ".wslconfig : ajouter 'nestedVirtualization=true' sous [wsl2]"
}
} else {
WARN "$wslConfig absent - créez-le avec [wsl2] / nestedVirtualization=true"
}
$ram = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB)
if ($ram -ge 16) { OK "RAM $ram Go" }
elseif ($ram -ge 12) { WARN "RAM $ram Go (minimum)" }
else { KO "RAM $ram Go insuffisante" }
$freeGB = [math]::Round((Get-Item $PSScriptRoot).PSDrive.Free / 1GB)
if ($freeGB -ge 150) { OK "Disque libre $freeGB Go" }
elseif ($freeGB -ge 80) { WARN "Disque libre $freeGB Go (juste le minimum)" }
else { KO "Disque libre $freeGB Go insuffisant" }
Write-Host ""
if ($fail -eq 0) { Write-Host "Prérequis critiques : OK." ; exit 0 }
Write-Host "Prérequis manquants. Voir docs\etudiant\fr\00-prerequis.md"
exit 1

78
scripts/check-prereqs.sh Executable file
View file

@ -0,0 +1,78 @@
#!/usr/bin/env bash
# Vérifie les prérequis locaux avant de lancer le lab.
# Fait par AcadéNice - https://acadenice.fr/
set -u
ok() { echo "[ OK ] $*"; }
ko() { echo "[FAIL] $*"; fail=1; }
warn() { echo "[WARN] $*"; }
fail=0
OS="$(uname -s)"
echo "Vérification des prérequis (OS détecté : $OS)"
echo
command -v docker >/dev/null 2>&1 \
&& ok "docker : $(docker --version 2>/dev/null | awk '{print $3}' | tr -d ',')" \
|| ko "docker absent"
docker compose version >/dev/null 2>&1 \
&& ok "docker compose v2 : $(docker compose version --short 2>/dev/null)" \
|| ko "docker compose v2 absent (plugin docker-compose-plugin requis)"
docker info >/dev/null 2>&1 \
&& ok "daemon docker joignable" \
|| ko "daemon docker inaccessible (user dans le groupe docker ?)"
case "$OS" in
Linux)
if [ -e /dev/kvm ] && [ -r /dev/kvm ] && [ -w /dev/kvm ]; then
ok "/dev/kvm accessible"
elif [ -e /dev/kvm ]; then
ko "/dev/kvm existe mais pas lisible (groupe kvm ?)"
else
ko "/dev/kvm absent (VT-x / AMD-V désactivé dans le BIOS ?)"
fi
lsmod 2>/dev/null | grep -q "^kvm " && ok "module kvm chargé" || warn "module kvm non chargé"
;;
Darwin)
if [ "$(uname -m)" = "arm64" ]; then
ko "Mac Apple Silicon : dockurr/windows non supporté (voir docs/etudiant/fr/00-prerequis.md)"
else
warn "Mac Intel : Docker Desktop avec virtualisation imbriquée requis"
fi
;;
MINGW*|CYGWIN*|MSYS*)
warn "Sous Windows, utilisez plutôt check-prereqs.ps1"
;;
esac
if command -v free >/dev/null 2>&1; then
MEM_GB=$(free -g | awk '/^Mem:/ {print $2}')
if [ "$MEM_GB" -ge 16 ]; then ok "RAM ${MEM_GB} Go"
elif [ "$MEM_GB" -ge 12 ]; then warn "RAM ${MEM_GB} Go (minimum — fermez les autres applis)"
else ko "RAM ${MEM_GB} Go insuffisante"
fi
fi
FREE_GB=$(df -BG "$PWD" 2>/dev/null | awk 'NR==2 {gsub("G",""); print $4}')
if [ -n "${FREE_GB:-}" ]; then
if [ "$FREE_GB" -ge 150 ]; then ok "Disque libre ${FREE_GB} Go"
elif [ "$FREE_GB" -ge 80 ]; then warn "Disque libre ${FREE_GB} Go (juste le minimum)"
else ko "Disque libre ${FREE_GB} Go insuffisant"
fi
fi
command -v xfreerdp3 >/dev/null 2>&1 || command -v xfreerdp >/dev/null 2>&1 \
&& ok "xfreerdp disponible" \
|| warn "xfreerdp absent (recommandé pour RDP fluide)"
echo
if [ $fail -eq 0 ]; then
echo "Prérequis critiques : OK."
exit 0
fi
echo "Prérequis manquants. Voir docs/etudiant/fr/00-prerequis.md"
exit 1

24
scripts/rdp-client.sh Executable file
View file

@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Ouvre une session RDP sur le poste client Windows (PC01).
# Fait par AcadéNice - https://acadenice.fr/
set -euo pipefail
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
[ -f "$PROJECT_DIR/.env" ] && set -a && . "$PROJECT_DIR/.env" && set +a
HOST="127.0.0.1"
PORT="${CLIENT_RDP_PORT:-3391}"
USER="${RDP_CLIENT_USER:-LocalAdmin}"
PASSWORD="${RDP_CLIENT_PASSWORD:-${AD_ADMIN_PASSWORD:-AdminP@ss!2026}}"
SIZE="${RDP_SIZE:-1600x900}"
if command -v xfreerdp3 >/dev/null; then RDP=xfreerdp3
elif command -v xfreerdp >/dev/null; then RDP=xfreerdp
else echo "xfreerdp non installé" >&2; exit 1
fi
exec "$RDP" \
/v:"$HOST:$PORT" /u:"$USER" /p:"$PASSWORD" \
/cert:ignore +clipboard \
/size:"$SIZE" /dynamic-resolution

43
scripts/rdp-dc.ps1 Normal file
View file

@ -0,0 +1,43 @@
# Ouvre une session RDP sur le contrôleur de domaine (DC01).
# Fait par AcadéNice - https://acadenice.fr/
param(
[string]$RdpHost = "127.0.0.1",
[int]$Port = 3389,
[string]$User = "Administrator",
[string]$Domain = "CORP",
[string]$Password = "AdminP@ss!2026"
)
$ErrorActionPreference = "Stop"
$envFile = Join-Path $PSScriptRoot "..\.env"
if (Test-Path $envFile) {
Get-Content $envFile | Where-Object { $_ -match '^([A-Z_]+)=(.*)$' } | ForEach-Object {
$k = $Matches[1]; $v = $Matches[2].Trim('"').Trim("'")
switch ($k) {
"DC_RDP_PORT" { $Port = [int]$v }
"AD_DOMAIN_NETBIOS" { $Domain = $v }
"AD_ADMIN_PASSWORD" { $Password = $v }
}
}
}
cmdkey /generic:"TERMSRV/$RdpHost" /user:"$Domain\$User" /pass:"$Password" | Out-Null
$sharedPath = (Resolve-Path "$PSScriptRoot\..\shared").Path
$rdpFile = Join-Path $env:TEMP "lab_ad_dc.rdp"
@"
full address:s:${RdpHost}:${Port}
username:s:${Domain}\${User}
redirectclipboard:i:1
redirectdrives:i:1
drivestoredirect:s:${sharedPath}
desktopwidth:i:1600
desktopheight:i:900
smart sizing:i:1
authentication level:i:0
"@ | Out-File -FilePath $rdpFile -Encoding ASCII -Force
Start-Process mstsc -ArgumentList "`"$rdpFile`""

31
scripts/rdp-dc.sh Executable file
View file

@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Ouvre une session RDP sur le contrôleur de domaine (DC01).
# Fait par AcadéNice - https://acadenice.fr/
set -euo pipefail
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
[ -f "$PROJECT_DIR/.env" ] && set -a && . "$PROJECT_DIR/.env" && set +a
HOST="127.0.0.1"
PORT="${DC_RDP_PORT:-3389}"
USER="Administrator"
DOMAIN="${AD_DOMAIN_NETBIOS:-CORP}"
PASSWORD="${AD_ADMIN_PASSWORD:-AdminP@ss!2026}"
SHARE_DIR="$PROJECT_DIR/shared"
SIZE="${RDP_SIZE:-1600x900}"
mkdir -p "$SHARE_DIR"
if command -v xfreerdp3 >/dev/null; then RDP=xfreerdp3
elif command -v xfreerdp >/dev/null; then RDP=xfreerdp
else
echo "xfreerdp non installé (apt install freerdp3-x11 / pacman -S freerdp / brew install freerdp)" >&2
exit 1
fi
exec "$RDP" \
/v:"$HOST:$PORT" /u:"$USER" /d:"$DOMAIN" /p:"$PASSWORD" \
/cert:ignore +clipboard \
/size:"$SIZE" /dynamic-resolution \
/drive:shared,"$SHARE_DIR"

0
shared/.gitkeep Normal file
View file