Skip to main content
Version: 3.0.0-preview

Active Directory Permission Model

  • Version: 3.0
  • Methodology: Extracted from [MaesterTest] Permission attribute on each AD test
  • Total tests: 270
  • Format: <Service>:<Kind>:<Name>

The permission model documents the exact minimum permissions each built-in AD test requires. It does not describe human role names (e.g., Domain Admin); it describes the technical permission a test needs to retrieve its data.

Permission Formatโ€‹

Every AD test declares its permissions via the [MaesterTest] Permission attribute as one or more strings in this format:

<Service>:<Kind>:<Name>
SegmentDescriptionExamples
ServiceService registry name the test also lists in ServiceActiveDirectory, Graph, Azure
KindKind of grant for that serviceLdap, Cim, File, Remoting, Group
NamePermission as the product spells it (everything after the second colon)domainDNS.msDS-Behavior-Version:ReadProperty, SYSVOL:Read, Microsoft.PowerShell

AND / OR semanticsโ€‹

  • Array elements are AND โ€” the identity needs every element.
  • Pipe | inside an element is OR โ€” any one alternative is enough, least privileged first.
# Both required
Permission = ('ActiveDirectory:Ldap:user:ReadProperty', 'ActiveDirectory:Ldap:group:ReadProperty')

# Either sufficient
Permission = 'ActiveDirectory:Ldap:domainDNS.name:ReadProperty | ActiveDirectory:Ldap:domainDNS:ReadProperty'

# (One domain attribute OR another) AND group access
Permission = ('ActiveDirectory:Ldap:domainDNS.name:ReadProperty | ActiveDirectory:Ldap:domainDNS:ReadProperty',
'ActiveDirectory:Ldap:group:ReadProperty')

Use parenthesized constant lists ('a', 'b') in the attribute, not @('a', 'b').

Examplesโ€‹

TestPermission stringWhat it means
AD-DOM-01ActiveDirectory:Ldap:domainDNS.name:ReadPropertyRead the name attribute on the domainDNS object via LDAP
AD-DACL-01ActiveDirectory:Ldap:*.ntSecurityDescriptor:ReadControlRead ntSecurityDescriptor (with DACL) on all object classes via LDAP
AD-GPO-01ActiveDirectory:Ldap:groupPolicyContainer.gPCFileSysPath:ReadPropertyRead GPO LDAP metadata
AD-GPO-01ActiveDirectory:File:SYSVOL:ReadRead GPO files from SYSVOL share
AD-DNS-01ActiveDirectory:Cim:root\MicrosoftDNS:MicrosoftDNS_Zone:ReadRead DNS zone data via CIM
AD-DNS-01ActiveDirectory:Remoting:Microsoft.PowerShellExecute commands via PowerShell remoting endpoint
AD-DC-02ActiveDirectory:Cim:root\Microsoft\Windows\SMB:MSFT_SmbServerConfiguration:ReadRead SMB configuration via CIM

These are technical permission strings, not human role names. A test that requires ActiveDirectory:Ldap:groupPolicyContainer.gPCFileSysPath:ReadProperty needs the technical ability to read that specific GPO attribute; it does not require membership in a built-in administrative group.

Querying Test Permissionsโ€‹

Every AD test declares its permissions via the [MaesterTest] Permission attribute. You can query them dynamically:

Import-Module Maester -Force
$test = Get-MtTest -Path ./tests/ad/domain/Test.AD-DOM-01.ps1
$test.Permission # outputs: ActiveDirectory:Ldap:domainDNS.name:ReadProperty

Or discover all AD test permissions in bulk:

Get-ChildItem ./tests/ad -Recurse -Filter 'Test.AD-*.ps1' | ForEach-Object {
$test = Get-MtTest -Path $_.FullName
[PSCustomObject]@{
Id = $test.Id
Permissions = $test.Permission -join '; '
}
}

The ADPermissionValidation.Tests.ps1 unit test validates that every AD test's Permission attribute parses without engine errors. Run it to verify the model:

Invoke-Pester ./powershell/tests/general/ADPermissionValidation.Tests.ps1

Active Directory Permission Kindsโ€‹

KindName formatExample
Ldap[<partition>/]<objectClass>[.<attribute>]:<right>ActiveDirectory:Ldap:Configuration/*:ReadProperty
Cim<namespace>:<class>:<right>ActiveDirectory:Cim:root\MicrosoftDNS:MicrosoftDNS_Zone:Read
File<share>:<right>ActiveDirectory:File:SYSVOL:Read
Remoting<endpoint>ActiveDirectory:Remoting:Microsoft.PowerShell
Group<group name>ActiveDirectory:Group:Remote Management Users

For LDAP, the optional partition is Configuration or Schema; omitted means the domain. objectClass.attribute reads one attribute; omitting .attribute reads all attributes of that object class.

Tests Requiring Elevated Privilegesโ€‹

A standard authenticated user (Domain User) can read most LDAP attributes on most objects via the default security descriptor. The following tests require privileges beyond what a standard Domain User holds by default.

DACL Tests (18 tests)โ€‹

TestsRequired PermissionWhy It Requires Elevation
AD-DACL-01 through AD-DACL-18ActiveDirectory:Ldap:*.ntSecurityDescriptor:ReadControlReading the DACL portion of ntSecurityDescriptor is restricted. Standard users can read the owner and group, but not the full DACL.

DNS Tests (19 tests)โ€‹

TestsRequired PermissionsWhy It Requires Elevation
AD-DNS-01 through AD-DNS-19ActiveDirectory:Cim:root\MicrosoftDNS:MicrosoftDNS_Zone:Read, ActiveDirectory:Remoting:Microsoft.PowerShellRemote CIM/WMI access and PowerShell remoting both require administrative or specific group membership.

DC Management Tests (3 tests)โ€‹

TestsRequired PermissionsWhy It Requires Elevation
AD-DC-02, AD-DC-03, AD-DC-04ActiveDirectory:Cim:root\Microsoft\Windows\SMB:MSFT_SmbServerConfiguration:Read, ActiveDirectory:Remoting:Microsoft.PowerShellRemote CIM access for SMB server configuration and PowerShell remoting execution require elevated access.

GPO Tests (40 tests)โ€‹

TestsRequired PermissionWhy It May Require Elevation
AD-GPO-01 through AD-GPO-05, AD-GPOL-01 through AD-GPOL-06, AD-GPOREP-01 through AD-GPOREP-20, AD-GPOS-01 through AD-GPOS-09ActiveDirectory:File:SYSVOL:ReadReading files from the \\domain\SYSVOL share. While Authenticated Users typically receive read access to SYSVOL, this is filesystem access separate from LDAP and may be restricted in hardened environments.

Summary: 80 of 270 AD tests (30%) require privileges beyond a standard authenticated user. The remaining 190 tests can run with standard Domain User LDAP read access.

Category Summaryโ€‹

CategoryTestsRequired permissions
cfgAD-CFG-01 through AD-CFG-24ActiveDirectory:Ldap:Configuration/*:ReadProperty
compAD-COMP-01 through AD-COMP-10ActiveDirectory:Ldap:computer:ReadProperty
daclAD-DACL-01 through AD-DACL-18ActiveDirectory:Ldap:*.ntSecurityDescriptor:ReadControl
dcAD-DC-01 through AD-DC-08ActiveDirectory:Ldap:nTDSDSA:ReadProperty; AD-DC-02 through AD-DC-04 also need ActiveDirectory:Cim:root\Microsoft\Windows\SMB:MSFT_SmbServerConfiguration:Read and ActiveDirectory:Remoting:Microsoft.PowerShell
dcdAD-DCD-01 through AD-DCD-04ActiveDirectory:Ldap:nTDSDSA:ReadProperty
dcompAD-DCOMP-01 through AD-DCOMP-09ActiveDirectory:Ldap:computer:ReadProperty
dfsrAD-DFSR-01ActiveDirectory:Ldap:domainDNS.distinguishedName:ReadProperty
dnsAD-DNS-01 through AD-DNS-19ActiveDirectory:Cim:root\MicrosoftDNS:MicrosoftDNS_Zone:Read, ActiveDirectory:Remoting:Microsoft.PowerShell
domAD-DOM-01 through AD-DOM-08ActiveDirectory:Ldap:domainDNS:ReadProperty
domsAD-DOMS-01ActiveDirectory:Ldap:domainDNS:ReadProperty
featAD-FEAT-01 through AD-FEAT-02ActiveDirectory:Ldap:msDS-OptionalFeature:ReadProperty
fgppAD-FGPP-01 through AD-FGPP-04ActiveDirectory:Ldap:msDS-PasswordSettings:ReadProperty
forAD-FOR-01 through AD-FOR-04ActiveDirectory:Ldap:crossRef:ReadProperty
forsAD-FORS-01 through AD-FORS-04ActiveDirectory:Ldap:crossRef:ReadProperty
gchgAD-GCHG-01ActiveDirectory:Ldap:group:ReadProperty
gmcAD-GMC-01 through AD-GMC-11ActiveDirectory:Ldap:group:ReadProperty; GMC-01 also needs ActiveDirectory:Ldap:group.member:ReadProperty
gpoAD-GPO-01 through AD-GPO-05ActiveDirectory:Ldap:groupPolicyContainer.gPCFileSysPath:ReadProperty, ActiveDirectory:File:SYSVOL:Read
gpolAD-GPOL-01 through AD-GPOL-06ActiveDirectory:Ldap:groupPolicyContainer.gPCFileSysPath:ReadProperty, ActiveDirectory:File:SYSVOL:Read
gporepAD-GPOREP-01 through AD-GPOREP-20ActiveDirectory:Ldap:groupPolicyContainer.gPCFileSysPath:ReadProperty, ActiveDirectory:File:SYSVOL:Read
gposAD-GPOS-01 through AD-GPOS-09ActiveDirectory:Ldap:groupPolicyContainer.gPCFileSysPath:ReadProperty, ActiveDirectory:File:SYSVOL:Read
grpAD-GRP-01 through AD-GRP-10ActiveDirectory:Ldap:group:ReadProperty
krbtgtAD-KRBTGT-01 through AD-KRBTGT-03ActiveDirectory:Ldap:user:ReadProperty
msaAD-MSA-01ActiveDirectory:Ldap:msDS-GroupManagedServiceAccount:ReadProperty
ouAD-OU-01 through AD-OU-05ActiveDirectory:Ldap:organizationalUnit:ReadProperty
printAD-PRINT-01ActiveDirectory:Ldap:printQueue:ReadProperty
pwdpolAD-PWDPOL-01 through AD-PWDPOL-07ActiveDirectory:Ldap:domainDNS:ReadProperty
replAD-REPL-01 through AD-REPL-02ActiveDirectory:Ldap:nTDSConnection:ReadProperty
rootdseAD-ROOTDSE-01 through AD-ROOTDSE-03ActiveDirectory:Ldap:domainDNS:ReadProperty
schAD-SCH-01 through AD-SCH-05ActiveDirectory:Ldap:attributeSchema:ReadProperty
siteAD-SITE-01 through AD-SITE-05ActiveDirectory:Ldap:site:ReadProperty
spnAD-SPN-01 through AD-SPN-13ActiveDirectory:Ldap:computer:ReadProperty, ActiveDirectory:Ldap:user:ReadProperty
subAD-SUB-01 through AD-SUB-11ActiveDirectory:Ldap:subnet:ReadProperty
trustAD-TRUST-01 through AD-TRUST-07ActiveDirectory:Ldap:trustedDomain:ReadProperty
userAD-USER-01 through AD-USER-29ActiveDirectory:Ldap:user:ReadProperty

Known Misleading Outcomesโ€‹

The following behaviors can hide incomplete access. They are documented here so operators do not misinterpret empty or partial results as proof of a clean configuration.

DACL tests (AD-DACL-*)โ€‹

Get-MtLdapDacl delegates to Invoke-MtLdapSearch and returns an empty array when no entries match. An empty result is indistinguishable from insufficient access. Tests set $testResult = $true even when the array is empty, so a pass does not prove the DACL was fully read.

GPO tests (AD-GPO-, AD-GPOL-, AD-GPOREP-, AD-GPOS-)โ€‹

Get-MtADGpoState can return a non-null state with an empty GPO array. A non-null check therefore does not establish that GPO data was retrieved. GPO reads also depend on SMB/SYSVOL file access; an LDAP probe alone does not prove policy files were read.

DNS tests (AD-DNS-*)โ€‹

If Invoke-MtADManagementCommand fails, the DNS category collector throws. Get-MtADDomainState catches the failure and leaves DNS arrays empty. The helper then skips with NotConnectedActiveDirectoryDNS, which does not distinguish "server has no data" from "query could not retrieve data."

Configuration tests (AD-CFG-*)โ€‹

Get-MtLdapConfigurationContainer catches individual query errors. The state object survives with empty arrays or null properties even when subqueries did not return data.

Transport and cacheโ€‹

WinRM HTTPS-to-HTTP Negotiate fallback (commit ca74fc79) means a successful management result may have used HTTP; it does not prove the HTTPS listener or certificate was validated. Get-MtADGpoState caches by resolved domain and may reuse state across DCs. The target-scoped Get-MtADDomainState cache includes resolved target identity. Do not assume all scoped collections share unscoped data.

This documents current behavior, not a future enforcement model. Tests do not consistently emit LimitedPermissions or NotAuthorized when access is insufficient. A pass, skip, empty collection, or null result must be interpreted with the specific test's known ambiguity in view.