In today's blog we will look at a feature from Entra ID: Managed Identities. Throughout this blog we will learn what they are and why we should use them, how we can integrate them in our Azure DevOps environments and pipelines, how to secure them and some use cases examples.
Let's get started.
Table of Contents
The what and why?
Managed Identities are a type of authentication asset allowing you to authenticate non-human/programmatical workload without managing the credential aspect. They are like the cloud version of Active Directory Domain and Services (ADDS) Group Managed Service Account (gMSA) and are perfect for any type of automation scenarios.
You will find them in your Entra portal under Enterprise Applications and refining the list by selecting Managed Identities.
There are 2 types of managed identities:
System-assigned: a service account will be associated with the Azure workload - there is a relational of 1:1 ie an eligible workload such as a VM can only have a single System-managed Identity and this identity will only be associated with this workload. If the workload is removed (in our case if the VM is deleted) the managed identity will also be removed.
User-assigned: an independent service account will be associated or federated with the relevant workload. The relationship here is 1:many ie this identity will be associated with 0 to many workloads and a workload can be associated with 0 to many user-assigned managed identities. You will notice that I didn't mention Azure workload because one of their characteristics is that they can be federated or used with other platforms using federated credentials. This is a really powerful feature which will have for limit only your imagination and unlock all sort of automation across multiple environments and workloads.
Which type should I use?
My typical consultant answer:
Both types have their own places:
For most scenarios, a System-assigned managed identity should be enough. For example, in a n-tiers application hosted with Azure App Services, you could enable the system-assigned managed identity of your front end application to authenticate to your private API or using the managed service identity of your Azure Automation account to authenticate against the Graph API. System assigned managed identities are great in such scenarios ie authenticate a single and permanent platform against a workload.
For larger scope of automation, or in scenario where the resource is temporary and (re)provisioned multiple times you may be better using a User-assigned managed identity. This will enable you to reassign the identity to your workload without reconfiguring it. It also allow you to span across multiple environments or use a single identity to managed all your different workloads.
We will focus on User-assigned managed identity in the rest of this blog, because they will allow us to link our pipelines in Azure DevOps with our environment(s).
Configure Azure DevOps pipelines to use a managed identity
The first step is to create the User-assigned managed identity. In the Azure Portal, search for Managed Identities > Create > fill the information
Note: A System-assigned identity is enabled on the workload itself often in the identity section
In Azure DevOps (ADO), your pipelines connect to your different environments using a Service Connection. There are many types available but we will here focus on Azure Resource Manager. To create a service connection navigate to:
your ADO organisation > your project > project settings > Service connections > Azure Resource Manager
After pressing the next button use the following options select
Identity type: Managed identity
alternatively select app registration or managed identity (manual)) and choose Workload identity federation as credentials
Managed Identity details:
Select the location of your existing managed identity
Select the scope:
Subscription
Resource group using "use the resource group for Service connection (optional)"
Management Group
Machine Learning Workspace
Service connection details:
Service connection name: enter the name of your service connection.
Ensure to use a recognisable name including the targeted environment, workload and scope like:
<env name>-<env type>-<scope>-<app name>
with:
<env type>: test/dev/prod
< scope >: resource group(rg)/subscription(sub)/management group(mg)/machine learning workspace (ml)
ex: f365cAzure-test-sub-testApp
Pivoting back to the Azure portal, you will notice that a federated credentials have been added to your managed identity.
When you create your service connection with the option: app registration or managed identity (manual) you will need to create this federated credentials manually: the issuer and subject identifier will be available in the service connection creation pane
The only step left for the configuration is to assign the relevant permissions to your managed identities. These permissions can be typical Azure RBAC permissions on the scope level required. General rule of thumb here is LEAST privilege: don't assign permissions to your managed identities just in case of.... If you know this pipeline will only be used on a specific resource group only then contributor/owner will be sufficient on this resource group (subscription or management group level won't be required).
You can also assign Graph API permissions or other Microsoft 365 APIs such as Exchange Online or SharePoint PnP.
How to use them?
We are all setup now and ready to prepare our pipeline. There are many built-in pipeline tasks supporting service connection from which:
AzurePowerShell@5: run any command from the Az PowerShell module (5.1 or 7)
AzureResourceManagerTemplateDeployment@3: deploy an ARM or Bicep template to Azure
AzureFileCopy@6: copy files to a storage account.
InvokeRestAPI@1: this is a great option to query the Graph API using a Microsoft-hosted agent
For a full list visit: Review pipeline tasks - Azure Pipelines | Microsoft Learn
We can also use the PowerShell@2 task and use the managed identity with the different PowerShell SDKs using a self-hosted pipeline agent but this will be for part 2 of this blog.
Some security tips
Do not grant access to your service connection to all pipelines
Ensure to grant least privilege permissions to your managed identities
Ensure to scope the managed identity to the least level (resource, resource group, subscription, management group)
Use Entra ID group to assign permissions to your ADO environment and continuously monitor them using access reviews and consider integrating those groups with PIM.
Ensure a good hygiene of your Azure RBAC model
Ensure a proper naming and tagging strategy is in place for your Managed Identities and your Azure workloads in general
Monitor managed identity provisioning using Log Analytics and the Azure Activity logs
OperationNameValue = MICROSOFT.MANAGEDIDENTITY/USERASSIGNEDIDENTITIES/WRITE
Review permissions assigned to your managed identities using access review (Microsoft Entra Workload Identity add-on required)
Consider enforcing access controls with risk-based Conditional Access (Microsoft Entra Workload Identity add-on required)
Enable Defender CSPM on your subscription to monitor permissions creep for your workload identities
Convert your existing ARM service connections using secrets to OpenID federated identities. In the background, this process will create a federated credential in the app registration of your service connection/principal and will be authenticated the same way as managed identities identity removing the need of managing credentials
Conclusion
Using managed identities and workload federated identities will not only improve your authentication security but also remove the burden of renewing secrets and certificates. It reminds me the good old time of ADFS certificates renewal exercise 😁 #iykyk.
Stay tune for an upcoming blog where I will demonstrate how to use managed identities in your pipelines to authenticate against your Microsoft 365 workload and the Graph API
Thanks for reading!
References
About William Francillette:
I am a Microsoft Solutions Architect specialized in Microsoft 365, Entra and Azure security products at Threatscape.
I love learning, blogging and coding. My interests are very diverse and span across architecture, security, cloud engineering, automation, DevOps and PowerShell.
I own as of today 17x (and counting) Microsoft certifications and have worked in IT across multiple and diverse industries for over 15 years.