windowspowershellactive-directory

"Cannot find an overload" Error When Using System.DirectoryServices.ActiveDirectoryAccessRule in PowerShell


What I am trying to do: I want to add the user "octo" as a member of "Key Admins". After that, I want to add "Key Admins" to AdminSDHolder and set both write and read permissions on the msDS-KeyCredentialLink attribute for "Key Admins". I have written a PowerShell script to accomplish this, but I encounter the current error when running it.

I am trying to set permissions on the AdminSDHolder object in Active Directory using PowerShell. However, I am encountering an error when creating an instance of the System.DirectoryServices.ActiveDirectoryAccessRule class. Here is the code I am using:

function Set-KeyCredentialLinkPermissions {
    param (
        [Parameter(Mandatory = $true)]
        [string] $groupName,

        [Parameter(Mandatory = $true)]
        [string] $userToAdd
    )

    # Add the user to the group
    try {
        Add-ADGroupMember -Identity $groupName -Members $userToAdd
        Write-Output "$userToAdd was successfully added to the $groupName group."
    } catch {
        Write-Error "An error occurred while adding the user to the group: $_"
        return
    }

    # Get the DistinguishedName of the AdminSDHolder object
    $adminSDHolderDN = (Get-ADObject -Filter { Name -eq "AdminSDHolder" } -Properties DistinguishedName).DistinguishedName

    try {
        # Connect to the AdminSDHolder object
        $adsi = [ADSI]"LDAP://$adminSDHolderDN"

        # Get the ObjectSID of the group
        $groupSID = (Get-ADGroup -Identity $groupName -Properties ObjectSID).ObjectSID

        # Convert the SID to string format
        $identityReference = $groupSID.Value

        # GUID for msDS-KeyCredentialLink attribute
        $guidKeyCredentialLink = "2f68b1d6-f5ae-4cb6-b34f-8108b3409d6b" # msDS-KeyCredentialLink GUID

        # Get the current ACL
        $acl = $adsi.ObjectSecurity

        # Optionally clear existing rules (to leave only msDS-KeyCredentialLink permissions)
        $acl.Access | Where-Object { $_.IdentityReference -eq $identityReference } | ForEach-Object {
            $acl.RemoveAccessRule($_)
        }

        # Create new access rules
        $writeRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
            $identityReference, 
            [System.DirectoryServices.ActiveDirectoryRights]::WriteProperty, 
            [System.Security.AccessControl.AccessControlType]::Allow, 
            [System.DirectoryServices.ActiveDirectorySecurityInheritance]::Descendants, 
            $guidKeyCredentialLink)

        $readRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
            $identityReference, 
            [System.DirectoryServices.ActiveDirectoryRights]::ReadProperty, 
            [System.Security.AccessControl.AccessControlType]::Allow, 
            [System.DirectoryServices.ActiveDirectorySecurityInheritance]::Descendants, 
            $guidKeyCredentialLink)

        # Set general read permission (for descendant user objects)
        $readAllRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
            $identityReference, 
            [System.DirectoryServices.ActiveDirectoryRights]::GenericRead, 
            [System.Security.AccessControl.AccessControlType]::Allow, 
            [System.DirectoryServices.ActiveDirectorySecurityInheritance]::Descendants, 
            [guid]::Empty.ToString())

        # Add access rules and commit changes
        $acl.AddAccessRule($writeRule)
        $acl.AddAccessRule($readRule)
        $acl.AddAccessRule($readAllRule)
        $adsi.ObjectSecurity = $acl
        $adsi.CommitChanges()

        Write-Output "Permissions for msDS-KeyCredentialLink were successfully set on the AdminSDHolder object."
    } catch {
        Write-Error "An error occurred while setting msDS-KeyCredentialLink permissions on the AdminSDHolder object: $_"
    }
}

# Run the function
Set-KeyCredentialLinkPermissions -groupName "Key Admins" -userToAdd "octo"

However, I encounter the following error when running the code:

Set-KeyCredentialLinkPermissions: C:\Users\Administrator\Desktop\msDS-KeyCredentialLink.ps1:80
Line |
  80 |  Set-KeyCredentialLinkPermissions -groupName "Key Admins" -userToAdd " …
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | AdminSDHolder nesnesinde msDS-KeyCredentialLink izinleri ayarlanirken bir hata olustu: Cannot find an overload
     | for "ActiveDirectoryAccessRule" and the argument count: "5".

I created a PowerShell script to achieve the following goals:

Add the user "octo" to the "Key Admins" group.

Add the "Key Admins" group to the AdminSDHolder object.

Set both write and read permissions on the msDS-KeyCredentialLink attribute for the "Key Admins" group.


Solution

  • Note: In the case at hand you're targeting a .NET type's constructor, but since constructors as just special methods, the following also applies to methods.


    Your specific problem was primarily a typo:

    To put it all together, using the last constructor call as an example:

    $readAllRule =
      [System.DirectoryServices.ActiveDirectoryAccessRule]::new(
        $identityReference,
        [System.DirectoryServices.ActiveDirectoryRights]::GenericRead,
        [System.Security.AccessControl.AccessControlType]::Allow,
        [System.DirectoryServices.ActiveDirectorySecurityInheritance]::Descendents,
        [guid]::Empty
      )
    

    [1] This is an unavoidable consequence of PowerShell being a late-bound language, and it is why PowerShell-native solutions are generally preferable to .NET method calls, if available.
    The alternative is to match the constructor / method signature precisely, using casts, if necessary, which is the only way to guarantee long-term stability.
    For a real-life example affecting the System.String.Split method, to which new overloads were added in .NET (Core) and therefore PowerShell (Core) 7, see the bottom section of this answer.