Aug 302019
 

For some reason it’s not straight-forward to create new credentials for an existing Service Principal account in Azure Active Directory using PowerShell.

I’m using PowerShell, because I’m not an Azure AD admin in my current organization, but as a developer, I am able to create and manage service principal accounts. This is extremely convenient, because we use them for automated deployments to Azure.

We started using Azure DevOps release management about a year ago, and thus I recently encountered the first credential expiration of a service principal that was used by Azure DevOps to deploy resources to Azure. This makes sense, because service principal credential lifetime defaults to one year.

A deployment which worked earlier today just failed with the error message

AADSTS7000222: The provided client secret keys are expired.

Checking the Service connection in Azure DevOps showed the same error:

Verify Connection failed because the client secret keys are expired

OK, so just create new credentials, and then update the Service Connection in Azure DevOps.

But that’s not as easy as I would like it to be.

Luckily, finding the Service Principal is easy. The Service Connection window in Azure DevOps (the screenshot above) contains the Service Principal’s “Application ID”. Now, it’s not called that in the screenshot, because the Application ID, Client ID, and many other names mean the same thing when talking about Azure AD.

But take the “Service principal client ID” from the above window, and run this PowerShell command:

Get-AzADServicePrincipal -ApplicationId <service principal client ID> | Get-AzADServicePrincipalCredential

That returns the details about the ServicePrincipals credentials:

StartDate           EndDate             KeyId                                Type
---------           -------             -----                                ----
29-08-2018 11:33:21 29-08-2019 11:33:21 64677c9e-2dae-4cbf-a031-1152814b3053 Password

Alright, so it expired a few days ago. Then let’s create a new one.

First get the Service Principal into a PowerShell object:

$sp = Get-AzADServicePrincipal -ApplicationId d33bc064-f562-4a7c-99db-643aca6a86c0

Then create new credentials:

$newcredential = New-AzADSpCredential -ServicePrincipalObject $sp

This creates a new password for the service principal, but you’ll never know the password, because it’s secret.

$newcredential

Just returns:

Secret    : System.Security.SecureString
StartDate : 30-08-2019 13:07:57
EndDate   : 30-08-2020 13:07:57
KeyId     : 34e1c9a4-519d-4930-b2fe-1b90ba450554
Type      : Password

And the above command to list the credentials shows that a new credential has been created:

StartDate           EndDate             KeyId                                Type
---------           -------             -----                                ----
30-08-2019 13:07:57 30-08-2020 13:07:57 34e1c9a4-519d-4930-b2fe-1b90ba450554 Password
29-08-2018 11:33:21 29-08-2019 11:33:21 64677c9e-2dae-4cbf-a031-1152814b3053 Password

So $newcredential contains the new password, but since it’s secret how do you get to it?

There’s a reason that the .NET SecureString type is unpopular with the security community. You can get to it with two lines of .NET code. And with PowerShell you can just write them at the prompt:

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($newcredential.Secret)
$UnsecureSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

At this point, $UnsecureSecret contains the clear-text password.

Paste the password into the Update Service Connection window in Azure DevOps, hit the Verify link, and then save it.

Now you have updated the Service Principal credentials that your Azure DevOps Service Connection uses.

In short:

  1. Get the Application ID from the “Update Service Connection” window’s “Service principal client ID” field.
  2. Run this in a PowerShell prompt where you have the Az module and you are signed in to Azure:
$sp = Get-AzADServicePrincipal -ApplicationId <your application ID>
$newcredential = New-AzADSpCredential -ServicePrincipalObject $sp
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($newcredential.Secret)
$UnsecureSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
  1. Output $UnsecureSecret and copy/paste it to the “Service Princpal Key” field in Azure DevOps

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)