Legacy on-premises method
If there ever was a case to move to the cloud, Microsoft just gave me another one with the introduction of managed identities. Remember the good ol' connection strings that needed to be created to connect an application to a database? They looked something like this:
Server=sql.example.com;Database=OrdersDB;User Id=webapp.svc;Password=SuperS3cuRE!;
They seem rather innocuous, but the implication of such connection strings are profound when it comes to security. Few questions come to mind. Where is this connection string stored on the app server, is it in memory? If the VM is rebooted or the service is restarted, where does the connection string get pulled from? Is it stored on disk? If so, is it stored in a secure location? For example, in a protected section of the web.config file. Did you encrypt the web.config section correctly 😏? Even better, maybe you had to push to a production environment ASAP, and shared the connection string with an operations team member over Teams/Slack. Do you see where I'm going with this line of thinking?
Passwords for service accounts are generally a poor way of securing services, in the modern era of cloud computing. They create a lot of unnecessary operational burden. You have to:
- Create and maintain the service accounts manually, which can be tedious and error-prone.
- Rotate the credentials periodically to comply with security policies and best practices, which can be complex and disruptive.
- Ensure that the credentials are stored and accessed securely, which can be challenging and costly.
- Monitor and audit the usage of the service accounts, which can be difficult and time-consuming.
Modern method in Azure
Fortunately, there is a better alternative: Azure managed identities. Managed identities are identities that are automatically managed by Azure. They eliminate the need for you to create and manage service accounts and their credentials. Instead, you can simply enable a managed identity for your Azure resource (such as a virtual machine, a web app, or a function app) and assign it the roles and permissions it needs to access other resources. Azure will take care of generating and rotating the credentials, storing them securely, and injecting them into your code when needed.
By hosting your application and database in Azure you can create a fully managed connection between your application and your database. To do this:
-
Enable managed identities for the type of service in Azure. Here are a few links:
-
Modify your database and add the identity as a principal to the database:
CREATE USER [managed-identity-name] FROM EXTERNAL PROVIDER
You can find the name of the managed identity by searching through the Enterprise Applications blade in Azure AD.
-
Grant the managed identity the necessary privileges within the database:
ALTER ROLE db_datareader ADD MEMBER [managed-identity-name]
-
Finally configure the simplified connection string for your web applications as follows:
Data Source=<servername>; Initial Catalog=OrdersDb; Authentication=Active Directory Managed Identity; Encrypt=True
Notice how there is no need to involve any sort of secret/key creation or management. This is a huge improvement over the status quo! By shifting the responsibility of managing the identity to Azure, we can realize the following benefits:
- Reduce the operational overhead and complexity of managing service accounts and their credentials, by shifting responsibility left, i.e. to the service provider, Entra ID and Azure.
- Improve the security of your applications using the using unified RBAC experiences in Azure to grant the managed identities and underlying service principals least privileged access to different components/sub-systems of your application.
- Simplify the development of your applications by using consistent and standardized authentication mechanisms across different Azure services. No more worries about checking in hard coded secrets to GitHub and or having to write code to pull it from environment variables or supplying it in a CI/CD pipeline. The managed identity just is!
Types of Managed Identities
One final comment is that Azure has two types of managed identities; user-assigned and system-assigned managed identities. The key difference between these two types lies in how they are created and associated with Azure resources:
-
User-Assigned Managed Identities:
- User-assigned managed identities are created and managed outside of the Azure resources they are assigned to.
- They are typically created as standalone Azure Active Directory (Azure AD) objects.
- You can assign a user-assigned managed identity to one or more Azure resources, such as virtual machines, Azure Functions, or Azure App Service instances.
- Once assigned, the user-assigned managed identity can be used by the associated resource(s) to authenticate and access other Azure services and resources.
-
System-Assigned Managed Identities:
- System-assigned managed identities are automatically created and associated with an Azure resource during its provisioning process.
- Each system-assigned managed identity is unique to the specific Azure resource it is assigned to and is bound to the lifecycle of that resource.
- System-assigned managed identities are closely tied to the lifecycle of the resource and are deleted when the resource is deleted.
- They are commonly used with resources like virtual machines, Azure App Service instances, and Azure Virtual Machine Scale Sets.
Simply put, user-assigned identities are created externally and can be assigned to multiple resources, while system-assigned identities are automatically created during resource provisioning (if enabled) and are specific to that particular resource.
Path forward
Over time I can only speculate that more services will be enabled for managed identities. This is a boon not only for developers, but also security and compliance teams. Some of the big ticket items I'm looking forward to, is managed identities for containers and Kubernetes, and also authenticated access to storage accounts via managed identities.