Skip to content

How can I automate certificate-import to group-policy

September 30, 2017

I am building ARM-templates to set up test-environments in Azure. I am using DSC to set up the different machines. One thing I want to automate is to import a certificate to the group-policies. You can do it like this manually on the domain-controller (Active-Directory server):

  • Group Policy Management -> Forest: mydomain.net -> Domains -> mydomain.net -> Group Policy Objects -> Default Domain Policy
  • Right click -> Edit
  • Default Domain Policy -> Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Public Key Policies -> Trusted Root Certification Authorities
  • Right click -> Import

I have laborated with Import-PfxCertificate, CertUtil.exe and .NET C# to accomplish it but haven’t succeeded. What I have tested you can see below, I have put some comments about my thoughts.

Can anyone help me? How should I do this?

First we create a certificate and export it and finally we delete it (we keep the exported one):

$certificateStoreLocation = "CERT:\LocalMachine\My";
$password = ConvertTo-SecureString -String "P@ssword12" -Force -AsPlainText;
 
$certificate = New-SelfSignedCertificate -CertStoreLocation $certificateStoreLocation -DnsName "Test-Certificate";
 
$certificateLocation = "$($certificateStoreLocation)\$($certificate.Thumbprint)";
 
$result = Export-PfxCertificate -Cert $certificateLocation -FilePath "C:\Data\Certificates\Test-Certificate.pfx" -Password $password;
 
Get-ChildItem $certificateLocation | Remove-Item;

List the certificate stores

foreach($item in Get-ChildItem "CERT:\")
{
	Write-Host " - CERT:\$($item.Location)\";
 
	foreach($store in $item.StoreNames.GetEnumerator())
	{
		Write-Host "   - CERT:\$($item.Location)\$($store.Name)";
	}
}

PowerShell – Import-PfxCertificate

$certificateStoreLocation = "CERT:\LocalMachine\Root";
$password = ConvertTo-SecureString -String "P@ssword12" -Force -AsPlainText;
 
Import-PfxCertificate -CertStoreLocation $certificateStoreLocation -FilePath "C:\Data\Certificates\Test-Certificate.pfx" -Password $password;
 
Get-ChildItem $certificateStoreLocation;
 
# Now you can find the certificate in the MMC Certificate Snapin:
# [Console Root\Certificates (Local Computer)\Trusted Root Certification Authorities\Certificates]
 
# Now you can find the certificate in the registry.
# Get-ChildItem "REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\";
 
# I want to put the certificate here:
# Get-ChildItem "REGISTRY::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\SystemCertificates\Root\Certificates\";

PowerShell – CertUtil

CertUtil -p "P@ssword12" -ImportPfx "Root" "C:\Data\Certificates\Test-Certificate.pfx";
 
Get-ChildItem "CERT:\LocalMachine\Root";
 
CertUtil -p "P@ssword12" -ImportPfx -GroupPolicy "Root" "C:\Data\Certificates\Test-Certificate.pfx"# No error but the same result as CertUtil -p "P@ssword12" -ImportPfx "Root" "C:\Data\Certificates\Test-Certificate.pfx".

.NET C#

using(var certificate = new X509Certificate2(@"C:\Data\Certificates\Test-Certificate.pfx""P@ssword12"))
{
	// We only have StoreLocation.CurrentUser and StoreLocation.LocalMachine.
	// Can I use System.Management.Automation.Security.NativeMethods+CertStoreFlags.CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
	// somehow to create/open a store by calling new X509Store(IntPtr storeHandle).
 
	using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
	{
		store.Open(OpenFlags.ReadWrite);
		store.Add(certificate);
	}
}

My imaginary solution

Thought this was a possible solution:

  1. Import the certificate to “CERT:\LocalMachine\Root”
  2. Move the registry-key “HKLM:\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\THUMBPRINT” to “HKLM:\Software\Policies\Microsoft\SystemCertificates\Root\Certificates\THUMBPRINT”
  3. Restart the machine

The registry-keys get correct but the localmachine-root-certificate is still in the certificate-mmc-snapin and no root-certificate is found in the Group Policy Management console.

$certificateRegistryKeyPathPrefix = "HKLM:\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\";
$certificateStoreLocation = "CERT:\LocalMachine\Root";
$password = ConvertTo-SecureString -String "P@ssword12" -Force -AsPlainText;
$pfxCertificatePath = "C:\Data\Certificates\Test-Certificate.pfx";
$policyCertificateRegistryKeyPathPrefix = "HKLM:\Software\Policies\Microsoft\SystemCertificates\Root\Certificates\";
 
# Get the thumbprint from the pfx-file so we can check if it's already in the registry.
$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2;
$certificate.Import($pfxCertificatePath, $password, "DefaultKeySet");
 
$policyCertificateRegistryKeyPath = "$($policyCertificateRegistryKeyPathPrefix)$($certificate.Thumbprint)";
 
$policyCertificateRegistryKey = Get-Item -ErrorAction SilentlyContinue -Path $policyCertificateRegistryKeyPath;
 
if(!$policyCertificateRegistryKey)
{
	$certificateRegistryKeyPath = "$($certificateRegistryKeyPathPrefix)$($certificate.Thumbprint)";
 
	$certificateRegistryKey = Get-Item -ErrorAction SilentlyContinue -Path $certificateRegistryKeyPath;
 
	if(!$certificateRegistryKey)
	{
		$certificate = Import-PfxCertificate -CertStoreLocation $certificateStoreLocation -FilePath $pfxCertificatePath -Password $password;
 
		$certificateRegistryKey = Get-Item -Path $certificateRegistryKeyPath;
	}
 
	Move-Item -Destination $policyCertificateRegistryKeyPath -Path $certificateRegistryKeyPath;
 
	# And then we need to reboot the machine.
}
Advertisements

From → Azure, DSC, PowerShell, Windows

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: