commit 8e1b06e0909b6e52c2564466210f2f9a31ac0d49 Author: Corentin Date: Fri Apr 17 11:29:49 2026 +0200 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/ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..677fdb5 --- /dev/null +++ b/.env.example @@ -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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..02304af --- /dev/null +++ b/.gitignore @@ -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/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c095546 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8adae31 --- /dev/null +++ b/README.md @@ -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 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/). diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 0000000..242a78d --- /dev/null +++ b/README_EN.md @@ -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 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/). diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6be7b8c --- /dev/null +++ b/docker-compose.yml @@ -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 diff --git a/docs/etudiant/en/00-prerequisites.md b/docs/etudiant/en/00-prerequisites.md new file mode 100644 index 0000000..cd63247 --- /dev/null +++ b/docs/etudiant/en/00-prerequisites.md @@ -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`. diff --git a/docs/etudiant/en/01-lab-startup.md b/docs/etudiant/en/01-lab-startup.md new file mode 100644 index 0000000..de42331 --- /dev/null +++ b/docs/etudiant/en/01-lab-startup.md @@ -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 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`. diff --git a/docs/etudiant/en/02-dc-promotion.md b/docs/etudiant/en/02-dc-promotion.md new file mode 100644 index 0000000..56d9b26 --- /dev/null +++ b/docs/etudiant/en/02-dc-promotion.md @@ -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`. diff --git a/docs/etudiant/en/03-ou-users-groups.md b/docs/etudiant/en/03-ou-users-groups.md new file mode 100644 index 0000000..0c0ce7a --- /dev/null +++ b/docs/etudiant/en/03-ou-users-groups.md @@ -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. diff --git a/docs/etudiant/en/04-gpo.md b/docs/etudiant/en/04-gpo.md new file mode 100644 index 0000000..a8ad3aa --- /dev/null +++ b/docs/etudiant/en/04-gpo.md @@ -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. diff --git a/docs/etudiant/en/05-shares-ntfs.md b/docs/etudiant/en/05-shares-ntfs.md new file mode 100644 index 0000000..ce6ae5d --- /dev/null +++ b/docs/etudiant/en/05-shares-ntfs.md @@ -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% +# 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. diff --git a/docs/etudiant/en/06-join-windows-client.md b/docs/etudiant/en/06-join-windows-client.md new file mode 100644 index 0000000..f5a3ff9 --- /dev/null +++ b/docs/etudiant/en/06-join-windows-client.md @@ -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 +``` + +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 with the value from: +# docker inspect lab-dc01 --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' +Add-Content C:\Windows\System32\drivers\etc\hosts "`n 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:'' /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. diff --git a/docs/etudiant/en/07-join-linux-client.md b/docs/etudiant/en/07-join-linux-client.md new file mode 100644 index 0000000..eadb929 --- /dev/null +++ b/docs/etudiant/en/07-join-linux-client.md @@ -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. diff --git a/docs/etudiant/en/troubleshooting.md b/docs/etudiant/en/troubleshooting.md new file mode 100644 index 0000000..26ffd2e --- /dev/null +++ b/docs/etudiant/en/troubleshooting.md @@ -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 +``` diff --git a/docs/etudiant/fr/00-prerequis.md b/docs/etudiant/fr/00-prerequis.md new file mode 100644 index 0000000..ddd4c9c --- /dev/null +++ b/docs/etudiant/fr/00-prerequis.md @@ -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`. diff --git a/docs/etudiant/fr/01-installation-lab.md b/docs/etudiant/fr/01-installation-lab.md new file mode 100644 index 0000000..4fb11df --- /dev/null +++ b/docs/etudiant/fr/01-installation-lab.md @@ -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 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`. diff --git a/docs/etudiant/fr/02-promotion-dc.md b/docs/etudiant/fr/02-promotion-dc.md new file mode 100644 index 0000000..cebab42 --- /dev/null +++ b/docs/etudiant/fr/02-promotion-dc.md @@ -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`. diff --git a/docs/etudiant/fr/03-ou-utilisateurs-groupes.md b/docs/etudiant/fr/03-ou-utilisateurs-groupes.md new file mode 100644 index 0000000..d8e092e --- /dev/null +++ b/docs/etudiant/fr/03-ou-utilisateurs-groupes.md @@ -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`. diff --git a/docs/etudiant/fr/04-gpo.md b/docs/etudiant/fr/04-gpo.md new file mode 100644 index 0000000..d2b3b68 --- /dev/null +++ b/docs/etudiant/fr/04-gpo.md @@ -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. diff --git a/docs/etudiant/fr/05-partages-ntfs.md b/docs/etudiant/fr/05-partages-ntfs.md new file mode 100644 index 0000000..10fe561 --- /dev/null +++ b/docs/etudiant/fr/05-partages-ntfs.md @@ -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% +# 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. diff --git a/docs/etudiant/fr/06-jonction-poste-windows.md b/docs/etudiant/fr/06-jonction-poste-windows.md new file mode 100644 index 0000000..53c60d1 --- /dev/null +++ b/docs/etudiant/fr/06-jonction-poste-windows.md @@ -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 +``` + +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 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 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:'' /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. diff --git a/docs/etudiant/fr/07-jonction-poste-linux.md b/docs/etudiant/fr/07-jonction-poste-linux.md new file mode 100644 index 0000000..20a3567 --- /dev/null +++ b/docs/etudiant/fr/07-jonction-poste-linux.md @@ -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. diff --git a/docs/etudiant/fr/troubleshooting.md b/docs/etudiant/fr/troubleshooting.md new file mode 100644 index 0000000..4815a58 --- /dev/null +++ b/docs/etudiant/fr/troubleshooting.md @@ -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 +``` diff --git a/docs/formateur/corriges/01-Setup-AD.ps1 b/docs/formateur/corriges/01-Setup-AD.ps1 new file mode 100644 index 0000000..20d5f22 --- /dev/null +++ b/docs/formateur/corriges/01-Setup-AD.ps1 @@ -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." diff --git a/docs/formateur/corriges/02-Setup-GPO.ps1 b/docs/formateur/corriges/02-Setup-GPO.ps1 new file mode 100644 index 0000000..05fedd6 --- /dev/null +++ b/docs/formateur/corriges/02-Setup-GPO.ps1 @@ -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." diff --git a/docs/formateur/corriges/03-Setup-Partages.ps1 b/docs/formateur/corriges/03-Setup-Partages.ps1 new file mode 100644 index 0000000..06e92fa --- /dev/null +++ b/docs/formateur/corriges/03-Setup-Partages.ps1 @@ -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." diff --git a/docs/formateur/corriges/README.md b/docs/formateur/corriges/README.md new file mode 100644 index 0000000..c2087a8 --- /dev/null +++ b/docs/formateur/corriges/README.md @@ -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/). diff --git a/docs/formateur/en/course-plan.md b/docs/formateur/en/course-plan.md new file mode 100644 index 0000000..f8b9ce4 --- /dev/null +++ b/docs/formateur/en/course-plan.md @@ -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. diff --git a/docs/formateur/fr/deroule-cours.md b/docs/formateur/fr/deroule-cours.md new file mode 100644 index 0000000..053fe80 --- /dev/null +++ b/docs/formateur/fr/deroule-cours.md @@ -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. diff --git a/linux-client/Dockerfile b/linux-client/Dockerfile new file mode 100644 index 0000000..4f7b4e6 --- /dev/null +++ b/linux-client/Dockerfile @@ -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"] diff --git a/linux-client/entrypoint.sh b/linux-client/entrypoint.sh new file mode 100755 index 0000000..e675e6b --- /dev/null +++ b/linux-client/entrypoint.sh @@ -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 <> /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 </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 diff --git a/scripts/rdp-client.sh b/scripts/rdp-client.sh new file mode 100755 index 0000000..41d62c7 --- /dev/null +++ b/scripts/rdp-client.sh @@ -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 diff --git a/scripts/rdp-dc.ps1 b/scripts/rdp-dc.ps1 new file mode 100644 index 0000000..aa93e6f --- /dev/null +++ b/scripts/rdp-dc.ps1 @@ -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`"" diff --git a/scripts/rdp-dc.sh b/scripts/rdp-dc.sh new file mode 100755 index 0000000..cd9be79 --- /dev/null +++ b/scripts/rdp-dc.sh @@ -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" diff --git a/shared/.gitkeep b/shared/.gitkeep new file mode 100644 index 0000000..e69de29