Azure · Database · Segurança · Web App

Managed Identity – Acceder a SQL Database con App Service

Con Azure Managed Identity es posible eliminar la necesidad de que los desarrolladores gestionen contraseñas y credenciales, manteniendo la comunicación segura entre los servicios. Si aún no sabes qué es Azure Managed Identity, confere este artículo aquí

En el artículo de hoy, voy a mostrar un ejemplo práctico de cómo acceder a SQL database con App Service utilizando Managed Identity

Ejemplo práctico

Utilizando la imagen de arriba como ejemplo, suponiendo que ya posees un App Service y un Azure SQL Database, y quieres realizar la comunicación entre ellos a través del Managed Identity

Requisitos previos

  • Azure SQL Server debe estar configurado para aceptar autenticación con Microsoft Entra
    • No necesita ser solo Entra ID, puede ser en modo SQL y Entra
  • Asociar un Managed Identity en tu App Service
  • Conceder permisos en el SQL para el Managed Identity

Asociar un Managed Identity en el App Service

Puedes hacerlo tanto desde el Azure Portal como desde la línea de comandos

System Assigned

Para crear Managed Identity del tipo System Assigned basta ejecutar el siguiente comando

az webapp identity assign --name Meu-Web-App --resource-group Meu-Resource-Group

User Assigned

Para crear Managed Identity del tipo User Assigned, es necesario primero crear la Managed Identity

$managedIdentity = az identity create --resource-group Meu-Resource-Group --name Managed-Identity-Name

A continuación asociar con el App Service

az webapp identity assign --resource-group Meu-Resource-Group --name Meu-Web-App --identities ($managedIdentity | ConvertFrom-Json).id

Conceder permisos en el SQL

Para que esa comunicación se establezca, el App Services necesita tener acceso al Azure SQL Database a través de una Managed Identity, por lo que debes conectarte al servidor de SQL utilizando una cuenta de Entra con privilegios para crear usuarios (preferiblemente que sea admin) y ejecutar el siguiente comando en la Database a la que quieras conceder acceso vía Managed Identity

Conectar en SQL Management Studio

Abre SQL Management Studio, indica el servidor y elige la autenticación como Microsoft Entra MFA, ya que desde Julio/2024 Microsoft exige que los usuarios de Azure tengan MFA configurado, por lo que esta es la opción que debe utilizarse para permitir la autenticación

Tu navegador por defecto se abrirá, solicitando que te conectes a la cuenta y realices el proceso de autenticación utilizando MFA

Una vez conectado, ve a la database a la que quieres crear el usuario para el Managed Identity, haz clic derecho y New Query

Y luego ejecuta el siguiente comando, sustituyendo por el nombre de la Managed Identity que está asociada a tu App Service

Si la Managed Identity es del tipo System Assigned, el nombre siempre será el nombre del App Service

CREATE USER [<identity-name>] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [<identity-name>];
ALTER ROLE db_datawriter ADD MEMBER [<identity-name>];
ALTER ROLE db_ddladmin ADD MEMBER [<identity-name>];
GO
System Assigned
User Assigned

Es posible utilizar tanto SQL Server Management Studio como conectarte a través de la línea de comandos y, luego ejecutar el comando anterior

sqlcmd -S <server-name>.database.windows.net -d <db-name> -U <aad-user-name> -P "<aad-password>" -G -l 30

Y luego ejecutar la SQL Query para crear el usuario según tu Managed Identity

Configurando tu aplicación

Suponiendo que utilizas un App Service y un Azure SQL Database y, para comunicarse, defines una ConnectionString para que tu aplicación pueda conectarse a la base de datos.

Para este ejemplo, estamos utilizando la siguiente solución, que está disponible aquí

Utilizando Visual Studio, navega hasta el proyecto y abre el archivo DotNetAppSqlDb.sln

Requisitos previos

Agregar el paquete NuGet

Ve a Tools, NuGet Package Manager y haz clic en Package Manager Console

En la console escribe

Install-Package Azure.Identity

Y deberías ver una salida similar a la de la imagen de abajo, indicando que el paquete Azure.Identity fue añadido

Actualizar el Entity Framework

Luego, en la misma console escribe

Y deberías recibir una salida similar a esta imagen de abajo

Connection Strings

La forma en que creas tu ConnectionString puede cambiar según el lenguaje en el que esté escrita tu aplicación, así que usaremos aquí ASP.NET, donde tendrías la siguiente línea dentro de Web.config

...  
<connectionStrings>
    <add name="MyDbConnection" connectionString="Data Source=sql-server;Initial Catalog=app-database;User Id=sql-user;Password=sql-password;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;providerName=System.Data.SqlClient" />
  </connectionStrings>
...

Claramente, no es la forma más segura de utilizar, ya que cualquier persona con acceso al servidor verá información sensible en texto plano

Como se mencionó anteriormente, sería posible utilizar Key Vault, pero aún hay gestión de contraseñas y credenciales por realizar; de esta forma Managed Identity sería una alternativa, donde la ConnectionString cambiaría a

...
<connectionStrings>
  <add name="MyDbConnection" connectionString="Data Source=tcp:azure-sql-server.database.windows.net,1433;Initial Catalog=app-database;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" providerName="System.Data.SqlClient" /> />
</connectionStrings>
...

Autenticación vía Managed Identity

Y, claro, dentro de tu aplicación necesitaría determinar que la conexión de MyDbConnection se realizará mediante la solicitud de un token a Entra ID mediante el código abajo (Models\MyDatabaseContext.cs)

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Configuration;
using Azure.Identity;

namespace DotNetAppSqlDb.Models
{
    public class MyDatabaseContext : DbContext
    {
    
        public MyDatabaseContext() : base("name=MyDbConnection")
        {
            Azure.Identity.DefaultAzureCredential credential;
            var managedIdentityClientId = ConfigurationManager.AppSettings["ManagedIdentityClientId"];
            if (managedIdentityClientId != null)
            {
                //User-assigned managed identity Client ID is passed in via ManagedIdentityClientId
                var defaultCredentialOptions = new DefaultAzureCredentialOptions { ManagedIdentityClientId = managedIdentityClientId };
                credential = new Azure.Identity.DefaultAzureCredential(defaultCredentialOptions);
            }
            else
            {
                //System-assigned managed identity or logged-in identity of Visual Studio, Visual Studio Code, Azure CLI or Azure PowerShell
                credential = new Azure.Identity.DefaultAzureCredential();
            }
            var conn = (System.Data.SqlClient.SqlConnection)Database.Connection;
            var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[] { "https://database.windows.net/.default" }));
            conn.AccessToken = token.Token;
        }

        public System.Data.Entity.DbSet<DotNetAppSqlDb.Models.Todo> Todoes { get; set; }
    }
}

Quitar Connection Strings configuradas en el App Service

Los parámetros configurados a nivel de recurso App Service > Settings > Environment Variables tienen prioridad sobre los configurados dentro de tu aplicación, por ejemplo en Web.config

Por lo tanto, para garantizar que la conexión ocurra a través de la Managed Identity vamos a eliminar esa Connection Strings con el siguiente comando

az webapp config connection-string delete --resource-group Meu-Resource-Group --name Meu-Web-App --setting-names Minha-Connection-String

Y verificando el App Service nuevamente, ya no hay referencia: la Connection String se definió en Web.config y las configuraciones allí definidas junto con Models\MyDatabaseContext.cs permitirán la conexión vía Managed Identity

Publicar tu aplicación conectando con Managed Identity

Suponiendo que ya tienes el perfil de publish de tu aplicación para el Web App en Azure, ahora con los cambios realizados, vamos a publicar la aplicación a través de Visual Studio

Selecciona el proyecto en el Solution Explorer, luego ve a Build y haz clic en Publish DotNetAppSqlDb

Luego la parte de Publish con el profile aparecerá en Visual Studio, basta hacer clic en Publish

Si todo está OK con tu build, deberías ver el mensaje de que está ocurriendo warm up

El navegador por defecto abrirá una nueva pestaña, y voilá, verás tu aplicación funcionando (si todo está correcto)

Y puedes hacer clic en Create New, añadir una descripción y presionar Create para verificar si la conexión e interacción con la database están ocurriendo correctamente

¿Cómo verificar que la conexión se está realizando a través de Managed Identity?

Necesitas ir a Entra dentro del portal de Azure, en la sección Monitoring y en Sign-in logs, luego elegir Managed identity sign-ins

Como se puede observar en la tercera columna, Managed Identity, tiene el mismo ID que la Identity asociada al App Service y que tiene acceso a Azure SQL Database

AzureAzure App ServiceAzure SQLManaged Identity
Managed Identity – Acceder a SQL Database con App Service — Vinicius Deschamps