Tuesday, 1 November 2016

Request Subject Alternative Name certificate with PowerShell

Finally I managed to write this script. I had this on my agenda for quite a while and last week in the end I did.

Whoever went through all the 21 steps for requesting a SSL certificate with a custom Subject Alternative Name will know what it actually means to do monkey business.

Hence I wrote myself a PowerShell script. The script requires two files:
* An settings template .inf file that defines the certificate request settings.
* A JSON file with all the information about the Distinguished Name of the certificate, like Common Name, Organization and Subject Alternative Names.

My script will parse the JSON file and create a temporary policy file. From this temporary file it will build a certificate signing request using certreq.exe command-line tool.

The script should be started from an elevated command prompt like this:
C:> .\Create-SanCsr.ps1 -SettingsFileInf .\Settings.inf -CsrFileJson .\csr.json -OutFile MyCertRequest.txt

This Link (opens in a new window) is to the example JSON.
This Link (opens in a new window) is to the settings.inf.

This is my script Link (opens in a new window):
 

Saturday, 4 June 2016

PowerShell is limited on certificate operations

This is a story of failure and how PowerShell is lacking when it comes to certificate operations. It is not lacking when it comes to operating with the Windows certificate stores or when it comes to managing the PKI with PowerShell cmdlets, but it is weak when operating with certificates themselves, converting and manipulating them and working with 'open' standards.

My requirements were as follows: write a PowerShell script which will download the certificate chain from a Microsoft CA, convert the chain to a format that is OpenSSL compliant and can be imported to F5 BIG-IP. User ONLY PowerShell and .NET namespaces, not OpenSSL for Windows or whatever else one could imagine.
The first part is not that complicated. The snippet below is not very beautiful but it illustrates the process of downloading the chain to a file and the required user input.

In the example below I used variables and hard coded the URL, this should better be done with parameters in a function.

## Variables
$cred = Get-Credential -UserName "$env:USERDOMAIN\$env:USERNAME" -Message "Enter Password"
$PKIurl = "https://my-issuingca"

## Get Chain from CA
$WebResponse = (Invoke-WebRequest -Uri ("$PKIurl/certsrv/certnew.p7b?ReqID=CACert&Renewal=1&Enc=b64") -Credential ($cred)).RawContent
$WebResponse | Out-File $env:TMP\WebResponse.tmp
Get-Content $env:TMP\WebResponse.tmp | select -Skip 10 | Set-Content .\certnew.p7b
Remove-Item $env:TMP\WebResponse.tmp -Force

There are two things worth to explain:
* The protocol (http or https) and hostname of the CA server are required as well as the username and password of the current user are required in order to authenticate to the IIS on the CA server.
* The part right of the protocol/hostname is always the same and can be hardcoded in the script.
* You may notice that I save the response to a temporary file and remove the first 10 lines. Why? Because they are the response header for the web server, from line 11 the actual certificate chain begins. This is what I need.
* And, as you can see, I download the chain in Base64 encoding. Again - why? Because the .NET namespace used in the second part of the script (for converting the certificates) requires reading from Base64 and cannot read from binary encoded file.

However the second part is also where PowerShell fails. I did not find a way, to decode the chain in a way where PowerShell will properly convert the line breaks.
I can read all certs from the chain, export each of them to single files, compose a new chain file with all certificates from the chain - but OpenSSL or F5 BIG-IP will not be able to read it properly, because the line breaks are not in the proper format.

This is the second script, suggestions for fixing it are welcome:

Thursday, 14 April 2016

Comparing MD5 hashes with PowerShell

I do very much appreciate when software publishers publish the MD5 hashes of their binaries or image files. This way I can verify that a file has not changed as a result of a faulty file transfer, a disk error or other manipulation.
PowerShell has a (not very well known) cmdlet for creating MD5 hashes - Get-FileHash.
However, this was still to manual for me. Compute the file hash, read the hash from the .md5 file and manually compare the hashes.
Therefore I wrote myself a small PowerShell script that required two parameters - the path to the binary or image file and the path to the .md5 file. It assumes that the hash is the first 32 characters in the .md5 file.

An example how to run the script would be:

PS C:\Users\admin\Downloads> .\Check-Md5Sum -param1 .\windows81.iso -param2 .\windows81.md5

Wednesday, 13 April 2016

Finding duplicate alerts in SharePoint

SharePoint alerts are email notifications sent out by SharePoint in case anything changes in a Document Library or any kind of List (e.g. Task Lists, Announcements, Calendars, etc.).
There are plenty of good reasons to setup alerts - you edit the work on the same set of documents with different people and want to get notified if some document is changed, you want to get notifications on new events in a calendar, or you want to monitor changes in a Document Library.

Now alerts are something very much user-related. You can easily setup alerts for other team members of groups via the SharePoint webpages, but to track who has set which alert for himself is not possible.
Recently I was asked: “Why I always get this alarm twice?”. PowerShell to the rescue.

We have available the following information:
  • Username ($_.User)
  • Site Collection URL ("https://marketing.contoso.com")
  • URL of the Subsite ($_.ParentWebUrl)
  • Name of the List / Library ($_.Title)

The bellow code snippet works for hostnamed site collections and will check for a specific library in a specific subsite.

$SPsite = Get-SPSite "https://marketing.contoso.com"
$SPweb = $SPsite.AllWebs
$ListID = $SPweb.Lists | select Title, ID, ParentWebUrl | where { $_.Title -like "*Workshops*" -AND $_.ParentWebUrl -like "*digitalmarketing*" }
$SPweb.Alerts | select Title, User, ListID | where { $_.ListID -eq $ListID.ID.Guid -AND $_.User -like "*CONTOSO\william.faulkner*" }

Thursday, 24 March 2016

Why ASAP won't help you to get help faster

I read the phrases ASAP or URGENT quite often. In ticketing or issue tracking systems, in chats or also in emails. In emails they are usually accompanied with the High Importance flag.
To tell the truth to all the project managers out there - adding this kind of metadata to your issue won’t help you to get your issue solved faster.

It will just lead to the following:

1. One will read your request, evaluate the issue and prioritize it accordingly among the other issues he or she has on the to-do list.
2. If you managed to build a solid record of marking EVERYTHING as important, then you will always go last on the to-do list.

It is not rude to use ASAP or to ask for immediate help if deadlines are approaching or the business is stuck because of the issue.
But if you constantly overemphasize your issues it just shows one thing - you don’t know how to prioritize properly.

Furthermore - If your issue is that urgent, pick up the phone and give the person a call. People do check their email regularly, so as long as the subject line catches their attention, you are likely to get help soon.
Instead of flagging the mail with ASAP or High Importance use a subject line like: “Customer needs answer today” - It perfectly describes the deadline without setting a rude or desperate tone.

Wednesday, 23 March 2016

A simple TCP listener in PowerShell

Sometimes you have to make a point. Today my point was: “If you do THIS on the firewall, I can connect from server A, B and C to THAT on server D.”

Unfortunately THAT was not yet installed on server D, but I wanted to have a successful test. Therefore I needed to have something on server D that is listening on the same port like THAT.
Since one can use .NET Framework classes from within Windows PowerShell it is possible to write a script which starts a TcpListener server and simulates that on server D THAT missing piece is already installed.

Just invoke the script with the parameters:
PS C:\Users\daniel\Desktop> .\Start-TcpListener.ps1 -IpAddress 127.0.0.1 -TcpPort 9090

And this is the script:

Sunday, 20 March 2016

EDC: Gerber Paraframe II

I bought this knife in October 2015 and since then it became part of my everyday equipment.

The Paraframe II is a one-handed opening stainless steel knife with an open frame. The blade can be opened with one hand, but it doesn't really go easy with one hand. The frame-lock on the other hand is rock solid, not matter if the blade is in open or closed position

I use the knife quite frequently - for cutting open packaging, going on a mushroom foray or to disembowel fish. It's a great knife. However, when cutting cardboard the knife requires more frequent sharpening.

The size is good, the clip is strong and the knife has a constant place in my backpack.