Creating secure service connections in Azure DevOps

Creating quick service connections to Azure from Azure DevOps can be easy. Creating secured, easy-to-manage, connections is harder.
The Easy Connections
If you’re a Project Administrator or Endpoint Administrator on a Team project, you can create a new Service Connection. For Azure Service Connections, you also need Owner rights to the respective subscription and the ability on Azure Active Directory to create new app registrations.
From a Team Project, you can go to Settings and Service Connections. From there, you can create a new service connection.
For more information, here’s the Microsoft docs.
Guidelines
Following the principle of least priviledge, the smaller the scope for a service principal the better. In other words, if you can scope it down to a resource group even better.
The Problem
Today, when creating multiple Azure DevOps service principals with limited access, they will all show up with unfriendly names in Azure Active Directory. For a Team Project with many Azure service connections, you might end up with several service principals with the same name - making it very difficult to segregate access for each one.
For example
I created two service connections with Azure DevOps. I scoped these to a facundo-rg resource group.
From the IAM blade in facundo-rg, there’s the service principals created for this team project.
Although there’s two service connections, they have the same names! The name is just a combination of the Team Project and the Subscription ID.
It’s impossible to see which service principal belongs to which Azure DevOps service connections.
The Solution - Do it yourself
Note: Inspiration taken from the Azure DevOps labs
Bash
subscriptionId=[Some subscription Id]
resourceGroupName1=facundo-rg
resourceGroupName2=facundo2-rg
az ad sp create-for-rbac -n "test-my-app3" --role contributor \
--scopes /subscriptions/$subscriptionId/resourceGroups/$resourceGroupName1 \
/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName2
Result will look like
{
"appId": "[some app id]",
"displayName": "test-my-app3",
"name": "http://test-my-app3",
"password": "[some password]",
"tenant": "[some tenant]"
}
Then from Azure DevOps, use the link to manually complete the service connection.
- Service Principal Client ID -
appId - Service Principal Key -
password - Tenant -
tenant - Subscription ID - your subscription id
- Subscription Name - the name of your subscription
Extra Credit
Use the Azure DevOps extension for the Azure CLI to also automate the creation of the service connection. See more here.
Note: Install the Azure DevOps CLI extension first.
teamProject="Service Principals Demo"
subscriptionId=$(az account show | jq -r '.id')
subscriptionName=$(az account show | jq -r '.name')
resourceGroupName1=facundo-rg
resourceGroupName2=facundo2-rg
name="test-my-app3"
response=$(az ad sp create-for-rbac -n $name --role contributor \
--scopes /subscriptions/$subscriptionId/resourceGroups/$resourceGroupName1 \
/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName2)
appId=$(echo $response | jq -r '.appId')
tenantId=$(echo $response | jq -r '.tenant')
export AZURE_DEVOPS_EXT_AZURE_RM_SERVICE_PRINCIPAL_KEY=$(echo $response | jq -r '.password')
az devops service-endpoint azurerm create --azure-rm-service-principal-id "$appId" \
--azure-rm-subscription-id "$subscriptionId" \
--azure-rm-subscription-name "$subscriptionName" \
--azure-rm-tenant-id "$tenantId" \
--name "$name" \
--project "$teamProject"
About the author
I used to be a .NET developer. Nowaways, I am a DevOps solutions architect with a focus on Azure and Kubernetes.
I also love productivity topics, especially when it comes to doing more with less of my time. I'm also a daddy, so time is a limited resource for me.
Comments
Join the discussionThat was really useful explanation with code, it was not there on internet anywhere, when MS documentation only contains half of it.
Great Work Gauna !!






