Windows PowerShell cmdlets to secure PSCredential Objects

I have previously discussed securing credentials using Windows Powershell atPowershell: Securing credentials using the PSCredential class. In this article, I will discuss a number of cmdlets I have created to secure credentials using a Advanced Encryption Standard (AES) encryption key to retrieve the content from a encrypted standard string.

As I am using an encryption key and storing the information in a content file, I will be using ACLs on the NTFS filesytem to control access. Alternative methods could be to store the encryption key in a database or use a certificate to control access to the item. Also, in practice I will store the encryption key on a remote file server.

Firstly, we need to create the encryption key using the ‘New-EncryptionKey’ cmdlet to which we use the RNGCryptoServiceProvider class to generate a random byte array for the encryption length. By default, the cmdlet using a 32-byte array to support the AES 256-bit encryption length. The cmdlet also supports using 128-bit and 192-bit encryption lengths which a 16-byte and 24-byte array. The random byte array for the specified encryption length is generated and sends the output to a file which will be the encryption key content.

Once the content has sent to the output file, the content of random byte array is then removed from the current session.

# Creates an AES 256-bit encryption key at the location D:\Output\Keys\mykey.key
New-EncryptionKey -Output D:\Output\Keys\mykey.key 

# Creates an AES 192-bit encryption key at the location D:\Output\Keys\mykey.key
New-EncryptionKey -Bytes 24 -Output D:\Output\Keys\mykey.key

We have now created an encryption key so that we may now convert the secure string for a credential object password using the specified encryption key and sends the output to a password file using the ‘New-EncryptedString’ cmdlet. The cmdlet will retrieve the content of the specified file containing the encryption key and from the stored credential objects convert the secure string of the password to an encrypted standard string and send the output to a file and clear the content of the stored encryption key from the current session.

New-EncryptedString -KeyFile D:\Output\Keys\mykey.key -PasswordFile D:\Output\Passwords\mypassword.txt 

Finally we want to retrieve the credential object to use as a variable to pass to a subsequent cmdlet which will require authentication. The content of the password file is retrieved and converted to a secure string using the content of the encryption key and stored as a password variable and passed to the PSCredential class to represent a set of security credentials and return the object. For subsequent cmdlets I can use the ‘$Password.GetNetworkCredential().Password’ property value for authentication from the PSCredential object.

$Password = Get-PSCredentialObject -Username administrator -KeyFile D:\Output\Keys\mykey.key -PasswordFile D:\Output\Passwords\mypassword.txt 

The cmdlets are available from the below:

New-EncryptionKey –
New-EncryptedString –
Get-PSCredentialObject –

Creating JetBrains YouTrack issues with Windows PowerShell

YouTrack is a proprietary, commercial browser-based bug tracker, issue tracking system and project management software developed by JetBrains. There is also a REST API provided which allows for various actions to be performed programmatically. In this article I will describe the cmdlets I have created to create issues for projects which leverage the Invoke-WebRequest cmdlet to interact with the REST API using Windows PowerShell.

The cmdlets require a minimum of Windows PowerShell 3.0 and uses the response object for HTML content without Document Object Model (DOM) parsing, this is required when Internet Explorer is not installed on the local instance invoking the cmdlets. An example of a use case for the cmdlets, is to be configured as an event handler from an infrastructure monitoring solution which will create issues for alarms raised.

The REST API is enabled by default and you can confirm connection and access permissions by browsing to ‘http://{baseURL}/rest/admin/project’ which should return an XML file with a list of all the projects. A more detailed description of the REST API can be found at

In this example, we are using cookie-based authorization. However this process can be adapted to also used Hub OAuth 2.0 authentication as well, which is described at

Firstly, we need to establish a connection to the REST API using specified credentials and store the web request session object using the session variable. This will allow for cookie information to be re-used for use in subsequent web requests. The specified parameters of login and password are required to be used in the POST method as below:

POST /rest/user/login?{login}&{password}

The cmdlet Connect-YouTrack establishes a connection by specifying the YouTrack Uri, Username and Password parameters and returns the web request session object, which in this example I am storing in the Connection variable.

$Connection = Connect-YouTrack -YouTrackUri http://server1 -Username administrator -Password P@55Word! 

Once a connection has been established and the web session object has been returned, we can now create an issue in a project and specify a summary and description. The cmdlet ‘New-YouTrackItem’ will invoke a PUT request to the REST API with the specified parameters of project, summary and description as below.

PUT /rest/issue?{project}&{summary}&{description}

Once the item has been created, the URI of the new issue is retrieved from the response header and using a regular expression pattern match we retrieve the item number so that we can use a subsequent web request to update the item with additional information as a variable, in this example ‘NewIssue’. The Connection variable returned when establishing a connection to the REST API is passed to the session variable for authentication.

$NewIssue = New-YouTrackItem -YouTrackUri http://server1 -Project YT -Summary "Summary API Rest Method" -Description "Description API Rest Method" -SessionState $Connection

Finally, we want to apply a command to the issue created to update items with specified paramaters, as below.

POST /rest/issue/{issue}/execute?{command}

The cmdlet ‘Update-YouTrackItem’ specifies a mandatory parameter named ‘ExecuteCommand’ to specify all the items you wish to update in the issue. In this example, I will be invoking a command to set the priority as ‘High’, the type as ‘ Service Desk’ and category as ‘Support’ to update the issue previously created from the stored ‘NewIssue’ variable.

Update-YouTrackItem -YouTrackUri http://server1 -Item $NewIssue -ExecuteCommand "priority High type Service Desk category Support" -SessionState $Connection

The cmdlets are available from the below:

Connect-YouTrack –
New-YouTrackItem –
Update-YouTrackItem –

Posting messages to Slack channel using Windows PowerShell

Download: Send-ToSlack

As previously commented I had been exploring the use of Slack and integration with other tools. One use case was to send messages to channels within Slack when certain steps in an automated workflow were triggered and to provide notification of the status upon completion.

Therefore, I created a Windows PowerShell function that would post a message to a specified slack channel using the Web API methods available, which according to Slack:

The Slack Web API allows you to build applications that interact with Slack in more complex ways than the integrations we provide out of the box.

Currently, my requirement is only to post messages and therefore the function only provides support for the chat.PostMessage method to posts a message to a public channel, private group, or IM channel.

In order to provide authentication to the API this can be achieved by a bearer token to identify a single user which uses  a generated full-access token, see ‘‘ for more details and to generate/retrieve your bearer token information.

If you plan to authenticate several users, it is recommended to use OAuth2 by registering your application. Currently, this method for authenticatin is not supported within the function.

The function uses the Invoke-WebRequest cmdlet to send a request to the URL ‘‘ and provide the arguments for generating the message that will be posted to the specified Slack channel. The protocol ‘https’ is specified as all methods must be called using this protocol.

The ‘chat.PostMessage’ method has mandatory requirements to specify the token, channel and text arguments. In addition, the function currently provides the ability to specify the ‘icon’ and ‘username’ arguments when posting a message.

# Generates POST message to be sent to the slack channel.
$PostMessage = @{token="$Token";channel="$Channel";text="$Text";username="$Bot";icon_url="$Icon"}

The response will contain a JSON object, which contains a top-level boolean property which indicates success of failure. In the event of an error posting the message to the slack channel conditional logic is used to determine if the response contains an error ‘”ok”:false’ and processing the string to terminate with an error and return the machine-readable error code.

# Sends HTTPS request to the Slack Web API service.
$WebRequest = Invoke-WebRequest -Uri $Uri -Body $PostMessage
# Conditional logic to generate custom error message if JSON object response contains a top-level error property.
If ($WebRequest.Content -like '*"ok":false*')
# Terminates with error if the response contains an error property, parses the error code and stops processing of the command.
Throw ($WebRequest.Content -split '"error":"')[1] -replace '"}',''
} # If
} # Try
# Terminates with error and stops processing of the command.
Throw ("Unable to send request to the web service with the following exception: " + $Error[0].Exception.Message )
} # Catch
} # Process

view raw
hosted with ❤ by GitHub

On successfully posting a message to a channel, you will receive a customised output to the console session to confirm. The success code is determined by the response containing the string ‘”ok”:true’.

Send-ToSlack -Channel "#apitest" -Text "This is a test message generated by the function Send-ToSlack" -Token "xoxp-17822671332-9811436111-15776151506-a5a9c3855"
Successfully sent the message to the slack channel #apitest.





In addition, to the above the function also provides the ability to encrypt your bearer token using an encryption key and retrieve the string using the ‘System.Management.Automation.PSCredential’ class.



Scripting Games – December 2015

So here is my submitted entry to the December 2015 Scripting Games Puzzle hosted at to which comments have been posted on the Wrap Up containing the official answer(s).

The challenges presented in this puzzle are described below and to which I detail my approach to solving each one.

Split $list into a collection of entries, as you typed them, and sort the results by length. As a bonus, see if you can sort the length without the number.

Firstly, I split the collection of entries and store the output as a variable. In order to sort the number by length the variable is retrieved and the objects are sorted by property length. For sorting the objects without the number, the retrieved variable replaces any numbers in the objects.

Turn each line into a custom object with a properties for Count and Item

For each object in the list of items an action is performed to create a custom object for a count and item property value. In order to retrieve property values, a regular expression is used to replace all numbers to retrieve the item property value and then to replace all alphabetic characters for the item property value.

Using your custom objects, what is the total number of all bird-related items?

Here I perform a keyword match which contains all the bird-related items agaisnt the custom object and the calculate the sum of the property value count to retrieve the total number.

What is the total count of all items?

As previously, I have used regular expression to remove all alphabetic characters from each item in the collection. I then join the returned values with the ‘+’ character and pass the string as the command parameter value for the Invoke-Expression cmdlet to perform the calculation.

$List = @"
1 Partridge in a pear tree
2 Turtle Doves
3 French Hens
4 Calling Birds
5 Golden Rings
6 Geese a laying
7 Swans a swimming
8 Maids a milking
9 Ladies dancing
10 Lords a leaping
11 Pipers piping
12 Drummers drumming
# Challenge 1 – Split $list into a collection of entries, as you typed them, and sort the results by length. As a bonus, see if you can sort the length without the number.
$Gifts = $List -Split "`n"
Write-Output "Challenge 1 – Sorting collection of entries by length.`n"
$Gifts | Sort-Object Property Length
Write-Output "`nChallenge 1 (Bonus) – Sorting collection of entries by length without the number.`n"
$Gifts -Replace "[0-9]" | Sort-Object Property Length
#Challenge 2 – Turn each line into a custom object with a properties for Count and Item.
$GiftObjects = ForEach ($Gift in $Gifts)
[PSCustomObject] @{
Count = $Gift -Replace '[a-zA-z]'
Item = $Gift -Replace '[0-9]'
} #PSCustomObject
} # ForEach
Write-Output "`nChallenge 2 – Create custom object for each line with count and item property."
# Challenge 3 – Using your custom objects, what is the total number of all bird-related items?
$Birds = "Partridge|Turtle Doves|French Hens|Calling Birds|Geese|Swans"
Write-Output ("`nChallenge 3 – The total number of bird related items: " + ($GiftObjects -match $Birds | Measure-Object Property Count Sum).Sum + "`n")
# Challenge 4 – What is the total count of all items?
Write-Output ("Challenge 4 – The total number of gift items received: " + (Invoke-Expression (($Gifts -Replace '[a-zA-Z]') -join "+")))

Creating concatenated certificate container files using Windows PowerShell

I was recently enabling SSL on a web application which required the certificate file to be provided as a concatenated certificate container file containing all SSL certificates in the chain.

The method to perform the above is relatively simple and just requires each certificate to the chain to be opened in a text editor and the content to be combined into a single file.

Whilst relatively simple, I decided to use Windows PowerShell and create an advanced function to achieve the above.

Firstly, we need to specify the certificate files to combine to a container file and the in correct order of the certificate path. For Example, if you were to open the SSL certificate and view the certification path the order of the certificate files you specify should be in ascending order. Also, optionally you require to specify the private key in some scenarios in this case this should be the first certificate file specified. By default, the container file is created in the location of the users profile in PEM format but you may specify an alternative location and/or file extension.

[Parameter(Mandatory=$true)][ValidateScript({Get-Item $_})][String[]] $Certificates,
[String] $Output = ([Environment]::GetEnvironmentVariable("UserProfile")) + "\container_file.pem"

Once we have a list of certificates to combine to a container file in the correct order to retrieve (Get-Content) the content of each certificate file and add the content (Add-Content) to the container file. When I reference the content of a certificate file we are retrieving the body of each file including the begin and end tags as below.

# Retrieves and adds the content of each certificate from the specified location to a concatenated certificate container file.
ForEach ($Certificate in $Certificates)
Get-Content $Certificate | Add-Content $Output
} # Try
Write-Host ("The creation of the concatenated certificate container file failed with the following exception message: " + $Error[0].Exception.Message) -ForegroundColor Red
} # Catch
} # Process

Once the content of each certificate file has been retrieved and the content has been added to the container file this will create a file in the location specified or by default in the location of the users profile folder in PEM format.

Below is an example of the invoking the function and the output generated with the verbose message stream enabled.

ConvertTo-CertificateContainer -Certificates "C:\Certificates\SSL.crt", "C:\Certificates\IntermediateCA.crt", "C:\Certificates\RootCA.crt" -Output C:\Certificates\chain.pem -Verbose


The advanced function is available from here.