17 Apr 2019, 00:00

Renommage d'un domaine Windows

But de la manoeuvre : transformer travail.domaine.com en work.ville.nouveaudomaine.fr, ainsi que les noms NetBIOS de TRAVAIL vers WORK.

Sources : Pour du Server 2003
Pour du Server 2008
Une synthèse
Une autre synthèse

Note préalables

  • Les serveurs Exchange ne supportent pas le changement de nom (sauf Exchange 2003, et uniquement le nom DNS, pas le nom NetBIOS)
  • Je n’aborde pas ici la mise à jour des relations de confiance entre domaines, elle est détailée dans l’article de chez Microsoft
  • Il est très fortement conseillé de backuper les données, ainsi que l’état du système, pour pouvoir le restaurer si besoin
  • Il faut faire les opérations depuis un serveur intégré au domaine, mais qui n’est pas un contrôleur de domaine. Celui-ci devra avoir la fonctionnalité “Administration de serveur distants” (qui donne notamment accès à la commande rendom)

Création de la nouvelle zone DNS

Il faut au préalable créer une nouvelle zone DNS. Pour ceci, Gestionnaire DNS -> nouvelle zone
Dans un cas simple, laisser les choix par défaut (zone principale, intégrée à l’AD, vers tous les serveurs DNS executés sur des DC dans ce domaine). Adapter si besoin.
Nom de la zone à créer : work.ville.nouveaudomaine.fr

Changement du nom de domaine

Depuis la station de contrôle, on lance une invite de commande en administrateur. Je conseille de dédier un répertoire à la migration

mkdir C:\migration_domaine
cd C:\migration_domaine

Puis

rendom /list

Ceci crée un fichier domainList.xml dans le répertoire courant, qu’il faut éditer en remplaçant l’ancien nom de domaine par le nouveau (il est sage de le backuper avant modification).
On remplace dedans les occurences de travail.domaine.com par work.ville.nouveaudomaine.fr.

On lance ensuite

rendom /showforest

Ceci affiche les infos updatées selon le fichier DomainList.xml modifié. Il ne modifie rien, mais permet de vérifier que la nouvelle organisation est bien celle attendue.

Ensuite,

rendom /upload

Ceci crée le fichier Dclist.xml et l’envoie sur les controlleurs de domaine. Cette étape freeze la foret pour éviter les interactions indésirables entre la migration de domaine, et d’éventuelles modifications sur la forêt.

Microsoft conseille ensuite de répliquer les infos de configuration depuis le serveur Domain Naming Master (mettre son hostname à la place dans la commande suivante) :

repadmin /syncall /d /e /P /q DomainNamingMaster

Si besoin de le connaitre le serveur qui joue le rôle de DNM, on a la commande

dsquery server -forest -hasfsmo Name

Vérifier dans le serveur DNS que nous avons IMPÉRATIVEMENT toutes les entrées définies dans cet article

On peut ensuite lancer la commande

rendom /prepare

qui va vérifier que tous les DCs sont aptes à être mis à jour. Ceci se vérifie sur le fichier Dclist.xml (les DC doivent être en état Prepared).

Enfin,

rendom /execute

qui lance effectivement la mise à jour. Les DCs vont rebooter automatiquement.

Penser à vérifier après reboot que le login se fait bien en utilisant le nouveau domaine, ainsi que les panneau de conf Système.
Vérifier le fichier Dclist.xml, les DCs doivent être à l’état Done.
Si il subsiste un état “Error”, il est possible de compléter la ligne <Retry><Retry> en <Retry>yes<Retry>, puis de réaplliquer cette étape (les DCs à l’état Done ne seront pas réaffectés par la manipulation).
Si un DC reste malgré tout à l’état Error, il faut lui enlever (puis remettre) les rôles AD-DS.

Puis sur un (chaque?) DC après redémarrage :

gpfixup /olddns:travail.domaine.fr /newdns:work.ville.nouveaudomaine.fr

qui met à jour et répare les dépendances de nom de domaine dans le stratégies de groupe après changement.

De même,

gpfixup /oldnb:TRAVAIL /newnb:WORK

qui met à jour le nom NetBIOS du domaine.
À ce stade, il faut redémarrer 2 fois chaque poste client, puis vérifier que son FQDN prend bien en compte le nouveau domaine.

On peut enfin lancer la commande

rendom /clean

qui supprime les références à l’ancien domaine.
Attention, les postes non rebootés 2 fois après cette étape devront être manuellement retirés de l’ancien domaine, puis réintégrés dans le nouveau domaine.

Enfin,

rendom /end

qui finalise la procédure et dévérouille la forêt.

Après connexion d’un client, on peut vérifier que celui-ci est bien présent dans la zone récemment créée des serveurs DNS.

Actions manuelles pour finaliser le changement

Vérifier/updater les chemins du DFSN, des partages réseaux déployés et des imprimantes déployées

  • Les FQDN des clients intègrent automatiquement le nouveau nom de domaine, mais pas les serveurs. Pour les renommer correctement, il faut ajouter le FQDN du nouveau domaine, puis le mettre en principal. Pour ceci,

    netdom computername DC1.travail.domaine.com /add:DC1.work.ville.nouveaudomaine.fr netdom computername DC1.travail.domaine.com /makeprimary:DC1.work.ville.nouveaudomaine.fr

  • Les partages réseaux déployés par les GPO ne sont pas mis à jour automatiquement pour utiliser le nouveau domaine/nom d’hôte, il faut le faire à la main

  • De même pour les imprimantes déployées par GPO. Si le serveur les hébergeant a changé de nom d’hôte, il faut les mettre à jour

  • si un espace de nom DFS (DFSN) est utilisé, il ne sera pas non plus mis à jour automatiquement

  • lorsque tout fonctionnait bien j’ai backupé (exporté) puis supprimé la zone DNS de l’ancien domaine des serveur DNS pour en effacer les traces et m’assurer que tout reposait bien sur le nouveau domaine

  • la synchronisation user/password avec Azure AD Connect ne fonctionnait plus, il a fallu la réinitialiser selon ce post

Dcdiag /test:DNS /DnsRecordRegistration /s:domaincontroller

16 Apr 2019, 00:00

Désactivation et réactivation des services de synchronisation Azure AD Connect

Source principale

Il peut parfois être nécessaire de reconfigurer complètement les services de synchronisation entre un Active Directory local et les services Office 365 (Azure Active Directory Connect).

Pour ceci, il faut les désactiver chez O365 via Powershell, les désinstaller du serveur local, puis réinstaller AAD Connect sur le serveur local.

On ouvre une session Powershell en admin.
Si les outils de gestion PS vers O365 ne sont pas installés, on le fait via

Install-Module -Name MSonline

(si message de commande introuvable, il est nécessaire d’installer les PackageManagement, dispo ici

On initialise la variable de connection via

$msolcred = get-credential

en rentrant les ids d’un admin sur O365.

On établit la connection aux services O365

connect-msolservice -credential $msolcred

Il est ensuite temps de supprimer les applis AAD Connect du serveur local (ajout/suppression de programme).
Une fois désinstallés, on lance la commande PS :

Set-MsolDirSyncEnabled -EnableDirSync $false

et on valide avec Y.

pour obtenir l’état de synchro, on lance la commande

Set-MsolDirSyncEnabled -EnableDirSync $false

qui doit désormais renvoyer “false”.

Il faut plusieurs heures (voire une nuit) à Microsoft Azure pour prendre réellement en compte l’arrêt de la synchro. Lorsque ce sera fait, l’interface d’admin O365 n’affichera plus le status AAD Connect, ni l’état (Synchronisé/Dans le cloud) des Utilisateurs O365. Les utilisateurs anciennement synchronisés seront de facto considérés comme utilisateurs cloud.

Une fois que la suppression de la synchro est bien prise en compte par les serveurs O365, il suffit de réinstaller Azure AD Connect, avec éventuellement une passe préalable de IdFix.
Cf. ce post

La synchro reprend normalement assez rapidement, et quelques heure plus tard, l’état AAD Connect réapparait dans le centre d’administration O365.

10 Feb 2019, 00:00

Notes sur fail2ban

Généralités

2 articles qui m’ont inspiré :
http://xmodulo.com/configure-fail2ban-apache-http-server.html
https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-centos-7

fail2ban se base sur l’analyse des logs pour bannir des adresses ip (via, par défaut, la création de règles iptables) qui auraient enfreint certaines règles.
Les expressions régulières qui servent à analyser les fichiers de conf se trouvent dans le dossier /etc/fail2ban/filter.d/.

Les fichiers de conf sont lus dans l’ordre suivant, sachant que c’est la dernière mention d’un paramètre redondant qui sera prise en compte :

/etc/fail2ban/jail.conf
/etc/fail2ban/jail.d/*.conf
/etc/fail2ban/jail.local
/etc/fail2ban/jail.d/*.local

Il est conseillé de ne pas toucher aux fichier .confs (ce qui permet entre autres de ne pas perturber les mises à jour système) mais de rajouter nos propres règles dans des fichiers .local.

On voit dans jail.conf des paramètres par défaut (sous la balise [DEFAULT]) :

# "bantime" is the number of seconds that a host is banned.
bantime  = 600

# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime  = 600

# "maxretry" is the number of failures before a host get banned.
maxretry = 5

On voit que si une ip échoue à se connecter 5 fois de suite (maxretry) en moins de 600 secondes (findtime), alors elle sera bannie pendant 600 secondes (bantime).
Il y’a aussi dans cette même section un nom fichier de filtre par défaut, qui reprend le nom de la jail :

filter = %(__name__)s

Cela dit que le fichier de filtre qui sera récupéré est le même que le nom de la jail.

Plus bas, on voit des exemples de jails, de type

[sshd]

port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Ces jails sont définies par défaut, mais non activées. Pour ceci, il faut leur donner le paramètre enabled = true. Par défaut, sous Debian, seul le service sshd est protégé par fail2ban, via le fichier /etc/fail2ban/jail.d/defaults-debian.conf.

Installation et configuration

Pour installer :

sudo apt install fail2ban

On peut ensuite créer par exemple un fichier /etc/fail2ban/jail.d/ssh.local qui contiendra :

[sshd]
enabled = true
port = 12345
findtime  = 60
maxretry = 5

afin de spécifier un port custom, et laisser le droit à 5 essais par minute.

On peut aussi créer /etc/fail2ban/jail.d/apache.local pour activer fail2ban pour apache :

# detect password authentication failures
[apache-auth]
enabled  = true
port     = http,https
findtime  = 60
maxretry = 5

pour un fail2ban sur l’authentification par mot de passe.

02 Feb 2019, 00:00

Usage du .htaccess dans Apache 2

Le fichier .htaccess est un fichier en texte clair, qui permet de définir le message affiché lors de la demande de mot de passe, ainsi que le fichier dans lequel Apache ira vérifier que l’utilisateur/mot de passe est correct (le .htpasswd).
Dans mon cas, je choisis de faire un fichier .htpasswd par répertoire, car tous les répertoires ne doivent pas être accessibles aux mêmes utilisateurs.

Je crée le .htpasswd :

cd /path/to/site/files
htpasswd -c .htpasswd user1

L’option -c sert à créer/réécrire le fichier. Si on ne la spécifie pas, ça rajoute une nouvel utilisateur qui pourra lire ce répertoire.

Ensuite, on ajoute le .htaccess, qui va directement protéger le répertoire

nano .htaccess

Dans lequel on met :

AuthType Basic
AuthUserFile "/path/to/site/files/.htpasswd"
AuthName "Identification pour ce dossier ?"
Require valid-user

Il semble indispensable d’indiquer le chemin complet vers le .htpasswd, sans quoi le serveur retourne une erreur 500.

Dans le cas où le repértoire est en dehors des répertoires standards de Apache (/usr/share ou /var/www), il faut les ajouter à la main dans le /etc/apache2/apache2.conf ou dans /etc/apache2/sites-available/00X-mon-site.conf :

<Directory /path/to/site/files/>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
</Directory>

Ceci permet respectivement de suivre les liens symboliques (utile pour mon setup), de permettre d’outrepasser les droits localement (et donc d’utiliser le htaccess), et permet à tout le monde (toutes les IPs notamment) d’accéder au site.

28 Jul 2018, 00:00

Divers - Office 365 - Exchange online

Équivalences AD / O365 / EAC si ADConnect paramétré

Globalement, l’autorisation “Gérer” de AD correspond au status “Propriétaire” sous O365.
Ce qui existe dans l’AD est transmis vers O365/EAC, l’inverse n’est pas (forcément) vrai. Si on souhaite avoir les éléments en local, il FAUT les créer en local.
Les autorisations d’envoyer un mail “en tant que” (par ex. en tant qu’un groupe de distribution) se gèrent dans tous les cas dans l’EAC, car dans le setup actuel, il n’y a pas de serveur Exchange en local, seulement sur O365.

Utilisateurs

Un utilisateur créé sous AD apparaîtra dans O365 sous “Utilisateurs actifs” et dans EAC sous “Destinataires -> Boîtes aux lettres”. C’est un utilisateur à part entière avec boîte mail dédiée.

Groupes de sécurité

Un groupe de sécurité créé sous AD peut avoir une adresse mail renseignée ou non.

Si adresse, il apparaîtra dans O365 sous “Groupes” (en tant que “Sécurité avec extension messagerie”) et dans EAC sous “Destinataires -> Groupes” (en tant que “Sécurité à extension courrier”).

Si aucune adresse mail n’est renseignée, il apparaitra sous O365 sous “Groupes” (en tant que “Sécurité”) et n’apparaitra PAS dans EAC.

C’est avant tout un groupe pour l’organisation de l’entreprise (GPO de l’AD, etc.), qui peut également être utilisé pour remettre un courrier à tous les membres de ce groupe.
Si un autre groupe est lui-même membre du groupe, les utilisateurs de cet autre groupe ne recevront le mail QUE SI cet autre groupe a une adresse de messagerie renseignée dans ses propriétés (ceci permet de couper le transfert vers les N+1 par exemple, si on ne met pas d’adresse mail).

Groupes de distribution

Un groupe de distribution créé sous AD apparaitra dans O365 sous “Groupes” en tant que “Liste de distribution” et dans EAC sous “Destinataires -> Groupes” en tant que Liste de distribution. Il faut lui définir une adresse mail, sans quoi son intérêt est très limité (il semble qu’il n’apparaisse as dans EAC si pas d’adresse mail renseignée).

C’est un alias qui va rediriger le courrier envoyé à l’adresse en question vers tous les membres inclus dedans (permet une gestion différente des groupes de sécurité).
Si un sous-groupe est lui-même membre du groupe, les utilisateurs de ce sous-groupe ne recevront le mail QUE SI le sous-groupe a une adresse de messagerie renseignée dans ses propriétés.

L’autorisation “Send As” ne peut être définie que directement dans le EAC. Par contre, si le groupe a été créé sur AD, l’autorisation “Send On Behalf” est définie dans ADSI, sous l’attribut “publicDelegates”. Il faut toujours attendre quelques (dizaines de) minutes pour que les changements soient effectifs sous Exchange.
Dans certains cas, le client Outlook d’un utilisateur peut rester “bloqué” sur l’intention d’envoyer “de la part de” (on behalf), ce qui echouera si la seule autorisation accordée est “send as”. Pour “réinitialiser” le comportement du client, il faut désactiver puis réactiver le mode “en cache” du compte Exchange.

Boîte au lettres partagées

Il s’agit d’une boîte à part entière, avec son propre stockage/quota (quota de 99Go à l’heure de cet article). Elle permet de centraliser des messages partagés par plusieurs utilisateurs, ainsi que le calendrier. Sur l’Outlook de l’utilisateur, la boîte sera distincte de celle de l’utilisateur.
Elle permet également de partager un calendrier entre tous les utilisteurs.

Comme nous n’avons dans le cas présent pas de serveur Exchange en local, il ne me semble pas possible d’en créer une sur l’AD. Elle peut être créée dans l’EAC sous “Destinataires -> Boîte aux lettres partagée”.

Elle n’apparaitra pas dans l’AD, mais dans O365 sous les “Utilisateurs actifs”, et bien sûr dans l’EAC.

Création d’une boite aux lettres partagées avec déploiement automatique (dont calendrier)

Dans le centre d’administration Exchange (EAC), on peut aller dans Recipients -> Shared, et créer une boite aux lettres partagées. Tous les utilisateurs qui sont entrés dans les propriétés de la boite partagée -> Mailbox delegation -> Full access verront la boite mail ainsi que son calendrier se déployer automatiquement sur leur client Outlook (avec toutefois un délai jusqu’à une heure).
Ceci correspond à une vraie boîte mail à part entière, avec son propre espace de stockage (quota de 99Go à l’heure de cet article) et apparaitra sur le client outlook séparée de la boite principale.

Il semblerait que l’ajout d’un groupe de sécurité, même avec adresse mail renseignée, ne déploie pas automatiquement les boites et calendriers chez les membres du groupe.

Liste de distribution (alias) sur EAC

Dans le EAC -> Recipients -> Groups, on peut créer des listes de distributions. Ceci ne correspond pas à une vraie boîte mail, mais plutôt à un alias. Les messages sont transférés à tous les utilisateurs définis dans les propriétés de la liste -> Membership.
Si on souhaite qu’un utilisateur puisse écrire depuis l’adresse de la liste de distribution, il faut ajouter l’utilisateur en question dans les propriétés de la liste -> Group delegation, et ajouter son nom sous Send As (envoi en tant qu’alias) ou bien Send on Behalf (envoi en tant que user au nom de alias).

Pour que l’utilisateur puisse envoyer des messages depuis sont Outlook (version de bureau), il faut ajouter le champ De qui est masqué par défaut. Sous 2016, ceci peut se faire dans la fenêtre de rédaction d’un message, sous l’onglet Options. Ensuite, on ajoute à la main le nom de l’alias qui doit servir à envoyer le message. Si les paramètres serveur sont corrects, l’envoi devrait fonctionner. Sinon, essayer de désactiver puis réactiver le mode “en cache” du compte Exchange.

10 May 2018, 00:00

Mise en place d'une réplication/failover AD/DNS/DHCP/DFS sur 2 Windows Server

Préambule

Je pars d’une situation où j’ai déjà un serveur Windows 2012R2 configuré en controleur de domaine, avec GPO et partage de fichiers. Je veux ajouter un 2e serveur sous Windows Server 2016, qui fasse office principalement de failover si un des 2 serveurs tombe en panne. Ceci pour les rôles de contrôleur de domaine, de serveur DHCP, serveur DNS, de serveur SMB et déploiement automatique de partages réseaux et d’imprimantes.

Le domaine est WINDOMAIN, le serveur actuel est WINDOMAIN\DC1.

Configurer le serveur secondaire

On commence par relier le serveur au réseau, on lui configure une adresse ip fixe, le hostname souhaité (ici DC2). on le connecte au domaine.

On peut ensuite installer le rôle AD DS, puis promouvoir le serveur en contrôleur de domaine.
La réplication de l’AD se fait automatiquement, avec toutes les GPO.

DNS

Intégration à l’AD

Normalement, le serveur DNS est installé et configuré en même temps que le serveur AD DS. Ceci permet aux enregistrements DNS d’être stockés dans l’AD directement, et donc d’être répliqués entre tous les controleurs de domaine. Cela se vérifie dans le gestionnaire DNS, avec un clic droit -> Propriétés sur une zone, on doit voir l’Etat “Intégré à AD”.
Ceci ne fonctionne que si les 2 serveurs DNS sont aussi des controleurs de domaine, ce qui est le cas ici. Si un serveur DNS n’est pas controleur, il faut passer par la création sur le second serveur d’une zone secondaire qui pointera vers le premier serveur).

Un peu plus d’infos chez Microsoft

Redirecteurs

Toujours dans le gestionnaire DNS, dans les propriétés de chaque serveur, il faut penser à aller vérifier les redirecteurs (serveur DNS utilisé si le serveur intégré ne sait pas résoudre, c’est-à-dire pour tout ce qui ne relève pas du domaine). Typiquement, on peut mettre l’IP de notre box, ou 8.8.8.8 par exemple. Il y’a aussi l’option de se rapatrier sur les serveurs DNS racines en cas d’indisponibilité des redirecteurs. On trouve la liste de ces serveurs dans l’onglet “Indications de racine”.

Distribution par DHCP

Enfin, il faut aller paramétrer les options du DHCP pour qu’il distribue les 2 serveurs DNS. Pour ceci, dans DC1 (actuellement le seul serveur DHCP), aller dans le gestionnaire DHCP, IPv4 -> Étendue -> Options d’étendue et ajouter l’IP du nouveau serveur dans les Serveurs DNS (006).

Note : si un des 2 serveurs venait à être en panne/hors-ligne durablement, penser à s’assurer que le serveur toujours en place est bien distribué en serveur primaire, ceci accélérera la résolution DNS.

DHCP

La première étape est d’avoir une étendue active sur un des 2 serveurs, dans cet exemple sur DC1. Si ce n’est pas le cas, on peut en créer une dans le gestionnaire DHCP -> Nouvelle étendue. L’installation est complètement guidée.
Penser à spécifier les options telles que serveurs DNS, passerelle par défaut.

Sur DC2, installer le rôle Serveur DHCP. Ne pas configurer d’étendue maintenant, elle va être automatiquement répliquée depuis DC1.
Aller sur DC1 dans le gestionnaire DHCP, IPv4 -> Clic-droit sur “Étendue” -> Configurer un basculement
Suivre les étapes en ajoutant l’IP du serveur secondaire (DC2).

Au cours de la création du basculement, les options du serveur DHCP de DC1 seront répliquées sur DC2 (étendue, route par défaut, serveur DNS etc°. Toutefois ces options ne seront par la suite plus synchronisées automatiquement. Pour les synchroniser, on peut lancer sur le serveur “source”, qui possède les informations à jour, la commande Powershell suivante :

Invoke-DhcpServerv4FailoverReplication

qui va répliquer l’ensemble de ses paramèters sur tous les serveurs partenaires.
Il y’a aussi un script planifié qui permet de faire ceci automatiquement, disponible sur cette page avec l’archive zip mirroré sur mon memo.

Si on souhaite supprimer la relation de basculement, il faut savoir que si on procède à la déconfiguration du basculement sur DC1, cela supprimera automatiquement l’étendue sur DC2 (et vice-versa).

Partage de fichiers

Afin d’assurer l’accès aux partages réseaux même si un des 2 serveurs (hébergeant directement les données) tombe, nous allons passer par la réplication DFS. Celle-ci va nous permettre une synchronisation instantanée et permanente de l’état des dossiers de travail, tout en y accédant de manière transparente par le réseau, via un espace de nom DFS.

Dans mon cas, je pars d’un dossier de travail déjà existant, sur DC1, avec le chemin D:\Travail\. Celui-ci est paramétré avec des droits d’accès spécifiques, et le partage réseau est déployé automatiquement via GPO avec le chemin \\DC1\Travail\.

Configuration de la réplication DFS (DFSR)

Il faut commencer par installer le rôle Services de fichiers et de stockage -> Services de fichiers et iSCSI -> Espaces de noms DFS et Réplication DFS sur DC1 ET sur DC2.

On lance le Gestionnaire de système de fichiers distribué DFS.
Réplication -> Nouveau groupe de réplication.... J’ai laissé le choix par défaut, groupe de réplication multi-usages.
On donne un nom au groupe de réplication, dans mon cas “Travail”.
On ajoute DC1 et DC2 dans la liste des serveurs.
Pour une réplication dans les 2 sens, quel que soit le serveur sur lequel les données sont modifiées, on choisit “Maille pleine”. J’ai laissé les options de bande passante par défaut, puisq’on est ici en réseau local.

On prend bien garde à choisir le serveur qui contient actuellement les données en tant que Membre principal. Il s’agit ici de DC1, car DC2 ne contient actuellement aucune donnée. Ainsi, au cours de la synchro initiale, toutes les données présentes actuellement sur DC1 seront répliquées sur le ou les autres serveurs. une fois la synchro initiale terminée, cela ira dans les 2 sens.

On choisit ensuite le dossier local où sont stockées les données sur DC1. C’est D:\Travail comme indiqué au-dessus.
Note : Microsoft eux-même déconseillent de répliquer directement une lettre de lecteur, bien que ce soit censé fonctionner. J’ai personnellement eu des soucis lorsque j’ai essayé. Il faut ensuite la réplication sur chaque serveur membre. On coche la case Activé, et on définit un chemin local sur le membre en question. Il n’est pas obligatoire que tous les membres aient le même chemin d’accès local.

On valide, et la réplication commencera sous peu. Les données seront ainsi sur les 2 serveurs. Toutefois, le partage réseau déployé chez les clients ne fait toujours appel qu’au serveur DC1.

Par défaut, lorsque le service DFSR s’arrête, par exemple lorsqu’un serveur reboote, le système lui laisse 30 secondes pour s’éteindre proprement. S’il sépasse ce délai, alors la fermeture sera forcée, de façon brutale.
Or il arrive régulièrement que le service aie besoin de plus de temps que ça pour s’éteindre (dans le cas d’une grosse base de fichiers). Pour éviter ce problème, on peut, sur chaque serveur, accéder à la clé de registre

`HKLM\SYSTEM\CurrentControlSet\Control`

et régler la valeur WaitToKillServiceTimeout sur le nombre de millisecondes que l’on souhaite accorder à l’extinction (de chaque service). Par exemple, 600000 pour laisser 10 minutes. À noter que cette valeur ne peut excéder 1h, sans quoi elle est réinitialisée à la valeur par défaut de 30 secondes. Source2012

DFSR - Problème de synchronisation

Il peut arriver que certains dossiers ou fichiers ne soient pas répliqués correctement. Plusieurs raisons peuvent expliquer ceci, des problèmes de taille de la Staging Area étant régulièrement évoqués. (cf comment définir une taille de staging)

Une autre raison possible est que les éléments en question soient chiffrés. DFSR ne synchronise pas les fichiers chiffrés.
Le script suivant, strippé de cette page (script bien plus complet et détaillé), permet de lister les fichiers chiffrés dans le fichier $logFile, puis de les déchiffrer

$logFile = "C:\Users\Administrateur\Desktop\EncryptedFiles.log"
$path = "X:\path\to\data"

$encryptedfiles +=  Get-ChildItem $path -File -Recurse -Force -ErrorAction SilentlyContinue |
                    Where-Object { $_.Attributes -match "Encrypted" } |
                    Select-Object -ExpandProperty FullName

foreach ($file in $encryptedfiles){
    Add-Content $logFile "$file"
    (Get-Item -Force -LiteralPath $file).Decrypt()
    }

$encryptedfolders += Get-ChildItem $path -Directory -Recurse -Force -ErrorAction SilentlyContinue |
                     Where-Object { $_.Attributes -match "Encrypted" } |
                     Select-Object -ExpandProperty FullName

foreach ($folder in $encryptedfolders){
    Add-Content $logFile "$folder"
    cipher.exe /d /i $folder
}

juste avant la dernière accolade pour ajouter le déchiffrement automatique.

Une autre raison possible est que DFSR, par design, ne synchronise pas les dossiers/fichiers avec l’attribut “temporaire”. Source : https://blogs.technet.microsoft.com/askds/2008/11/11/dfsr-does-not-replicate-temporary-files/
Or, il peut arriver, sur de gros volumes de données, que des dossiers légitimes contiennent, par erreur (humaine ?), cet attribut. Rien n’indique graphiquement sa présence, et l’utilitaire attrib.exe non plus. Il faut utiliser fsutil pour le consulter.

fsutil usn readdata X:\path\to\folder\

qui retournera quelque chose du genre

Major Version : 0x2
Minor Version : 0x0
FileRef# : 0x0021000000002350
Parent FileRef# : 0x0003000000005f5e
Usn : 0x000000004d431000
Time Stamp : 0x0000000000000000 12:00:00 AM 1/1/1601
Reason : 0x0
Source Info : 0x0
Security Id : 0x5fb
File Attributes : 0x120
File Name Length : 0x10
File Name Offset : 0x3c
FileName : test.txt

On y voit que, dans les attributs du fichier, le masque 0x100 est présent. Selon la table donnée dans le lien ci-dessus, il correspond à l’attribut TEMPORARY.

Pour le supprimer récursivement, on passe par Powershell :

Get-childitem X:\PATH -recurse | ForEach-Object -process {if (($_.attributes -band 0x100) -eq 0x100) {$_.attributes = ($_.attributes -band 0xFEFF)}}

Configuration de l’espace de nom DFS (DFSN)

Généralités

L’idée est de pouvoir centraliser les partages réseaux en y accédant via le nom de domaine. Par exemple, au lieu de déployer \\DC1\Travail, on va déployer le partage \\WINDOMAIN\Travail, et ce sera un des serveurs hébergeant l’espace de nom Travail qui va répondre.

Cette techno est complètement dissociable de la réplication, bien qu’elles soient souvent utilisées ensemble. On peut décider de partager sous des chemins unifiés des ressources venant de serveurs différents (par exemple \\DC1\Travail et \\DC2\Direction, même si uniques sur leurs serveurs respectifs, peuvent être accessibles sous \\WINDOMAIN\Travail et \\WINDOMAIN\Direction). On peut aussi utiliser la réplication sans espace de noms, juste pour dupliquer les données d’un site à l’autre par exemple.

Si 2 serveurs hébergent le même espace de nom, mais sans réplication des dossiers, le contenu affiché sera alternativement le contenu de l’un ou l’autre. Par exemple, si \\DC1\Travail et \\DC2\Travail sont tous les 2 référencés par l’espace de nom \\WINDOMAIN\Travail mais que les 2 dossiers ne sont pas répliqués et ont des contenus différents, on ne sait jamais quel sera le contenu affiché par \\WINDOMAIN\Travail, ce sera celui qui répond le plus vite.

Mise en place

On ouvre le gestionnaire DFS.
Espace de noms (clic-droit) -> Nouvel espace de noms. On choisit DC1 comme premier serveur. On nomme notre espace de nom, ici Travail ; Dans Modifier les paramètres, on peut choisir l’emplacement des données locales. On choisit ici D:\Travail, comme défini précédemment, et on choisit les droits d’accès Admin : Full ; Users : RW (les vrais droits d’accès sont gérés par le NTFS).
On choisit l’option “Espace de noms de domaine”, puis on valide la création.

Le serveur DC1 est maintenant prêt à répondre lorsqu’on appelle \WINDOMAIN\Travail. On veut maintenant que DC2 puisse répondre aussi. Pour ceci, dans le gestionnaire DFS, sous Espaces de noms, clic-droit sur \WINDOMAIN\Travail -> Ajouter un serveur d’espaces de noms. Comme ci-dessus, on rentre le nom du serveur, on choit l’emplacement local des données, on met les droits sur le partage et on valide.

Et voilà : les 2 serveurs sont désormais capables de répondre lorsque l’on interroge le partage directement auprès du domaine, et grace à la combinaison avec la réplication, la continuité en cas de chute d’un serveur est quasi-transparente (à un caffouilage d’explorer près, sur les postes clients).

Note : il est possible, directement sous l’espace de noms DFS? de “Publier” des dossiers, qui seront créés puis partagés automatiquement, et référencés dans le gestionnaire. Il n’est pas du tout obligatoire de les utiliser si l’on souhaite créer des sous-dossiers et les partager, et le faire manuellement permet une plus grande souplesse (chemin du partage réseau notamment).

18 Dec 2017, 00:00

Notes en vrac sur Azure AD Connect et Office 365

Mise en cohérence des domaines

Dans mon cas, l’AD avait été pis en place il y’a longtemps, le domaine local était du genre domain.oldcompany.com, mais les utilsateurs utilisaient aujourd’hui des adresses mail du genre user@newcompany.fr, et l’abonnement O365 avait pour domaine initial unusedcompany.onmicrosoft.com.

Dans ces conditions, la synchro de l’AD vers Azure donnait des identifiants du type nomprenom@unusedcompany.onmicrosoft.com, ce qui rend tout plus pénible, par exemple la connexion à OWA qui ne marche pas avec d’éventuels alias, mais qu’avec cet identifiant.

Comme le domaine initial ne peut être changé, il faut ajouter et vérifier le domaine newcompany.fr dans la gestion des domaines sur le portail O365, connecté en admin de l’abonnement. Pour le vérifier, il faudra aller mettre une preuve TXT dans la zone DNS.
Il faut ensuite ajouter un nouveau suffixe UPN au domaine (Outils d’administration -> Domaines et approbations Active Directory -> Propriétés -> Suffixes UPN), on ajoutera ici newcompany.fr car c’est l’adresse couramment utilisée par l’entreprise. Il faut ensuite modifier les suffixes UPN des utilisateurs dans les Utilisateurs et Ordinateurs AD, pour les passer de p.nom@domaine.oldcompany.fr à p.nom@newcompany.fr. Il est possible de le faire en PowerSehll, par exemple avec ce script

Ainsi, les utilisateurs auront un seul couple adresse/password pour se connecter à tout (Session sur le domaine, OWA, Portail O365 pour télécharger les logiciels etc).

Préparer l’AD local pour la synchro

Pour synchroniser un Active Directory local avec les services Azure Active Directory, il faut commencer par préparer l’AD local (notamment étendre le schéma AD sur un serveur Windows 2012). Cette page de Microsoft détaille beaucoup plus la précédure.

Il faut récupérer une installation d’Exchange 2013, par exemple sur cette page de chez Microsoft. On la décompresse, on lance cmd puis la commande suivante : Setup.exe /PrepareSchema /IAcceptExchangeServerLicenseTerms

Une fois que le schéma est préparé, on peut identifier les incohérences dans l’annuaire avant de synchroniser avec O365. Pour ça, on utilise l’outil IdFix (DL). Dans le cas où une offre dediée à O365 a été souscrite, il faut aller dans les paramétres et choisir “Dedicated” au lieu de “Multi-tenants”. On clique sur Query, on le laisse chercher, on vérifie puis acccepte les modifications, on fait Apply et on voit ce que ça donne. Si tout va bien, on peut passer à la synchro avec Azure. Si il y’a des problèmes (par exemple attributs non-existants), revérifier que l’AD a bien été préparé tel qu’indiqué sur le tuto de Microsoft.

Mise en oeuvre Azure AD Connect

Télécharger ici : https://www.microsoft.com/en-us/download/details.aspx?id=47594

Une fois installé et configuré, il est possibmle de sy nchroniser manuellement avec la commande PowerShell start-adsyncsynccycle -policytype delta

PowerShell et Office 365

Envoi en tant que groupe : Set-distributionGroup -Identity “group” -GrantSendOnBeHalfto “user@domain.com”

07 Oct 2014, 00:00

Sauvegarder via Rsync un backup Time Machine

Lorsqu’on sauvegarde avec Time Machine sur un disque réseau (fonctionnement différent du disque local), les données sont stockées au format .sparsebundle, une image disque qui s’étend à volonté, et qui contient un plusieurs anciennes versions des fichiers. Bien qu’elle apparaisse en tant que fichier sous OSX, une image qu’on peut monter dans le Finder pour en lire/écrire le contenu, c’est en réalité un dossier, qui contient quelques petits fichiers descriptifs, et surtout un gros dossiers, bands, qui contient lui-même toutes les données de l’image, découpé en fichiers de 8,4 Mo. Seule une petite partie de ces fichiers est mise à jour lors d’une sauvegarde Time Machine, et seule cette petite partie sera synchronisée via Rsync (environ 300 Mo. Il va de soi qu’avoir une connexion avec un bon upload, dans le cas d’une sauvegarde réellement distante, est un gros plus.

L’idée du script qui va suivre est de, régulièrement :

  • déclencher une sauvegarde Time Machine
  • monter le volume de sauvegarde (volume réseau, appelé “Time Capsule” ici, bien que ce puisse être n’importe quel volume proprement configuré) sur un point de montage précis
  • synchroniser le point de montage via rsync, avec un serveur ssh (par définition n’importe où dans le monde)

Les prérequis sont :

  • avoir configuré, via GUI ou autre, Time Machine, et être sûr que le setup fonctionne correctement
  • avoir configuré la redirection de ports sur le routeur devant le serveur ssh
  • avoir une configuré une authentification ssh sur le serveur via clé, sans demande de mot de passe, pour pouvoir l’automatiser
  • savoir identifier la time capsule sur le réseau, y accéder via hostname et connaître un couple user/password valide pour la lecture des données
  • avoir désactivé la planification de Time Machine. Le script s’occupe de lancer la sauvegarde, et une MAJ du contenu du sparsebundle pendant la synchronisation distante via rsync pourrait créer une incohérence dans les données.
  • avoir une système de fichiers de destination (sur le serveur ssh) qui supporte les liens durs (hard-link). Typiquement ext4. Bien qu’on stocke du HFS+, il n’est pas nécessaire que cette destination sot en HFS+, car le .sparsebundle contient un système de fichier virtuel, qui s’occupe de conserver toutes les permissions/ACL/attributs étendus nécessaires.

Voici le script proprement dit, très inspiré de cet article, avec un bon paquet de code copié/collé. Cependant, je choisis de simplement conserver les x dernières versions de la sauvegarde. En effet, Time Machine s’occupe déjà de faire un historique régulier (journalier, mensuel, annuel etc), le but de cette sauvegarde est simplement de la déporter sur un site externe, tout en pouvant retrouver une ancienne version en cas de corruption des données Time Machine, et en conservant la facilté de restauration. Ainsi, avec le paramètre daystokeep=90, nous disposons de 3 mois d’historique du contenu de la Time Capsule.

#!/bin/sh

### VARS
  # local
identifier=`hostname`
# the following folder will store lock and log files
filesPath="/path/to/folder with spaces/"  # must contain the trailing /
logfile="${filesPath}${identifier}.log"
lockfile="${filesPath}${identifier}.lck"


  # TimeCapsule (source)
  # should match the Time Machine settings (via TM GUI)
  # name is the Zeroconf name provided in the "Time Capsule" tab within the Airport Utility, finishing by .local
  # for the actual Time Capsule, username seems to be indifferent, but you need the correct password
  # for any AFP share server, username have to be correct
tc_name="Time-Capsule.local"  # it never contains spaces
tc_share="Server Backups"
tc_user="timemachine"
  # if password contains a @ sign, replace it with %40. Spaces are OK.
tc_pw="password %40 TimeCapsule"
tc_mount_point="/Volumes/TC/"  # must contain the trailing /
  # this var could be retrieved from the hostname, but is not for the moment
tc_file_name="iMac de User.sparsebundle"


  # Remote disk (destination)
ssh_user='backupuser'
ssh_server='storage.mydomain.com'
ssh_port=1111
ssh_connect="${ssh_user}@${ssh_server} -p $ssh_port "
target="/path/to/folder/" # must contain the trailing /

###  END OF VARS



# Date for this backup.
date=`date '+%Y-%m-%d_%Hh%Mm'`
# Process ID for this backup
mypid=${$}

### Log beginning of the backup
echo "\n" >> "${logfile}"
if [ ! -d "$filesPath" ]
  then mkdir "$filesPath"
  echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] -- $filesPath was just created" >> "${logfile}"
fi

echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] -- backup started" >> "${logfile}"




###  Check if process is already running to avoid multiples backups at the same time
###  which could corrupt data
if [ -f "${lockfile}" ]
then
  # Lockfile already exists, check if it belongs to a running process
  read -r lockpid < "${lockfile}" #Read the first line which contains a PID
  if [ -z "`ps -p ${lockpid} | grep ${lockpid}`" ]
  then
	# The process doesn't exist anymore. Should there be an incomple folder, it will be removed at the end of the script.
	echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Lockfile for ghost process (PID: ${lockpid}) found, continuing backup." >> "${logfile}"
  else
	echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Lockfile '${lockfile}' for running process (PID: ${lockpid}) found, backup stopped." >> "${logfile}"
	exit 73 # can't create (user) output file
  fi
fi
# The lockfile doesn't exist or belongs to a ghost process, make or update it containing the current PID.
echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] -- Création du fichier lock" >> "${logfile}"
echo ${mypid} > "${lockfile}"


### Launch the Time Machine Backup
# On OSX 10.6, the command `/System/Library/CoreServices/backupd.bundle/Contents/Resources/backupd-helper` is a "BACKUP NOW" command
#On 10.7 and later, Apple introduced the `tmutil` command which would allow to do the same
echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Time Machine backup launched" >> "${logfile}"
/System/Library/CoreServices/backupd.bundle/Contents/Resources/backupd-helper

## The backupd-helper command quits before the save is really finished
## so we check the existence of the process 'backupd'
while [ `/bin/ps -arxo state,comm | /usr/bin/grep backupd | wc -l` -ne 0 ];
do
	echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Time Machine backup still working. Waiting 180 seconds" >> "${logfile}"
	sleep 180
done
echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Time Machine backup succeed !" >> "${logfile}"



### Check if the ssh connection can be made, a ssh keypair without keyphrase must exist.
ssh -q -q -o 'BatchMode=yes' -o 'ConnectTimeout 10' ${ssh_connect} exit &> /dev/null

if [ $? != 0 ]
then
  echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] SSH connection ${ssh_connect} failed." >> "${logfile}"

  # Remove lockfile
  rm -f "${lockfile}"

  exit 69 # service unavailable
fi
echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] SSH connection ${ssh_connect} succeed." >> "${logfile}"


### check if target exists
if ssh ${ssh_connect} "[ ! -d '${target}' ]"
then
  echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Target '${target}' does not exist, backup stopped." >> "${logfile}"

  # Remove lockfile
  rm -f "${lockfile}"

  exit 66 # cannot open input
fi



### Mount the TC volume on the Filesystem
# if mountpoint doesn't exists, we create it
[ -d "$tc_mount_point" ] || mkdir "$tc_mount_point"

# mount the network disc
/sbin/mount_afp "afp://${tc_user}:${tc_pw}@${tc_name}/${tc_share}" "${tc_mount_point}"

# wait for the network disk to be actually mounted
sleep 30

### Make the actual backup of the backup

# check folder for rsync logs
if [ ! -d "${filesPath}"rsync_logs ]
then
    mkdir "${filesPath}"rsync_logs
fi

  echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Rsync started." >> "${logfile}"

/usr/local/bin/rsync3 \
	-e "ssh -p $ssh_port" \
	--bwlimit=75 \
	--archive \
	--compress \
	--human-readable \
	--delete \
	"${tc_mount_point}${tc_file_name}" \
	"${ssh_user}@${ssh_server}:'${target}latest'" | tee -a "${filesPath}"rsync_logs/`date '+%Y-%m-%d_%Hh%Mm%S '

  echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Rsync finished." >> "${logfile}"



### Create "history" folder if it doesn't exists
if ssh ${ssh_connect} "[ ! -d '${target}history/' ]"
then
  ssh ${ssh_connect} "mkdir '${target}history'"
fi


### archive current backup
ssh ${ssh_connect} "cp -al '${target}latest' '${target}history/${date}'"

### Remove backups older than specified days
ssh ${ssh_connect} "$target/historyClean.sh"  # this file have to be created on the backup's destination. It is detailed at the end.

### Unmount the TC Volume
/sbin/umount "${tc_mount_point}"

echo `date '+%Y/%m/%d %H:%M:%S '` "[${mypid}] Remote backup successfully finished ! " >> "${logfile}"
# Remove lockfile, this must always be done at the latest moment possible to avoid conflicting processes.
rm -f "${lockfile}"

Et voilà le script historyCleaning, qui doit être mis directement sur la machine (Unix-like) qui contient les sauvegardes du backup Time Machine (par exemple un NAS Synology).

## VARS
target="/path/to/folder/"  # path to the backup's backup. Must match the one in the main script and contain the trailing slash
tc_file_name="iMac de User.sparsebundle"  # must match the one in the main script
daystokeep=200
## END OF VARS

## We search for backups older than daystokeep ; modification time is only on the hostname.sparsebundle folder, so we search it and then we truncate the path
find "$target"history/*/* -maxdepth 0 -type d -mtime +$daystokeep | sed "s#/$tc_file_name##" > $target/dirsToRemove.txt


## We delete each folder
for j in `cat "$target"dirsToRemove.txt`
do
	# it is advised to check if everything is ok
	echo $j
	# if ok, uncomment this line
	#rm -R $j
done

20 Apr 2014, 00:00

Boucle pour appliquer un script à tous les utilisateurs d'un domaine

Si l’on souhaite appliquer un script à tous les utilisateurs d’un domaine, il faut commencer par générer la liste de tous ces utilisateurs. Ceci peut se faire via la commande powershell

dsquery user -o samid -limit 250 > C:\path\to\domainUsers.txt

qui va lister tous les utilisateurs du domaine, sous la forme SAM ID (nom raccourci), entourés de guillemets. L’otion -limit est facultative, mais par défaut dsquery ne liste que les 100 premières entrées (soit -limit 100).

Puis on éxecute le script suivant

@echo off

REM on parcourt le fichier domainUsers.txt et on passe chaque ligne en argument
for /f "delims=" %%i in ('type C:\path\to\domainUsers.txt') do (C:\path\to\myScript.bat %%i)

Il faudra penser, dans le script, lorsque l’on souhaite récupérer le paramètre, à utiliser %~1 et non %1, ce qui permet de prendre la valeur sans les guillemets.

20 Apr 2014, 00:00

Création d'un répertoire qui contiendra des dossiers privés d'utilisateurs d'un poste ou domaine

Le but de la manipulation est que des utilisateurs désignés d’un poste ou d’un domaine aient chacun un dossier qui leur est privé (accessible uniquement à eux-seuls, en dehors bien sur des administrateurs). Ces dossiers seront également accessibles par le réseau, avec les mêmes limitations. Ces dossiers seront tous situés dans un même dossier racine, qui ne sera même pas navigable par de simples utilisateurs pour éviter qu’ils ne voient les noms des autres utilisateurs ou encore ceux qui ont un dossier personnel.

Commencer par créer le dossier partagé en question. Dans mon exemple ce sera "C:\Dossiers Perso\". Editer les permissions, désactiver l’héritage et conserver les autorisations en tant qu’autorisations explicites. Puis supprimer toutes les permissions relatives aux Utilisateurs, Utilsateurs authentifiés ou Utilisateurs du domaine (ne laisser que des droits aux Administrateurs, en somme).

Aller dans l’onglet de partage du dossier, aller dans le partage avancé, partager le dossier avec le nom que vous souhaitez, et dans les autorisations, donner le controle total à tout le monde. Le faire dans l’onglet de partage simple donnera les mêmes autorisations ACL sur le dossier (ce que nous ne voulons pas), mais dans l’onglet avancé non. Le partage est donc en lecture/écriture à tout le monde, mais en réalité, les ACL du dossier refuseront l’accès.

Puis exécuter le script suivant, en prenant soin de modifier les chemins : (NOTE : il est conseillé de créer un document vierge, de l’enregistrer au format CP850 (ou OEM850 sous Notepad++) puis d’y coller le contenu ; ceci reglera les problèmes d’accès, notamment pour Invité) @echo off REM on supprime l’affichage des commandes

REM on définit le chemin du dossier racine
REM Ne pas mettre de guillemets meme s'il y'a des espaces
REM ils sont ajoutés dans le suite du script. Ne pas mettre l'antislash final
set privateFolderPath=F:\Dossiers Perso

REM Si il y a un argument à la commande on le récupère (sans guillemets, d'ou le %~1) au lieu de %1, sinon on le demande
if not "%~1"=="" (set user=%~1) else (set /p user="Nom de l'utilisateur dont il faut creer le dossier perso ? ")

REM on zappe l'utilisateur invité
REM le nom bizarre vient de la différence d'encodage : CP850 par défaut pour le batch
if %user% == Invité (
    echo On zappe l'utilisateur Invité
    goto :eof
)

REM on teste l'existence de l'utilisateur avec des espaces autour
REM pour être sûr que ce n'est pas juste un bout du nom qui a été trouvé
REM rajouter le commutateur /domain après Net User pour vérifier sur tout le domaine
net user | findstr /i /C:" %user% "
if errorlevel 1 (
    REM s'il est en début de ligne, il n'y a pas d'espace devant. On vérifie
    net user | findstr /i /B /C:"%user% " > NUL
    if errorlevel 1 (
        echo Cet utilisateur n'existe pas
        goto :eof
    )
)

REM S'il n'y a ni dossier ni fichier sur la destination
if not exist "%privateFolderPath%\%user%" (
    REM on crée le dossier
    mkdir "%privateFolderPath%\%user%"
) else (
    REM si il n'y a pas de fichier "." dedans, c'est que c'est un fichier
    if not exist "%privateFolderPath%\%user%\*.*" (
        echo Attention, "%privateFolderPath%\%user%" est un fichier !
        pause
        goto :eof
    )
)

REM On met l'utilisateur en propriétaire et on lui donne le controle total
REM l'utilisation de (OI) et (CI) équivaut à choisir en graphique
REM que les droits s'appliquent à "ce dossier, les sous-dossiers et les fichiers"
icacls "%privateFolderPath%\%user%" /setowner %user% /Q /T
icacls "%privateFolderPath%\%user%" /grant %user%:(OI)F /Q
icacls "%privateFolderPath%\%user%" /grant %user%:(CI)F /Q

Et voilà ! Le dossier de l’utilisateur est créé, il en est propriétaire, et il a (au même titre que les Administrateurs, par l’héritage) le contrôle total dessus. Et aucun utilisateur sans privilège ne peut naviguer son dossier (ni même le dossier "C:\Dossiers Perso" directement). Il peut y accéder en allant directement à "C:\Dossiers Perso\user" ou encore à \\IP_OU_NOM_SERVEUR\Dossiers Perso\user .

Si on souhaite appliquer ce script à tous les utilisateurs d’un domaine, se référer à ce post.