Azure Service Principals moonlighting as Service Connections
Azure DevOps is an interesting beast. It allows the automated delivery of applications, the tracking of work via Kanban boards, and with a little help from its friends, even time tracking (third party extension required). Sorry, the Beatles were swimming around my head as I write this.
One thing that has come up recently, is the method used by Azure DevOps to interact with other resources in Azure. This happens via a service connection and can control access to anything from Azure to GitHub and Jenkins if configured to do so. Here, I will be focusing on connections to Azure resources and walking through a problem that I encountered recently concerning the ability to deploy code using Azure DevOps.
The initial push of a change returned an error mentioning that the service principal was either not available or expired. When reviewing any and all information I was able to find, there was no distinct mention of a service principal to know just what item might be expiring.
Definition: A service principal is the Azure equivalent of a service account in the days of on premises Windows environments. It is intended to be used by applications or other services to authenticate - not used by humans.
In Azure, app registrations, the Azure CLI, and Azure PowerShell (among other tools) can create service principals. It turns out Azure DevOps can create them as well - with very little indication of where you might find them if you are looking in Azure Active Directory.
Azure DevOps uses an object called a service connection to access applications or services outside of itself. When publishing code to an Azure web service, the pipeline where the deployment work happens needs to be able to access the app service where the code exists. Since the service connection in Azure DevOps has created a service principal behind the scenes, and the service principal handles authentication - it is indeed likely that the secret (password) for the service principal will expire - which is what happened in this case.
Note: Service Connection managed service principals create two year passwords.
Like any other service principal or secret value with an expiration date configured for its password, the service connection must have the password reset. The rest of this entry will step through the process of resetting this password.
Creating Service Principals for Service Connections
To create a service connection (and its underlying service principal), complete the following steps:
- Login to Azure DevOps - (https://dev.azure.com)
- Select the Azure DevOps organization where the service connection will be created by clicking on the name of the organization in the navigation list (shown in figure A)
- Select the project that will be associated with the service connection (also shown in figure A)
- From the selected project dashboard, choose Project Settings at the very bottom left of the screen (shown in figure B)
- In the Project Settings screen, navigate down the list of options to Service Connections, figure C below.
On the Service connections screen, any existing service connections will be displayed. To create a new one, click the New service connection button at the top right of the screen
- To create a connection to an Azure App Service or other resource, choose Azure Resource Manager from the list of available service connection types and then click Next (shown in figure D)
- When configuring the New Azure Service connection, select Service principal (automatic) if a new service principal is needed.
To ensure that each project has its own service principal as well as to reduce the impact of changes to a service principal on other Azure DevOps resources, this is preferred. If you have an existing service principal you can select Service Principal (manual) and either create the service principal within Azure Active Directory or select an existing Service Principal.
Note: If your App Service or Azure resource has a Managed Identity, you may be tempted to choose this option - however this only works with custom build servers. If you are using the Microsoft Build Agent managed identity will not meet your needs.
- Once you have chosen to create a service principal, the scope for the service principal is needed. Choose the scope level, subscription is likely the best choice, especially if you are not sharing service connections - hint Don’t Share Service Connections it just makes things more complicated later.
- Select the Subscription and Resource Group that will be used with this service connection. The resource group that contains the resources that will be referenced by the service connection is preferred.
- Provide a name and description for the service connection - PLEASE USE DESCRIPTIVE NAMING and a description that explains what is going on. This will help others understand how the service connection is used. When all the pertinent information is provided, click Save to create the service connection. See figure F below
There you have it - the service connection is created and has a service principal for access to Azure. Upon creation, you will be whisked away to the overview screen for the service connection you have built. On this screen you can view the underlying service principal and refresh the service principal secret.
To do so, from the Service Connection overview screen for the connection you will be editing, click Manage Service Principal. This will send you to Azure and display the overview and details for the service principal. If you wish to see the expiration date of the service principal secret, you can do so by clicking Certificates and Secrets in the navigation menu for the service principal.
To update the secret for the service principal, simply click the Edit button from the Service Connection overview screen. If you make no changes and click save, the secret within the underlying service principal will be updated. The steps on the service connection overview are shown in figure G.