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 – https://github.com/dean1609/PowerShell/blob/master/Functions/New-EncryptionKey.ps1
New-EncryptedString – https://github.com/dean1609/PowerShell/blob/master/Functions/New-EncryptedString.ps1
Get-PSCredentialObject – https://github.com/dean1609/PowerShell/blob/master/Functions/Get-PSCredentialObject.ps1

Advertisements

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 https://confluence.jetbrains.com/display/YTD65/YouTrack+REST+API+Reference.

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 https://www.jetbrains.com/hub/help/1.0/OAuth-2.0-Authorization.html.

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 – https://github.com/dean1609/PowerShell/blob/master/Functions/Connect-YouTrack.ps1
New-YouTrackItem – https://github.com/dean1609/PowerShell/blob/master/Functions/New-YouTrackItem.ps1
Update-YouTrackItem – https://github.com/dean1609/PowerShell/blob/master/Functions/Update-YouTrackItem.ps1

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 ‘https://api.slack.com/web‘ 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 ‘https://slack.com/api/chat.postMessage‘ 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.

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.

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.

Slack_postMessage

 

 

 

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 PowerShell.org 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.

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.

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.

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-CertificateContainerResults

The advanced function is available from here.

 

 

 

 

 

 

 

 

 

 

Part Two – Computing email address hash value using Windows PowerShell

In part one I discussed computing the hash value using the MD5 hash algorithm for an email address, in this post I am going to discuss using other hash algorithms available in the HashAlgorithm Class to compute the value.

The available hash algorithms are MD5, RIPEMD160, SHA1, SHA256, SHA384 and SHA512 therefore in the advanced function we will set a parameter value which validates the input provided. By default, the hash algorithm of MD5 will be used unless specified.

The script block to compute the hash value does not differ from the example provided in the previous example which uses the StringBuilder Class .NET Framework object, other than we pass the hash algorithm parameter to the HashAlgorithm Class to compute the value.

Now be invoking the function and specifying a hash algorithm to compute the hash value I am able to use the default MD5 in the first instance and then each of the hash algorithms specified in the class.

Create-EmailHashPartTwoOutput

In the final part, I will look at using the  Blowfish-based hashing algorithm to compute the hash value and have an available advanced function and also provide the ability to specify not only an email address but a string value to compute the hash value.

Part One – Computing email address hash value using Windows PowerShell

I was recently discussing tracking email addresses and in particular protecting sensitive information and ensuring that the email address may not be re-used on deactivation. This got me thinking of how we could achieve this using Windows PowerShell.

As the advanced function required an email address I wanted to validate the  parameter specified for an email address so that is was valid. In the initial scenario I used a match based on regular expression as below. The regex pattern should match 99.9% of valid email addresses, but only allows for letters, digits and a couple of special characters. The official definition specified in RFC 5322 is far more complex

  (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*
  |  "(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]
      |  \\[\x01-\x09\x0b\x0c\x0e-\x7f])*")
@ (?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
  |  \[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
       (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:
          (?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]
          |  \\[\x01-\x09\x0b\x0c\x0e-\x7f])+)
     \])

However, I found that this generated what could be considered as an unfriendly error exception message, if the validation of the patten was returned as ‘false’.

 Cannot validate argument on parameter 'Email'. The "$_ -match "\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b"" validation script for the argument with value "someone@where" did not return a result of True

Therefore I decided to modify the script block for the parameter validation to throw an error if the validation of the pattern was returned as ‘false’,

This would now return the error exception message:

The email address someone@where is not a valid email address format.

So, lets now look at computing the hash value for the string provided as a valid email address. By default, Windows PowerShell only provides the Get-FileHash cmdlet to compute the hash value for a file by using a specified hash algorithm.

In the initial instance I used the MD5 hash algorithm by creating a StringBuilder Class .NET Framework object  and invoking the HashAlgorithm Class to compute the hash value.

This would return the following output when computing the hash algorithm:

CreateEmailHashMD5

Now we are all aware that MD5 contains weaknesses and we should not be using this as hashing algothrim for sensitive information so I will look at using alternative hashing algorithms and the Blowfish-based hashing algorithm (one good thing they were doing at Ashley Madison!) in additional posts covering this topic.