Alex Laverty
Alex Laverty

Reputation: 485

Powershell Script to Install Certificate Into Active Directory Store

I'm trying to write a powershell script to install a certificate into the active directory certificate store,

Here are the steps to do this manually, any help would be greatly appreciated.

On a Windows 2008R2 domain controller,

Click Start -> Run

type MMC

click ok

Click File -> Add/Remove Snap-In

Select "Certificates" -> Add

Select "Service Account"

Click Next

Select "Local Computer"

Click Next

Select "Active Directory Domain Services"

Click Finish

Click Ok

I want the script to install the certificate into :

NTDS\Personal

I would post an image but I don't have enough "reputation" apparently, so I can only provide text instructions.

So basically what I've tried is, I've used this powershell function below to import a certificate into the Local Machine -> Personal Store, which is where most certificates go, and the code works.

But I need to install the certificate into the "NTDS\Personal" store on a domain controller, but the $certRootStore only accepts localmachine or CurrentUser, so I'm stuck : /

function Import-PfxCertificate 
{
    param
    (
        [String]$certPath,
        [String]$certRootStore = "localmachine",
        [String]$certStore = "My",
        $pfxPass = $null
    ) 
    $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2 

    if ($pfxPass -eq $null) 
    {
        $pfxPass = read-host "Password" -assecurestring
    } 

    $pfx.import($certPath,$pfxPass,"Exportable,PersistKeySet") 

    $store = new-object System.Security.Cryptography.X509Certificates.X509Store($certStore,$certRootStore) 
    $store.open("MaxAllowed") 
    $store.add($pfx) 
    $store.close() 
}

Import-PfxCertificate -certPath "d:\Certificate.pfx"

Regards Alex

Upvotes: 4

Views: 8893

Answers (3)

Rob I
Rob I

Reputation: 11

Even though this post is years old, it is still helpful and turns up in searches, so to address the question of "I don't know how NTDS determines which certificate to use when there are multiple in the certificate store", the answer is that you will get unreliable results when there are two or more valid certificates installed that meet the requested criteria so it is recommended to remove the old/unneeded certificate(s) and just leave the newest/best one for the server auth.

Upvotes: 1

Bennett
Bennett

Reputation: 119

Using a combination of what you already had above and the registry keys for the two certificate stores this works.

The only other thing is that I don't know how NTDS determines which certificate to use when there are multiple in the certificate store.

function Import-NTDSCertificate {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$PFXFile,

        [Parameter(Mandatory)]
        [string]$PFXPassword,

        #Remove certificate from LocalMachine\Personal certificate store
        [switch]$Cleanup
        )
        begin{
            Write-Verbose -Message "Importing PFX file."
            $PFXObject = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
            $PFXObject.Import($PFXFile,$PFXPassword,[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)

            $thumbprint = $PFXObject.Thumbprint
        }
        process{
            Write-Verbose -Message "Importing certificate into LocalMachine\Personal"
            $certificateStore = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store('My','LocalMachine')
            $certificateStore.Open('MaxAllowed')
            $certificateStore.Add($PFXObject)
            $certificateStore.Close()

            Write-Verbose -Message "Copying certificate from LocalMachine\Personal to NTDS\Personal"
            $copyParameters = @{
                'Path' = "HKLM:\Software\Microsoft\SystemCertificates\MY\Certificates\$thumbprint"
                'Destination' = "HKLM:\SOFTWARE\Microsoft\Cryptography\Services\NTDS\SystemCertificates\My\Certificates\$thumbprint"
                'Recurse' = $true
            }
            Copy-Item @copyParameters
        }
        end{
            if ($Cleanup){
                Write-Verbose -Message "Removing certificate from LocalMachine\Personal"
                $removalParameters = @{
                    'Path' = "HKLM:\SOFTWARE\Microsoft\SystemCertificates\MY\Certificates\$thumbprint"
                    'Recurse' = $true
                }
                Remove-Item @removalParameters
            }
        }
}

Upvotes: 2

MDMoore313
MDMoore313

Reputation: 3311

Alright, first the bad news. The only managed certificate stores are LocalMachine and CurrentUser, as we have all seen in powershell.

Now, the not so bad news. We know that the 'physical' location store (physical is MS' word, not mine) exists in the registry on the ADDS server, HKLM\Software\Microsoft\Cryptography\Services\NTDS\SystemCertificates. This was dually verified by both

  1. Using procmon while importing a certificate into the store using the mmc snap-in

  2. Scavenging msdn for this nugget

The link in #2 shows that all physical stores for services are stored in the path mentioned above, substituting NTDS for . The real service name, not the display name.

However,

enter image description here

Because of the bad news. Trying to map it in powershell with that reg key as the root and -PSProvider Certificate will prove disappointing, it was the first thing I tried.

What one can try, is using the X509Store constructor that takes an IntPtr to a SystemStore, as described here. Yes, that invovles some unmanaged code, and mixing the two is something I do rarely, but this and googling for HCERTSTORE C# should get you there.

Upvotes: 1

Related Questions