Azure DevOps: Update service connection expired secret

If you’re reading this post, you’re trying to find a way to edit an existing service connection with a new service principal secret/key.

It’s a weird that UI and devops cli don’t allow us to quickly change service connection details if it was created automatically by Azure DevOps (“creationMode”: “Automatic”; will talk about it a bit later).

So, how to change a secret? Answer: Azure DevOps REST API.
Note: if you have correct permissions, try out the steps at the bottom of the post. The steps below are for those who don’t have Owner permissions.

  • Create a new Personal Access Token (full access and all scope, expiration 1 day)
  • Go to Project Settings – Service Connections, choose your connection and click on Manage Service Principal. Add a new secret and note it’s value.
  • Choose a tool to work with REST API. It could be either PowerShell or Postman, for instance. I will show both.
  • [Postman] Install Postman and create a new HTTP Request
Postman – File – New – HTTP Request
  • [Postman] Go to Authorization and paste PAT token to the password field
PAT token should be used as password for any REST API requests
  • [Postman] Using the following GET request, get a service endpoint details in JSON format. Organization Name, Project Name and Endpoint Name are parts of the URI (can be taken from service connections list in the azure devops ui) :

    https://dev.azure.com/<orgName>/<ProjectName>/_apis/serviceendpoint/endpoints?endpointNames=<Endpoint Name> &api-version=6.0-preview.4
  • [Postman] Copy everything from the response under the value as shown below
{
            "data": {
                "subscriptionId": "",
                "subscriptionName": "",
                "environment": "AzureCloud",
                "scopeLevel": "Subscription",
                "creationMode": "Automatic",
                "azureSpnRoleAssignmentId": ""
            },
            ...............
                }
            ]
}
  • [Postman] Using a PUT request update the service connection. Make sure you set Body – Raw to JSON , and then Paste JSON copied in the previous step to the Body
Body – RAW should be set to JSON
  • Here is a tricky part. Prior to sending PUT request, change creationMode from “Automatic” to “Manual”. Also, in my case, I had to delete the following parameters spnObjectId and appObjectId (data section). Plus, I added serviceprincipalkey with a value set to a new secret (authorization section)
    A short excerpt is provided below:
{
    "data": {
        "subscriptionId": "",
        "subscriptionName": "",
        "environment": "AzureCloud",
        "scopeLevel": "Subscription",
        "creationMode": "Manual",  # changed
        "azureSpnRoleAssignmentId": "",
        "azureSpnPermissions": ""
         spnObjectId # deleted
         appObjectId # deleted
    },
    "description": "",
    "authorization": {
        "parameters": {
            "tenantid": "",
            "serviceprincipalid": "",
            "authenticationType": "spnKey",
            "serviceprincipalkey": "secret here" # added
        },
        "scheme": "ServicePrincipal"
}
}
  • [Postman] URI used for a PUT request: https://dev.azure.com/OrganizationName/_apis/serviceendpoint/endpoints/EndpointId?api-version=6.0-preview.4
  • [Postman] Go back to Azure DevOps and make sure that service connections has been updated and ready to use.

  • [PowerShell] Use the following example
$token ="PAT Token"
$orgName = "Organization Name"
$projectName = "Project Name"
$endpointName = "your endpoint"
$endpointId = "your endpoint ID, use GET request or UI"
$header = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($token)")) }

# Get Endpoint details

Invoke-RestMethod -Method GET -URI "https://dev.azure.com/$($orgName)/$($projectName)/_apis/serviceendpoint/endpoints?endpointNames=$($endpointName)&api-version=6.0-preview.4" -Headers $header -ContentType "application\json"

# Update Endpoint
$json = @{ json here } | ConvertTo-Json -Depth <your depth>
Invoke-RestMethod -Method PUT -URI "https://dev.azure.com/$($OrgName)/_apis/serviceendpoint/endpoints/$($endpointId)?api-version=6.0-preview.4" -Body -Headers $header -ContentType "application\json" -Body $json


That’s it. Now you know how to change a service connection with a new secret without removing a connection and customizing all pipelines in a project.

P.S. If you have Owners permissions on the app registration/service principal used by the connection, try to edit the connection by adding a description, and then click on Save. Azure DevOps should create a new secret and update the connection automatically.

%d bloggers like this: