Tuesday, February 2, 2010

Group policy editing access denied, and sysvol

Hello again, We were recently working out an issue that our "group policy creator owners" members were running into for certain domains. They would be able to create group policies, but when editing the same policy they were receive access denied messages inside the editor. Normally changes for GPO's are made on the primary domain controller (PDC). We checked where they were pointing in GPMC, and checked all permissions for the GPO, no issues found. Sysvol permissions for PDC's were also correct, and these users had access. Looking at bit deeper into the problem with netmon, we noticed that not all GPO editing is done on the PDC. Some of our connections were hitting the nearest domain controller's Sysvol (based on dfs site costing). When checking sysvol permissions there, we realized some issues. Standard Sysvol share permissions give BUILTIN\Authenticated users: Full control permissions. Our build guide for domain controllers removed the full control permissions, but missed the addition of Group policy creator owners (KB article). Some of our older domain controllers still had full control permissions for Authenticated Users. This inconsistent set of permissions explained why certain users in certain regions could make an edit, while another user in a different region with same permission could not. So, to fix a few hundred domain controllers with least administrative effor.... powershell and old resource kit utilities (rmtshare.exe). In my standard code library for powershell I have a function called get-dclist which will give me all domain controllers in a specified domain. With this, it is a 4 line powershell script to fix one domain. More than one domain can be looped in an extra foreach loop.
  $domaincontrollers = get-dclist contoso.com /a

foreach ($controller in $domaincontrollers) {
rmtshare \\$controller\sysvol /GRANT "group policy creator owners":full
rmtshare \\$controller\sysvol /GRANT "authenticated users":read
}
GET-DCLIST function

#note: I have modified this function to simplify it and remove all options
#processing.  The code below may not be 100% correct syntax

function get-dclist ([string]$domain) {

 if (($domain -eq $null) -or ($domain -eq "")) {
  write-host -foregroundcolor "yellow" "Usage:  get-dclist domainname opt"
  write-host -foregroundcolor "yellow" "     Enter name of domain (fqdn or netbios name) to list all domain controllers."

  return
   
 }
 
 $returnarr = new-object collections.arraylist

 $error.clear()
 $remotecon = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $domain)
 $remotedom = [system.directoryservices.activedirectory.domain]::getdomain($remotecon)
 if ($?) {
  foreach ($dc in $remotedom.domaincontrollers) {
   $returnarr.add($dc.name) >$null
  }
 } else {
  write-host
  write-host
  write-host -foregroundcolor "red"  "Domain name entered was not valid or failed to connect"
 }
 return $returnarr
}
If you want to audit your current sysvol share settings with powershell and rmtshare, you can run a loop for all your domain controllers and run "rmtshare \\$servername\sysvol" to output, and dump all to text file. You can use a script like this for basic clean up and a more usable csv output.
Syvol-clean.ps1

$smatch=$false
$pmatch = $true
$outline = ""
$file = get-content c:\temp\sysvol-dump.txt
foreach ($line in $file) {

 if ($line -match "Share name") { 
  $pmatch = $false
  echo $outline
  $marker = $line.indexof("\")
  $server = $line.substring($marker) 
  $smatch = $true
  $outline = $server + ","
 }
 if ($line -match "The command completed") {
  $pmatch = $false
  $smatch = $false
 }
 if ($pmatch -eq $true -and $smatch -eq $false) {
  $marker2 = $line.indexof("\")
  $perm = $line.substring($marker2)
  $perm = $perm + ","
  $outline = $outline + $perm
 }
 if ($line -match "Permissions") {
  $pmatch = $true
  $smatch = $false
 }
 

}

No comments:

Post a Comment