Azure Key Vault: Protege tus datos sensibles en la nube con .NET
Administra claves y secretos de forma segura en tu API .NET 9 usando Azure Key Vault. 🐿️🗝️

Hey devs, nos ponemos prácticos, en esta oportunidad te voy a enseñar todo lo que necesitas saber sobre Azure KeyVault y de cómo integrarlo en una aplicación de tipo Web API con .NET 9, pero podrías utilizarlo prácticamente en cualquier tipo de aplicación y versión posible, y bueno, empecemos!

¿Qué es Azure Key Vault?

Es un servicio de la nube de Azure diseñado para almacenar y acceder de manera segura a datos confidenciales o sensibles como por ejemplo:

  • Secrets (cadenas de conexión, API Keys, Tokens, contraseñas)
  • Claves de cifrado
  • Certificados SSL/TLS
  • Valores de configuración en general que son sensibles

Te doy más contexto

Estimado dev, cuando estás trabajando en desarrollo usualmente usas appsettings.json o alguna de sus variantes como appsettings.development.json para guardar datos de configuración y por comodidad o practicidad allí pones también la cadena de conexión a tu base de datos, algún usuario y contraseña o tal vez un API-Key para firmar tokens, entre otras cosas.

Si bien esto podría ser aceptable en la etapa de desarrollo local (aunque hay muchas empresas que no permiten esto ni en desarrollo) esto es inaceptable en producción, sin embargo es muy común que aún en producción se termine usando estos archivos de configuración para almacenar data crítica y sensible.

Esto deja una puerta abierta para atacantes o intrusos que en el momento en que tengan acceso al servidor podrían copiar o leer la información simplemente con leer el archivo y es entonces donde se da la filtración de datos. Esto es un problema creciente de ciberseguridad y como podrás notar, los ingenieros de software estamos inmersos también en este mundo, así que debemos mejorar nuestras estrategias utilizando programación segura y las mejores prácticas de seguridad disponibles hoy en día para minimizar el riesgo de una filtración de datos.

Sabiendo todo esto entonces no sorprende el porqué de tantas filtraciones de datos que hay últimamente. Pero nosotros somos mejores que eso así que vamos a aprender una manera más profesional y segura de manejar datos críticos en nuestras aplicaciones.

Ventajas de usar Azure Key Vault

  • Seguridad centralizada
  • Se puede configurar rotación automática de secretos
  • Tiene control de acceso basado en roles (RBAC o políticas)
  • Se le puede hacer auditoría con Azure Monitor y Log Analytics.

Usar Key Vault

Suponiendo que tienes una cuenta y suscripción activa de Azure, empecemos.

Te comento que voy a trabajar con los recursos de Azure mediante la línea de comandos de Azure ya que me parece mucho más fácil pero todo esto también lo podrías hacer desde el portal de Azure. Aunque también voy a incluir algunos pantallazos para que puedas ubicarte bien.

Instala la Azure CLI si es que aún no la tienes, desde aquí.

Abre una terminal y ejecuta:

az login para iniciar sesión o az login --use-device-code para iniciar sesión cuando no tienes interfaz gráfica como cuando accedes por terminal a tu servidor o cuando tienes MFA activado.

Luego de iniciar sesión puedes corroborar tu sesión actual con:

az account show

Muestra todos los grupos de recursos que tienes con el comando:

az group list --output table

Si no tienes alguno para utilizar crea uno, lo llamaremos azurekeyvaultRG:

az group create --name 'azurekeyvaultRG' --location eastus

Y crea el recurso de Key Vault, lo llamaremos bravedeveloperKV

az keyvault create --name bravedeveloperKV --resource-group azurekeyvaultRG --location eastus

Hasta ahora para poder ejecutar los comandos mencionados deberás tener el rol de Owner, Contributor o alguno similar, si por algún motivo no puedes crear un Key Vault revisa eso.

Ahora para crear secretos necesitas permisos especiales así que primero debes verificar si tu cuenta tiene permisos sobre el Key Vault.

Verificar permisos

Ejecuta az keyvault show --name bravedeveloperKV y copia el ID

Ejecuta az role assignment list --scope (id copiado) --output table

Tras ejecutar ese comando deberías tener alguno de estos roles: Key Vault Administrator, Key Vault Secrets officer, Key Vault secrets user u otro según tus necesidades y privilegios deseados.

Si tienes el rol genial, sino tendrás que Asignarte roles usando el modelo Azure RBAC.

Asignando roles mediante RBAC

Abre el portal de Azure > Key Vault > Settings > Access Configuration y verifica que en Permission Model tengas seleccionado Azure RBAC.

El siguiente paso es ir a Access control(IAM) > Add > Add Role Assignment

En Role selecciona alguno de los roles descritos en un paso anterior (por ejemplo Key Vault Administrator) y continúa.

Puedes repetir estos pasos para asignarte más de un rol.

Selecciona tu usuario y finaliza la operacion con Review+Assign

Ahora si, vuelves a verificar deberías tener el rol asignado y podrás trabajar con Key Vault.

Yo me asigné dos roles y ahora puedo verlos

Genial ahora entonces ya podemos continuar.

Creando secrets en Key Vault

A continuación crearemos 2 secrets:

az keyvault secret set --vault-name bravedeveloperKV --name API-Key --value "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"

az keyvault secret set --vault-name bravedeveloperKV --name 'ConnectionStrings--myDefaultConnection' --value "server=.;database=MyDatabaseY;trusted_connection=true;trust server certificate=true"

Para cambiar el valor del secret simplemente vuelve a crearlo, esto lo sobreescribirá.

Si eliminas un secret, Key vault hace soft-delete, esto quiere decir que mantiene un secret eliminado por 90 días así que si en este lapso de tiempo quieres volver a crear uno con ese mismo nombre, antes debes purgarlo con:

az keyvault secret purge --name API-Key --vault-name bravedeveloperKV

Y volver a crear el secret.

Cuando en el nombre del secret defines ConnectionStrings--myDefaultConnection quiere decir que se alojará jerárquicamente como si fuese ConnectionStrings:myDefaultConnection y en un json significaría que son nodos padre e hijo.

Puedes verificar esto en el portal:

Integrar Key Vault en nuestra API

Haremos este ejercicio en una aplicación de tipo Web API con .NET 9 pero podrías adaptarla a casi cualqueir aplicación con .net.

Instalar las bibliotecas:

  • azure.extensions.aspnetcore.configuration.secrets
  • azure.identity

Configura tu appsettings.development (o el appsettings del entorno en el que esté definido en ASPNETCORE_ENVIRONMENT):

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "ConnectionStrings": {
    "myDefaultConnection": "" //ahora ya no establecemos nada aquí
  },
  "KeyVault": {
    "Name": "bravedeveloperKV"
  }
}

Tu clase Program.cs luciría algo así:

using Azure.Identity;

var builder = WebApplication.CreateBuilder(args);

//LOGGING
var loggerFactory = LoggerFactory.Create(logging =>
{
    logging.AddConsole();
    logging.AddDebug();
});
var logger = loggerFactory.CreateLogger<Program>();

// Agregar Azure Key Vault a la configuración
var keyVaultName = builder.Configuration["KeyVault:Name"];
var keyVaultUri = new Uri($"https://{keyVaultName}.vault.azure.net/");
builder.Configuration.AddAzureKeyVault(keyVaultUri, new DefaultAzureCredential());

//CONFIRMAR SECRETS
logger.LogInformation("Cadena de conexion => " + builder.Configuration.GetConnectionString("myDefaultConnection"));
logger.LogInformation("Otra manera => " + builder.Configuration["ConnectionStrings:myDefaultConnection"]);
logger.LogInformation("API-Key => " + builder.Configuration["API-Key"]);

builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

He añadido logs que muestran el valor de los secrets alojados en Azure para confirmar que pueden ser usados desde aquí, y en efecto allí están! 🥳

Consideraciones adicionales

Según el ambiente en el que estés vas a usar o credenciales de usuario de Azure locales (en development) o Managed Identity cuando ya estés en producción.

Nota que puedes traer una cadena de conexión de dos maneras:

  • builder.Configuration.GetConnectionString("myDefaultConnection")
  • builder.Configuration["ConnectionStrings:myDefaultConnection"]

Sin importar como obtengas la cadena de conexión en el código, tendrás que especificarle el nodo padre e hijo en Key Vault cuando le pongas nombre al secret así: ConnectionStrings--myDefaultConnection y como ya sabes -- es equivalente a : y representa jerarquía.

Los proveedores de configuración en .NET pueden ser varios y como pueden haber varios definiendo lo mismo, éstos se sobreescriben siguiendo este orden de jerarquía, de menor a mayor jerarquía, siendo Azure Key Vault el que más importancia tiene:

Orden de carga de configuración

  1. appsettings.json
    Carga inicial de configuración base.
  2. appsettings.{Environment}.json
    Sobrescribe valores si el entorno coincide (por ejemplo: DevelopmentProduction).
  3. Secret Manager (solo en entorno de desarrollo)
    Valores almacenados en secrets.json (sólo aplica en desarrollo).
  4. Variables de entorno
    Variables del sistema operativo (por ejemplo: ASPNETCORE_ENVIRONMENT).
  5. Argumentos de línea de comandos
    Valores pasados al ejecutar la aplicación (ejemplo: dotnet run --urls=http://localhost:5000).
  6. Proveedores adicionales (Azure Key Vault)
    Al agregarse manualmente (ejemplo: AddAzureKeyVault()), tienen máxima prioridad y sobrescriben todo lo anterior.

Y pues eso ha sido todo, es lo que necesitas para hacer software de calidad en este apartado de almacenamiento de secrets en la nube 🐿️👌🏼

Si esta entrada te ha gustado un montón compártela! 🔥

Créditos de imagen de portada: Basada en Foto de Volodymyr Dobrovolskyy en Unsplash

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *