Correction en masse de permissions non héritées (W11)

PAA 40 Points de réputation
2025-09-22T11:56:41.1966667+00:00

Bonjour,

Après de sérieuses difficultés (lesquelles semblent liées originellement à mise en place défaillante d'un antivirus), je me retrouve face au problème suivant :

  • dans une arborescence de disque (D: donc disque non système)
    comprenant essentiellement le dossier Onedrive (mais pas seulement)
  • des droits/permissions ont été attribués individuellement à chaque dossier et chaque fichier
  • l'héritage des droits depuis le niveau supérieur de cette arborescence avait été supprimé et remplacé par ces nouvelles attributions (toutes identiques)
  • j'ai pu rétabli dans une première étape l'héritage issu de la racine de D:\
    Les attributions de permissions de D:\ se sont bien propagées à l'ensemble de l'arborescence.

Cependant je ne trouve aucune méthode pour éliminer massivement ces permissions attribuées élément par élément à mon insu, et sans rique pour les quelques droits légitimes qui sont parfois présents au niveau de quelques dossiers.

Je ne peux pas envisager une rectification manuelle, s'agissant de 15k dossiers et 100k fichiers pour +300 Go de données.

Merci donc aux spécialistes de leurs meilleurs conseils.

Windows pour les particuliers | Windows 11 | Fichiers, dossiers et stockage
0 commentaires Aucun commentaire

Réponse acceptée par l’auteur de la question
Francisco Montilla 30,725 Points de réputation Conseiller indépendant
2025-09-22T13:58:12.2+00:00

Bonjour,

Vous avez déjà fait le plus difficile en rétablissant l’héritage sur D:. La manière la plus propre de supprimer en masse les ACE explicites restants sans toucher aux autorisations héritées consiste à effectuer un premier passage PowerShell pour tout auditer, puis un second passage qui supprime uniquement les règles non héritées. Cela préserve les autorisations héritées et vous permet d’ajouter en liste blanche tout dossier ou compte qui doit conserver des entrées explicites.

Exécutez ces étapes depuis une fenêtre PowerShell avec élévation de privilèges.

Mettez d’abord OneDrive en pause pour éviter l’agitation pendant les modifications d’ACL. Collez ensuite le script ci-dessous tel quel. Il démarre en mode Audit et écrit un CSV afin que vous puissiez examiner exactement ce qui serait supprimé. Lorsque vous êtes satisfait, définissez $DoRemoval sur $true et exécutez-le à nouveau pour effectuer le nettoyage.

# CONFIGURER ICI
$Root = 'D:\'                                   # racine de l’arborescence à corriger
$AuditCsv = 'D:\acl-audit.csv'                  # où écrire l’audit
$FixLog  = 'D:\acl-fix.log'                     # où consigner les changements
$DoRemoval = $false                              # laisser à false pour l’audit. mettre à $true pour supprimer

# Liste blanche de chemins (optionnel). Tout ce qui se trouve sous ces chemins sera totalement ignoré.
$WhitelistPaths = @(
    # 'D:\KeepExplicit\'
)

# Liste blanche de comptes (optionnel). Les ACE explicites pour ces identités seront conservés.
$WhitelistAccounts = @('BUILTIN\Administrators','NT AUTHORITY\SYSTEM','CREATOR OWNER')

# Aide pour tester le préfixe de chemin
function Test-IsUnder {
    param($Path, $Prefix)
    return $Path.StartsWith($Prefix, [System.StringComparison]::OrdinalIgnoreCase)
}

# Collecter les éléments. Ignorer les points de reconnexion pour éviter jonctions/symlinks.
$items = @()
try { $items += Get-Item -LiteralPath $Root } catch {}
$items += Get-ChildItem -LiteralPath $Root -Recurse -Force -Attributes !ReparsePoint -ErrorAction SilentlyContinue

# AUDIT
$report = New-Object System.Collections.Generic.List[object]
$index = 0
foreach ($item in $items) {
    $index++
    Write-Progress -Activity "Auditing ACLs" -Status $item.FullName -PercentComplete (($index / $items.Count) * 100)

    # Ignorer les chemins en liste blanche
    $skip = $false
    foreach ($p in $WhitelistPaths) { if (Test-IsUnder $item.FullName $p) { $skip = $true; break } }
    if ($skip) { continue }

    try {
        $acl = Get-Acl -LiteralPath $item.FullName

        # S’assurer que l’héritage est activé sur cet élément
        if ($acl.AreAccessRulesProtected) {
            $acl.SetAccessRuleProtection($false, $true)
            Set-Acl -LiteralPath $item.FullName -AclObject $acl
            $acl = Get-Acl -LiteralPath $item.FullName
        }

        $explicitRules = $acl.Access | Where-Object { -not $_.IsInherited }
        foreach ($r in $explicitRules) {
            $report.Add([pscustomobject]@{
                Path              = $item.FullName
                Identity          = $r.IdentityReference.Value
                Rights            = $r.FileSystemRights
                Type              = $r.AccessControlType
                InheritanceFlags  = $r.InheritanceFlags
                PropagationFlags  = $r.PropagationFlags
            })
        }

        if ($DoRemoval -and $explicitRules.Count -gt 0) {
            $changed = $false
            foreach ($r in $explicitRules) {
                if ($WhitelistAccounts -contains $r.IdentityReference.Value) { continue }
                # Supprimer la règle explicite exacte
                $null = $acl.RemoveAccessRuleSpecific($r)
                $changed = $true
            }
            if ($changed) {
                Set-Acl -LiteralPath $item.FullName -AclObject $acl
                Add-Content -LiteralPath $FixLog -Value ("Removed explicit ACEs from: " + $item.FullName)
            }
        }
    } catch {
        Add-Content -LiteralPath $FixLog -Value ("Error on: " + $item.FullName + " - " + $_.Exception.Message)
        continue
    }
}

# Écrire l’audit à la fin pour obtenir systématiquement une capture complète
$report | Sort-Object Path, Identity | Export-Csv -LiteralPath $AuditCsv -NoTypeInformation -Encoding UTF8
Write-Host ""
Write-Host "Audit written to $AuditCsv"
if ($DoRemoval) { Write-Host "Changes logged to $FixLog" } else { Write-Host "Removal is disabled. Set `$DoRemoval = `$true to apply the cleanup." }

Voici comment l’utiliser.

Exécutez-le d’abord exactement tel qu’affiché pour que $DoRemoval reste false. Ouvrez D:\acl-audit.csv et examinez quelques chemins pour confirmer qu’il ne répertorie que les entrées explicites non héritées que vous souhaitez supprimer. S’il existe des dossiers qui doivent conserver des ACE explicites, ajoutez leurs préfixes complets à $WhitelistPaths et ajoutez tout compte spécifique à $WhitelistAccounts, puis relancez en mode audit pour vérifier que le CSV est correct. Lorsque vous êtes prêt, passez $DoRemoval à $true, exécutez-le une fois encore et surveillez D:\acl-fix.log pour le suivi. Reprenez enfin la synchronisation OneDrive.

Si vous préférez une réinitialisation rapide et «brute» pour un sous-arbre où vous savez qu’il n’existe aucune entrée explicite légitime, vous pouvez aussi utiliser icacls pour effacer uniquement ce sous-arbre. Par exemple, pour normaliser D:\DataOnly sans toucher à vos exceptions, exécutez ceci depuis une invite de commandes avec élévation :

icacls "D:\DataOnly" /reset /t /c

Si quelque chose n’est pas clair ou si vous voulez que j’adapte la liste blanche à vos entrées spécifiques, donnez-moi un ou deux exemples issus du CSV et j’adapterai le script pour vous.

Cette réponse a-t-elle été utile ?


1 réponse supplémentaire

  1. PAA 40 Points de réputation
    2025-09-29T21:44:50.1033333+00:00

    Hello Francisco,

    Une fois encore, merci pour tous les efforts déployés afin de résoudre définitivement mon cas.

    La situation actuelle est que, en fait, j'avais fini le nettoyage "à la main", et que par la suite il ne restait donc plus grand chose, voire rien à nettoyer, grâce à votre aide pleine d'efficacité.

    J'ai quand même tenu à ne pas gaspiller vos derniers efforts : j'ai donc modifié mon script selon les indications données.

    Je ne m'y suis probablement pas bien pris (du fait de mon ignorance en matière de langage PowerShell) car je bute sur une erreur d'exécution dès son lancement.

    Je joins le script modifié (avec les avant/après bien visibles) PAA-Script3.txt. Le texte des erreurs est ici : PAA-Script3-ExecErrors.txt.Il est question d'une accolade manquante dans une expression qui débute avant l'insertion du nouveau bloc à insérer : effectivement dans cette partie MissingCurvedBrace.txt il y a 8 "{" mais seulement 7 "}". Puis dans le bloc à insérer (final) newbloc.txt, il y en a bien 12 paires.Je n'ai pas les compétences PS nécessaires pour trouver où doit se placer la "}" manquante, ou retirer la "{" excédentaire.

    De plus, il n'y a plus d'obligation de rectifier le tir, puisque l'objectif majeur de ma requête est totalement atteint et je vous en remercie chaleureusement une fois de plus car c'est un grand soulagement pour moi.

    Concernant l'autre problème qui affecte le répertoire Onedrive, sa nature me paraît différente et je suis convaincu qu'il faut continuer à le traiter à part dans https://learn.microsoft.com/fr-fr/answers/questions/5567274/r-pertoire-onedrive-acl-avanc-refuser-suppression. Je vais d'ailleurs y ajouter un commentaire car j'ai fait de nouveaux constats à son sujet.

    Et bien sûr je serais enchanté d'apprendre que vous avez des solutions pour ce cas également !

    Cette réponse a-t-elle été utile ?

    0 commentaires Aucun commentaire

Votre réponse

Les réponses peuvent être marquées comme « Acceptées » par l’auteur de la question et « Recommandées » par les modérateurs, ce qui aide les utilisateurs à savoir que la réponse a résolu le problème de l’auteur.