PSPKI icon indicating copy to clipboard operation
PSPKI copied to clipboard

Copying ACL's - Unexpected Results

Open jimchurches opened this issue 5 years ago • 12 comments

Hi Folks

Module Version: 3.7.2 OS: Windows 2019 Possibly related to #113 I have downloaded and am using the updated .dll from #113

Using the following code snippet I'm not getting the expected results.

$template = 'Test Template'
$SourceACL = Get-CertificateTemplate -Name "WebServer" | Get-CertificateTemplateAcl
$DestinationACL = Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl | Remove-CertificateTemplateAcl -Force 
$DestinationACL | Add-CertificateTemplateAcl -AcessRule $SourceACL.Access | Set-CertificateTemplateAcl | Out-Null

Before making any changes I get this:

PS C:\Windows\system32> (Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl).Access


CertificateTemplateRights : Read, Write
Rights                    : Read, Write
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\Authenticated Users
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl
Rights                    : Read, Write, FullControl
AccessControlType         : Allow
IdentityReference         : CONTOSO\Domain Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl
Rights                    : Read, Write, FullControl
AccessControlType         : Allow
IdentityReference         : CONTOSO\Enterprise Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

When running my code snippet above, $SourceACL.Access has the following values and these are what I expect:

PS C:\Windows\system32> $SourceACL.Access 


CertificateTemplateRights : Read
Rights                    : Read
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\Authenticated Users
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, Enroll
Rights                    : Read, Write, Enroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Domain Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, Enroll
Rights                    : Read, Write, Enroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Enterprise Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

After running my code snippet above, the ACLs have changed, but are not what I expect:

PS C:\Windows\system32> (Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl).Access


CertificateTemplateRights : Read, Write
Rights                    : Read, Write
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\Authenticated Users
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Write, Enroll, Autoenroll
Rights                    : Write, Enroll, Autoenroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Domain Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Write, Enroll, Autoenroll
Rights                    : Write, Enroll, Autoenroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Enterprise Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

Note that if I run the following code, all the permissions are removed and I have to use ADSI Edit to fix the object up in AD so I can access it, it is no longer visible in the to PowerShell or via the Certificate Template Console. I think this is the expected outcome and I ran it just to test the individual lines of my snippet above.

Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl | Remove-CertificateTemplateAcl -Force | Set-CertificateTemplateAcl

Am I doing something wrong or is there a bug here?

Thanks!

PS: Perhaps related, the code is also not removing inheritable permissions, I haven't dug into that in any detail but the results above show IsInherited being false and my first assumption is inheritable permissions should be removed, but I haven't really thought that through in detail. In my tests above I have manually removed inheritable permissions via ADSIEdit before running the examples and I haven't fully tested this.

jimchurches avatar Nov 03 '20 03:11 jimchurches

Hi, I'm not really understand the problem you are facing. The snippet from the top is working just fine. Last snippet indeed removes all ACEs from security descriptor and you have to use ADSIEdit to use owner rights and re-gain access to certificate template.

Perhaps related, the code is also not removing inheritable permissions

From my understanding, certificate templates use only explicit permissions on every template. There is no template (at least from default list) that inherits permissions from parent container? Can you tell more about your configuration:

  1. What permissions you have before modification
  2. Code you are running to modify permissions
  3. Actual results
  4. Expected results

Crypt32 avatar Nov 03 '20 08:11 Crypt32

On the inheritable permissions ...

I'm using ADCSTemplate to import certificate templates and it seems to create them with inheritable permissions. I don't seem to get inheritiable permissions when using the the Certificate Template Console, so perhaps its an issue with ADCSTemplate.

As noted in my original post, I haven't dug into this in to much detail at the moment.

jimchurches avatar Nov 03 '20 23:11 jimchurches

Hi

Here is the full process of what I'm doing, including the template export and subsequent import ... I've repeated much of what is above for clarity. I hope this is answering your question?

Step 1 - Manually copy a suitable default template to create two new templates using the Certificate Template Console, adjusting properties as required.

Step 2 - Export templates from the development PKI environment so I can deploy the templates to other PKI environments:

Install-Module ADCSTemplate -Force

$ExportPath = 'C:\Temp\PKITemplates'

if (-not (Test-Path -Path $ExportPath)) {
    New-Item -Path $ExportPath -ItemType Directory | Out-Null
}

$Templates = @(
    'Test SSL Certificate Template'
    'Test Code Signing Template'
)

foreach ($template in $Templates) {
    $fileName = "$(($template -replace ' ', '').Trim()).json"
    Export-ADCSTemplate -DisplayName $template | Set-Content -Path "$ExportPath\$fileName"
}

Step 3 - Import the templates into a new environment

Install-Module ADCSTemplate -Force

$ImportPath = 'C:\Temp\PKITemplates'

$Templates = @(
    'Test SSL Certificate Template'
    'Test Code Signing Template'
)

foreach ($template in $Templates) {
    $fileName = "$(($template -replace ' ', '').Trim()).json"
    New-ADCSTemplate -DisplayName $template -JSON (Get-Content "$ImportPath\$fileName" -Raw)
}

After this step the permissions on the two new templates look like this:

PS C:\Windows\system32> (Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl).Access


CertificateTemplateRights : Read
Rights                    : Read
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\Authenticated Users
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl
Rights                    : Read, Write, FullControl
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\SYSTEM
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl
Rights                    : Read, Write, FullControl
AccessControlType         : Allow
IdentityReference         : CONTOSO\Domain Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl
Rights                    : Read, Write, FullControl
AccessControlType         : Allow
IdentityReference         : CONTOSO\Enterprise Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

NOTE: The new templates also have permissions that are being inherited, but let's ignore that for now.

Step 4 - Fix up permissions:

foreach ($template in $Templates) {
    $SourceACL = Get-CertificateTemplate -Name "WebServer" | Get-CertificateTemplateAcl
    $DestinationACL = Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl | Remove-CertificateTemplateAcl -Force
    $DestinationACL | Add-CertificateTemplateAcl -AcessRule $SourceACL.Access | Set-CertificateTemplateAcl | Out-Null
}

After running this step the permissions on my new templates look like this (they have changed from what they were earlier).

PS C:\Windows\system32> (Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl).Access


CertificateTemplateRights : Read, Write
Rights                    : Read, Write
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\Authenticated Users
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, Enroll, Autoenroll
Rights                    : Read, Write, Enroll, Autoenroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Domain Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl, Enroll, Autoenroll
Rights                    : Read, Write, FullControl, Enroll, Autoenroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Enterprise Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

However, the permission on the WebServer template that I'm using as a source location to copy permissions from look like this.

PS C:\Windows\system32> (Get-CertificateTemplate -DisplayName 'Web Server' | Get-CertificateTemplateAcl).Access


CertificateTemplateRights : Read
Rights                    : Read
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\Authenticated Users
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, Enroll
Rights                    : Read, Write, Enroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Domain Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, Enroll
Rights                    : Read, Write, Enroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Enterprise Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

I also get this result if I output $SourceACL.Access from the code above (as I would expect). You can see the actual permissions on the new templates does not match the permissions on the WebServer certificate template (that is correct in $SourceACL.Access). NT AUTHORITY\SYSTEM does get removed, but the permissions for the remaining objects are not what I expect and don't match the WebServer certificate template.

If I repeat the process and use ADSI Edit to remove the inheritable permissions before running step 4 above (selecting the option to convert all inheritable permissions to direct permissions) the permissions look like this (same as above):

PS C:\Windows\system32> (Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl).Access


CertificateTemplateRights : Read
Rights                    : Read
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\Authenticated Users
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl
Rights                    : Read, Write, FullControl
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\SYSTEM
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl
Rights                    : Read, Write, FullControl
AccessControlType         : Allow
IdentityReference         : CONTOSO\Domain Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Read, Write, FullControl
Rights                    : Read, Write, FullControl
AccessControlType         : Allow
IdentityReference         : CONTOSO\Enterprise Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

If I now run Step 4, having removed the inheritable permissions, the resulting permissions look like this (different from above, but still not the expected result ...):

PS C:\Windows\system32> (Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl).Access


CertificateTemplateRights : Read, Write
Rights                    : Read, Write
AccessControlType         : Allow
IdentityReference         : NT AUTHORITY\Authenticated Users
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Write, Enroll, Autoenroll
Rights                    : Write, Enroll, Autoenroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Domain Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

CertificateTemplateRights : Write, Enroll, Autoenroll
Rights                    : Write, Enroll, Autoenroll
AccessControlType         : Allow
IdentityReference         : CONTOSO\Enterprise Admins
IsInherited               : False
InheritanceFlags          : None
PropagationFlags          : None

Playing around I have also found the following.

  • Import the templates (Step 3 above).
  • Use ADSI Edit to remove inheritiable permissions
  • Use ADSI Edit to remove all permissions and give Enterprise Admins 'Full Controll'
  • Run the following code
Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl | Remove-CertificateTemplateAcl -Force | Add-CertificateTemplateAcl -Identity 'CONTOSO\Enterprise Admins' -AccessType Allow -AccessMask Read | Set-CertificateTemplateAcl
Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl | Add-CertificateTemplateAcl -Identity 'CONTOSO\Enterprise Admins' -AccessType Allow -AccessMask Write | Set-CertificateTemplateAcl
Get-CertificateTemplate -DisplayName $template | Get-CertificateTemplateAcl | Add-CertificateTemplateAcl -Identity 'CONTOSO\Enterprise Admins' -AccessType Allow -AccessMask Enroll | Set-CertificateTemplateAcl

The result from line 1 and 2 from this snippet looks okay, the template gets read and write permissions only. When I run the third line to configure 'enroll' things break and I have to use ADSI Edit to fix them as the template is no longer available to PowerShell or the Certificate Template Console.

I hope this information is useful and I'm not missing something obvious.

jimchurches avatar Nov 04 '20 00:11 jimchurches

Looks like I see the problem and can replicate.

Crypt32 avatar Nov 04 '20 19:11 Crypt32

Awesome. Thanks for the your efforts here!

jimchurches avatar Nov 04 '20 22:11 jimchurches

A small update (not related to this issue, but same subject): https://github.com/PKISolutions/PSPKI/issues/130

Crypt32 avatar Nov 05 '20 16:11 Crypt32

Another related: https://github.com/PKISolutions/PSPKI/issues/131

Crypt32 avatar Nov 05 '20 17:11 Crypt32

Another related: https://github.com/PKISolutions/PSPKI/issues/132

Crypt32 avatar Nov 05 '20 17:11 Crypt32

Finally, got it working. Please, check if this DLL works for you: SysadminsLV.PKI-v3.2.7.5.zip

Crypt32 avatar Nov 05 '20 18:11 Crypt32

That appears to be working for me thank you! With the updated .DLL I am now getting the results I expect when both copying ACLs to a new template or attempting to set new permission on a certificate template.

I still have to deal with inheritable permissions separately using ADSI Edit and not in my script.

jimchurches avatar Nov 05 '20 23:11 jimchurches

Thanks for confirming this!

Crypt32 avatar Nov 06 '20 06:11 Crypt32

@jimchurches I was facing the same problem with inheritable permissions on new templates created outside of the console. Maybe you can use this sample code for removing inheritable permissions:

# Set permissions for deployment account before remove inheritance
Get-certificateTemplate -Name "$NewTemplateName" | Get-CertificateTemplateAcl `
| Add-CertificateTemplateAcl -User $DeploymentAccount -AccessType "Allow" -AccessMask Read, Write `
| Set-CertificateTemplateAcl -Verbose

# Remove Inheritance from new template.
<#
isProtected Boolean 
true to protect the access rules associated with this ObjectSecurity object from inheritance; false to allow inheritance.

preserveInheritance Boolean 
true to preserve inherited access rules; false to remove inherited access rules. This parameter is ignored if isProtected is false.
#>
$template = Get-certificateTemplate -Name "$NewTemplateName" -ErrorAction Stop -verbose
$adsi = [ADSI]("LDAP://" + $template.DistinguishedName)
$adsi.ObjectSecurity.SetAccessRuleProtection($true, $false) 
$adsi.CommitChanges()


# Set wanted permissions 
Get-certificateTemplate -Name "$NewTemplateName" | Get-CertificateTemplateAcl  `
| Add-CertificateTemplateAcl -User "Domain Admins", "Enterprise Admins", $CATemplMgr -AccessType "Allow" -AccessMask Read, Write  `
| Set-CertificateTemplateAcl  -Verbose

Get-certificateTemplate -Name "$NewTemplateName" | Get-CertificateTemplateAcl  `
| Add-CertificateTemplateAcl -User $inputTemplate.DomainLocalGroupName -AccessType "Allow" -AccessMask $inputTemplate.AccessMask  `
| Set-CertificateTemplateAcl -Verbose

# Remove temporary deployment account permissions
Get-certificateTemplate -Name "$NewTemplateName" | Get-CertificateTemplateAcl  `
| Remove-CertificateTemplateAcl -User $DeploymentAccount -AccessType "Allow" `
| Set-CertificateTemplateAcl  -Verbose

bencoremans avatar May 27 '21 05:05 bencoremans

Fixed in v4.0.0

Crypt32 avatar Jun 15 '23 07:06 Crypt32