Database Patterns with Azure Kubernetes Service Part 2: Azure SQL DB and Managed Identity

In the previous Part 1 blog post, discussed an in-cluster containerized database.

Objective: An ASP .NET Core app hosted in Azure Kubernetes Service (AKS) that is accessing an Azure SQL Database using Azure AD Managed Identity.

The benefit is the ability for the application code not to use conventional SQL credentials of username and password stored in configuration files. Also, not use Azure Key vault to retrieve any user name and password credentials. There is nothing wrong with these techniques, but using Managed Identity is more streamlined and is a security best practice.

This blog article will show a comprehensive architecture, flow and interdependencies of my demo implementation. This demo is based on the articles, sample code and tutorials below in the References section.

The ASP .NET Core Web Application

  • Application is based on Build an ASP.NET Core and SQL Database app in Azure App Service
  • Simple To Do List application
  • Uses Entity Framework as a data access layer
  • .NET Core 3.1 SDK
  • Uses Microsoft.Azure.Services.AppAuthentication Nuget package to enable the application to authenticate to Azure AD supported Azure services.
  • Appsettings.json has ConnectionStrings as
    “MyDbConnection”:”Server=tcp:rkaks-sqlserver.database.windows.net,1433;Database=rkaksDB;”

Concepts and Key Components

Managed Identity allows Azure services to authenticate to any other Azure service that support Azure AD authentication. Managed Identity is a feature of Azure AD and is essentially a managed wrapper over an Azure AD service principal. As an example, a .NET core application running in Azure Kubernetes in an Azure VM or Azure App Service can be provided access to Azure SQL Database since it support Azure AD authentication.

I’m using system assigned identity of the AKS cluster named as ‘rkaks-demo’ as opposed to user assigned identity.

Azure AD Pod Identity enables Kubernetes applications to access cloud resources securely with Azure Active Directory (AAD) such as Azure SQL DB.

The Managed Identity Controller (MIC) is a Kubernetes custom resource that watches for changes to pods, AzureIdentity and AzureIdentityBindings through the Kubernetes API server.

The Node Management Identity (NMI) server is a pod that runs as a DaemonSet on each node and listens for pod requests to Azure services.
NMI server then requests an access token from Azure Active Directory (AAD) based on the pod’s identity mapping. This process can involve querying the Managed Identity Controller (MIC).

The MIC checks for Azure identity mappings that correspond to a pod.

This access token can be used by the pod (or the .Net Core application) to then request access to Azure SQL Database.

  1. The deployed .NET Core application and Azure resources.

Here is the baseline architecture. There is no authenticated access to Azure SQL yet. Note that the NMI and MIC has been deployed as custom Kubernetes resources to support Pod identity configuration.

2. Application code architecture and configuration

Update the ASP .NET Core app’s connection string, add the Microsoft.Azure.Services.AppAuthentication Nuget package and update Entity Framework code to be able to connect to the database

Note the database connection string does not need any set of credentials and as such provides the benefit of not storing and handling per dev, test, prod environment. This is they benefit. The management of access is left to the administrator of Azure AD and specific Azure resources (e.g. Azure SQL DB).

appsettings.json:

"ConnectionStrings": {
    "MyDbConnection": "Server=tcp:rkaks-sqlserver.database.windows.net,1433;Database=rkaksDB;",
}

Here is the code snippet in the DBContext.cs to enable the database connection for the application:

var conn = (Microsoft.Data.SqlClient.SqlConnection)Database.GetDbConnection();
conn.AccessToken = (new Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result;

Read further implementation details at Tutorial: Secure Azure SQL Database connection from App Service using a managed identitySetup the

3. Azure Pod Identity for the application’s pods.

Deploy the Kubernetes manifest YAML files to setup the AzureIdentity which references the Azure AD Managed Identity, the AzureIdentityBinding that “binds” between the application’s pods that and the AzureIdentity object. Update any existing deployment manifest of your application to create the label aadpodidbinding to be selected by the AzureIdentityBinding. The MIC will watch for these changes and implement the configuration.

Read further implementation details at AAD Pod Identity

  • Grant database level access to the Managed Identity.

In my design, I have granted access to the Managed Identity rkaks-demo via an Azure AD Group named azureDBprincipals. The alternative is to directly grant permission to the managed identity. The choice is a matter of preference and access security design.

Read for further details at Grant permissions to managed identity

4. Runtime execution of the application accessing and saving data against the Azure SQL database.

Here the user click’s ‘save’, the application’s pod requires an access token from Azure AD to establish a SQL connection. The NMI effectively retrieves the access token upon successful authentication from Azure AD. There is a lot more behind the scenes retrieve the access token and can be read more at Using Managed Service Identity (MSI) to authenticate on Azure SQL DB and at Best practices for authentication and authorization in Azure Kubernetes Service (AKS)

Finally, the pod can establish a SQL connection and access the Azure SQL database with the provided access token. The end user will see the data saved in their To Do list.

Conclusion

There are many interdependencies at build time, deployment time and run-time and so make sure to understand all the relationships and flows. With the ability of leveraging Azure AD authentication to manage access between applications and Azure services, we establish and design that does not need credentials stored in build and deployment time via configuration files. This reduces security risks and exposure.

References

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s