Pages

tirsdag 1. januar 2013

PowerShell: Function to set AD Permission

I wanted to be able to set servicePrincipalName with a PowerShell function. I could not find any function for it, so I created one (Requires PowerShell 3.0):
Function Set-ADPermission {
<#
    .SYNOPSIS
        Add permission for a user or group in ActiveDirectory
    .SYNTAX
        Set-ADPermission
          -Identity <String>
          -PropertyName <String>
          -Target <String>
          -Read
          -Write
    .EXAMPLE
        To give the user svcSQLDbEngine Write permission on property
        servicePrincipalName for himself:
        Set-ADPermission
          -Identity "CONTOSO\svcSQLDbEngine"
          -PropertyName "servicePrincipalName"
          -Target "LDAP://CN=svcSQLDbEngine,OU=ServiceAccounts,DC=contoso,DC=com"
          -Write
    .REQUIREMENTS
        The right to change persmissions in AD
    .OUTPUT
        DirectoryServices.ActiveDirectoryAccessRule
#>
    param(
        [Security.Principal.NTAccount]$Identity,
        [string]$PropertyName,
        [adsi]$Target,
        [switch]$Write,
        [switch]$Read
    )
    If(!$Write -and !$Read){Throw "You must specify either -Write or -Read or both"}
    # Retrieve LDAP Root
    $rootDSE = [adsi]"LDAP://RootDSE"
    # Retrieve Schema Naming Context
    $schemaNC = $rootDSE.Properties["schemaNamingContext"][0]
    # Create DirectorySearcher object
    $ADSearcher = New-Object DirectoryServices.DirectorySearcher
    # Filter on the LDAPDisplayName attribute
    $ADSearcher.Filter = "(&(LDAPDisplayName=$PropertyName))"
    # Search in the Schema
    $ADSearcher.SearchRoot = "LDAP://$schemaNC"
    # Return only one result
    $schemaObj = $ADSearcher.FindOne()
    # Check that we got it
    If(!$schemaObj){Throw "Unable to find $PropertyName in Schema"}
    # Retrieve the GUID of the Attribute Schema
    $schemaIDGUID=@("")
    $schemaIDGUID[0]=$schemaObj.Properties["schemaidguid"][0]
    $oGUID = New-Object GUID $schemaIDGUID
    # Check that we got it
    If(!$oGUID){Throw "Unable to find GUID for $PropertyName in Schema"}
    # Determine the Access Rule
    If($Write -and $Read){$Rights="ReadProperty, WriteProperty"}
    ElseIf($Read){$Rights="ReadProperty"}
    ElseIf($Write){$Rights="WriteProperty"}
    $SecArgs = $Identity,[DirectoryServices.ActiveDirectoryRights]$Rights,"Allow",$oGUID,"None"
    $Rule = New-Object DirectoryServices.ActiveDirectoryAccessRule $SecArgs
    # Check that we got it
    If(!$Rule) {Throw "Unable to build AccessRule for $PropertyName in Schema"}
    # Add the AccessRule to the Object and Commit
    $Target.ObjectSecurity.AddAccessRule($Rule)
    $Target.CommitChanges()
    # Return the AccessRule
    Return $Rule
}

2 kommentarer:

  1. Hi Reidar,

    nice scripting. I do have a question though. Wouldn't it be possible to create a separate OU for service accounts and inherit the right from there?

    SvarSlett
    Svar
    1. Thank you. I always create a separate OU for service accounts and you could set the permission on the OU level if you want a specific user to be able to set the serviceprincipalname on all the user objects in that OU. But I used this script to assign the serviceaccount the right to update itself. I did not need it to be able to update other accounts. If you want to do this manually you would have to use ADSI Edit, so this script helped me to avoid to do this manually.

      Slett