Last active
January 18, 2021 13:50
-
-
Save IISResetMe/a9bee01a652d9e7d56e267e7f6fedec3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.Synopsis | |
Extends the Active Directory Schema with linked account attributes | |
.DESCRIPTION | |
Extends the Active Directory Schema with linked account attributes for use | |
with Microsoft tiered admin account model and similar account segregation | |
paradigms. | |
Adds a linked attribute pair to the schema to reflect account ownership, and | |
an auxiliary class to associate them with the user object class. | |
.EXAMPLE | |
Extend the schema and return the new schema elements | |
PS C:\> Add-ADSchemaAdminAccountExtensions -OrgPrefix 'myCompany' -PassThru -Confirm:$false | |
attributeID : 1.2.840.113556.1.8000.666.840424748.300608405.1140883067.626181007.520.1 | |
DistinguishedName : cn=myCompany-sourceAccount,CN=Schema,CN=Configuration,DC=corp,DC=mycompany,DC=tld | |
Name : myCompany-sourceAccount | |
ObjectClass : attributeSchema | |
ObjectGUID : bedc07a2-3de3-488b-bae1-606f8bc20f0e | |
attributeID : 1.2.840.113556.1.8000.666.840424748.300608405.1140883067.626181007.520.2 | |
DistinguishedName : cn=myCompany-adminAccounts,CN=Schema,CN=Configuration,DC=corp,DC=mycompany,DC=tld | |
Name : myCompany-adminAccounts | |
ObjectClass : attributeSchema | |
ObjectGUID : 98fd4190-c8f4-4728-a89b-21504e54e71e | |
DistinguishedName : cn=myCompany-adminAccountExtensions,CN=Schema,CN=Configuration,DC=corp,DC=mycompany,DC=tld | |
governsID : 1.2.840.113556.1.8000.666.840424748.300608405.1140883067.626181007.520.3 | |
Name : myCompany-adminAccountExtensions | |
ObjectClass : classSchema | |
ObjectGUID : 4d228e7f-f2bc-4d2b-960e-4531ef03130e | |
.EXAMPLE | |
In the following example, we extend the schema and use Set-ADUser to update existing admin accounts. | |
This change will be reflected on the target account automatically | |
PS C:\> Add-ADSchemaAdminAccountExtensions -OrgPrefix 'iRM' -Confirm:$false | |
PS C:\> Set-ADUser alice-admin -Replace @{ 'iRM-sourceAccount' = (Get-ADUser alice).distinguishedName } | |
PS C:\> Get-ADUser alice -Properties iRM-adminAccounts |% iRM-adminAccounts |Get-ADUser |select sAMAccountName | |
sAMAccountName | |
-------------- | |
alice-admin | |
.NOTES | |
Requires membership of Schema Admins in the forest of the computer, as well as the RSAT ActiveDirectory module | |
#> | |
function Add-ADSchemaAdminAccountExtensions { | |
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] | |
param( | |
[Parameter(Mandatory = $true)] | |
[string]$orgPrefix, | |
[ValidatePattern('^1(?:\.\d+)+$')] | |
[string]$orgOID, | |
[switch]$Force, | |
[switch]$PassThru | |
) | |
$ErrorActionPreference = 'Stop' | |
if(($orgPrefix.Length -lt 2 -or $orgPrefix -cnotmatch '^\p{Ll}\p{L}+$') -and -not $Force){ | |
throw 'Expected org prefix longer than one character, starting with a lowercase letter' | |
} | |
# Discover schema NC | |
$rootDSE = Get-ADRootDSE | |
$schemaNC = $rootDSE.schemaNamingContext | |
# Discover schema master | |
$schemaMaster = Get-ADObject $schemaNC -Properties fSMORoleOwner | Get-ADDomainController -Identity { $_.fSMORoleOwner } | |
# Re-bind against RootDSE on schema master | |
$rootDSE = [ADSI]::new("LDAP://$($schemaMaster.HostName)/RootDSE") | |
# Prepare the refresh the schema a couple of times!!! | |
$schemaRefresh = { | |
$rootDSE.Put("schemaUpdateNow", 1) | |
$rootDSE.SetInfo() | |
} | |
# Generate OID prefix if none is provided | |
if(-not $PSBoundParameters.ContainsKey('orgOID')){ | |
# Slightly modified version of Microsoft's OID generation script | |
# https://gallery.technet.microsoft.com/scriptcenter/56b78004-40d0-41cf-b95e-6e795b2e8a06 | |
$guidBytes = New-Guid |% ToByteArray | |
$orgOID = @( | |
"1.2.840.113556.1.8000.2554" | |
0..7 |%{ | |
[BitConverter]::ToUInt16($guidBytes, $_ * 2) | |
} | |
) -join '.' | |
} | |
# Define defaults | |
$server = @{ | |
Server = $schemaMaster.HostName | |
} | |
$newSchemaDefaults = @{ | |
Path = $schemaNC | |
PassThru = $true | |
Confirm = $false | |
} + $server | |
# Actual extensions | |
if (-not ($Force -or $PSCmdlet.ShouldProcess("Tiered AD Admin Account Schema Extensions", "Add"))) { | |
return | |
} | |
# Forward-link attribute to indicate the owner of a non-primary account | |
$fwdAttrName = "${orgPrefix}-sourceAccount".Trim("-") | |
Write-Verbose "Creating attributeSchema '$fwdAttrName'" | |
$fwdAttributeSchema = New-ADObject -Name $fwdAttrName -Type attributeSchema -OtherAttributes @{ | |
adminDisplayName = $fwdAttrName | |
lDAPDisplayName = $fwdAttrName | |
oMSyntax = 127 | |
attributeSyntax = "2.5.5.1" | |
attributeID = "${orgOID}.1" | |
isSingleValued = $true | |
isMemberOfPartialAttributeSet = $true | |
adminDescription = "Account owner" | |
instanceType = 4 | |
linkID = '1.2.840.113556.1.2.50' | |
showInAdvancedViewOnly = $false | |
} @newSchemaDefaults | |
& $schemaRefresh | |
$fwdAttributeSchema = $fwdAttributeSchema | Get-ADObject -Properties attributeID @server | |
# Backlink attribute reflecting the non-primary accounts referencing this user principal as source/owner | |
$bckAttrName = "${orgPrefix}-adminAccounts".Trim("-") | |
Write-Verbose "Creating attributeSchema '$bckAttrName'" | |
$bckAttributeSchema = New-ADObject -Name $bckAttrName -Type attributeSchema -OtherAttributes @{ | |
adminDisplayName = $bckAttrName | |
lDAPDisplayName = $bckAttrName | |
oMSyntax = 127 | |
attributeSyntax = "2.5.5.1" | |
attributeID = "${orgOID}.2" | |
isSingleValued = $false | |
isMemberOfPartialAttributeSet = $true | |
adminDescription = "Associated admin accounts" | |
instanceType = 4 | |
showInAdvancedViewOnly = $false | |
linkID = $fwdAttributeSchema.attributeID | |
} @newSchemaDefaults | |
& $schemaRefresh | |
$bckAttributeSchema = $bckAttributeSchema | Get-ADObject -Properties attributeID @server | |
# Auxiliary class that may contain our attributes | |
$auxClassName = "${orgPrefix}-adminAccountExtensions".Trim("-") | |
Write-Verbose "Creating classSchema '$auxClassName'" | |
$auxClassSchema = New-ADObject -Name $auxClassName -Type classSchema -OtherAttributes @{ | |
adminDisplayName = $auxClassName | |
lDAPDisplayName = $auxClassName | |
governsID = "${orgOID}.3" | |
mayContain = @( | |
$fwdAttributeSchema.attributeID | |
$bckAttributeSchema.attributeID | |
) | |
objectClassCategory = '3' | |
adminDescription = 'This class adds optional admin account relationship links to user account objects' | |
subClassOf = 'top' | |
} @newSchemaDefaults | |
& $schemaRefresh | |
$auxClassSchema = $auxClassSchema | Get-ADObject -Properties governsID @server | |
# Allow the 'user' object class to be extended with our new auxiliary class | |
Write-Verbose "Adding auxiliary class '$auxClassName' to the 'user' class" | |
Get-ADObject -SearchBase $schemaNC -Filter "Name -like 'user'" @server | Set-ADObject -Add @{ auxiliaryClass = $auxClassSchema.governsID } @server | |
& $schemaRefresh | |
if ($PassThru) { | |
$fwdAttributeSchema | |
$bckAttributeSchema | |
$auxClassSchema | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment