Automation of Web Application Creation in Managed Environments (Part V: Import certificates into cert store)

Before I begin I want to mention that this is one of the things that I have tried to automate at least 4 times in the last 2 years and I just failed again and again before I finally succeeded a couple of days ago. So this is currently my favorite script (yes, I have a favorite script, I am a nerd I know).

The reason why I had such a hard time was that there are a couple of methods described out there in the blogosphere on how to do this and none of them worked for me. Looking at what I was doing and thinking I was doing it wrong rather than expecting that there is a different way or additional effort of doing it took me quite some time to debug/ troubleshoot. On the other hand, if you don’t find anything via google these days, does it really exist? It obviously does (the other explanation would be that I suck at googling, but then I get lots of feedback that I am actually pretty good or at least above average, so that’s not it…)!

Looking a bit more into what Windows Server is bringing to the table in the last couple of weeks as I use Windows Server 2012 more heavily I investigated a bit more around the whole process of requesting and approving certificates and how Windows Server does this in terms of acting as a requester and approver.

So with this new knowledge I finally got it working with the certutil tool and it’s a pretty short script in the end as well.

But before I get to the script that actually does all the magic, why do I want to automate this in the first place?
If you ever counted the number of clicks you have to perform to manually add a certificate to the store you won’t ask…

  • open an mmc.msc via 'Windows + R' Shortcut or typing it in the Start>Search bar.
  • Add the certificates snap-in via File>Add/Remove>Select ‘Certificates’>Click Add>Select ‘Computer Account’>Next>Finish>OK
  • open personal>certificates in the tree and right click>All tasks>Import…>Next>Select File via Browse>Next>Next>Finish>OK

Counting every action here you are at 20 before you have your certificate where you want it and that’s without requesting it and provisioning it on your server. If you do this with 4-8 certificates on 6 servers you understand my pain. I am not lazy, I just hate doing something more than once. Imagine my frustration with these types of numbers.

So now you know why it makes sense to automate this. Why have it as it’s own step? Well the prerequisite of course is that the certificates are available from Part III and as this has nothing to do with SharePoint nor IIS it makes sense to separate it and also allow bulk import functionality.

The request and approve process at the customer I work with is separated between departments, so we use certreq.exe to request the certificate as described in Part III of this series.

In general if you want to troubleshoot something for the sake of efficiency you will want to reduce the dependencies to other persons and departments to be ideally zero. So what I did was use my development machine and Setup a Root Certificate Authority on a windows server 2008.

Then I requested certificates via UI with a local DC/ CA. This was after I found the article on how to import certificates using powershell. The code I reused is displayed below (for your convenience without the irritating question mark symbols).

function Import-509Certificate {
    param([String]$certPath,[String]$certRootStore,[String]$certStore)

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

So now I can call the function I have with something like

Import-509Certificate -certPath "C:\temp\mycert.cer" -certRootStore LocalMachine -certStore My

This will get me my certificate “mycert” into the personal cert store of the localmachine, which is what I want, because only those certificates can later be selected by IIS for the bindings of my IIS Sites in Part VI of this series.

So now that I did this Import-509Certificate this is what my certificate looks like in the store.

No PrivKey 1

and the properties look like this:

No PrivKey 2

So actually it look more like this and please concentrate on the highlighted sections that show the private keys from the machine are available:

PrivKey 1

and the properties should look like this:

PrivKey 2

So with the upper two images I pretty much have nothing. This is where I started overthinking it the first 3-4 times and failed. I didn’t have a password so the pfx script above didn’t help me any and the different constructors and flags for the X509Certificate2 object didn’t help me either. I did this in a couple of variations, tried the API in hopes this was a special case I was using that was not working. No dice.

So fast forward to a couple of days back.

The solution is a lot easier and I came across my building blocks when I found this article.

Certutil or the Certificate Utility sounded to me very similar to the certreq or Certficate Request Tool I was using successfully to create my cert requests. So why not investigate more.

I checked the parameters for the repairstore operation which sounded pretty good to me: Repair key association or update certificate properties or key security descriptor

I googled for the command and I came up with exactly what I wanted: link.

This is the resulting script that works for me.

param(
    [string] $certPath
)

#certutil -addstore My
#certutil -repairstore My 

CertUtil -addstore My $certPath

set-location "cert:\LocalMachine\My";

Get-ChildItem | ? { $_.hasprivatekey -eq $false } | % { certutil -repairstore my $_.Thumbprint }

The input is the full path of the file (the certificate itself – also known as the approved request or the response from the CA).

The certificate utility or certutil is an exe that can be found in the system directory of windows ([system]:\windows\system32\) so it is registered in the powershell of your chosing. The operation addstore allows you to add a certificate to the store you define, which in my case is the personal store of the local machine. This is also known as ‘my’.

In the next step I can set the location which is something I found in a blog I cannot remember. So similar to your registry or IIS when you import the webadministration module you can use your cert store as a directory (which makes absolute sense by the way).

So I set the location to localmachine\my which is the same location I just added my certificate at.

Now comes the brainy part of the script. I get all the child elements, i.e. all the certificates from that store that do not have a private key and I use certutil again with the repairstore parameter and identify the certificate via its thumbprint. Awesome! I don’t even need to have any more parameters, because if there are any other certificates in this store that do not have a private key…hey just keep doing what your doing to all of them…can’t hurt at all.

So once this has run, you will achieve happiness, because your certificate will also appear with the little key-symbol in your cert store. If that’s not the case F5 (refresh) will do the trick.

This is what powershell looks like by the way…

Powershell Output

So that was a lot of text to explain a very short script. The other articles should have a better ratio in this regard. 😉

So…

Continue Reading…Part VI

Back To Part IV
Back To Overview

Attachments:

Advertisements

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: