0Pricing
C# Academy · Lección

Gestión de secretos

Almacene secretos de forma segura mediante .NET User Secrets durante el desarrollo y Azure Key Vault o variables de entorno en producción.

Gestión de secretos es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.

Los secretos no son configuración

Las contraseñas, claves de API, cadenas de conexión y claves de firma JWT nunca deben almacenarse en appsettings.json ni confirmarse en el control de versiones. .NET proporciona varios mecanismos diseñados específicamente para administrar secretos.

User Secrets (desarrollo)

User Secrets almacena los secretos de desarrollo fuera del directorio del proyecto, en un archivo local de la máquina. Se cargan automáticamente en el entorno Development y nunca se incluyen con el código fuente.

# Initialize (adds UserSecretsId to .csproj):
dotnet user-secrets init

# Set secrets:
dotnet user-secrets set "Database:Password" "dev-pass-123"
dotnet user-secrets set "Jwt:SigningKey" "dev-jwt-key-abc"
dotnet user-secrets set "OpenAI:ApiKey" "sk-..."

# List / remove:
dotnet user-secrets list
dotnet user-secrets remove "OpenAI:ApiKey"

# Stored at:
# macOS/Linux: ~/.microsoft/usersecrets/{id}/secrets.json
# Windows:     %APPDATA%\Microsoft\UserSecrets\{id}\secrets.json

Carga explícita de User Secrets

Host.CreateApplicationBuilder carga automáticamente User Secrets en Development. También puede cargarlos explícitamente para escenarios que no sean de Development o para proyectos de prueba.

var builder = Host.CreateApplicationBuilder(args);

// Automatic (Development only) — already done by default
// Equivalent manual call:
if (builder.Environment.IsDevelopment())
    builder.Configuration.AddUserSecrets<Program>();

// In test projects (no ASPNETCORE_ENVIRONMENT):
var config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: true)
    .AddUserSecrets<Program>()   // loads secrets.json
    .AddEnvironmentVariables()
    .Build();

Variables de entorno para producción

En producción, inyecte los secretos como variables de entorno: el sistema operativo o el orquestador de contenedores las leen durante la ejecución y nunca se conservan en texto plano en el disco junto al código.

# docker-compose.yml — inject secrets:
services:
  api:
    image: myapp:latest
    environment:
      - Database__Password=${DB_PASSWORD}     # from .env file
      - Jwt__SigningKey=${JWT_KEY}
      - ConnectionStrings__Default=Server=db;Password=${DB_PASSWORD}

# Kubernetes Secret:
kubectl create secret generic app-secrets \
  --from-literal=Database__Password=secret123 \
  --from-literal=Jwt__SigningKey=verylongkey

# Reference in pod spec:
# env:
#   - name: Database__Password
#     valueFrom:
#       secretKeyRef: { name: app-secrets, key: Database__Password }

Integración con Azure Key Vault

Azure Key Vault es un almacén administrado de secretos para producción. El proveedor oficial carga los secretos directamente en el sistema de configuración; la aplicación los lee como cualquier otro valor de configuración.

// dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
// dotnet add package Azure.Identity

var builder = WebApplication.CreateBuilder(args);

if (!builder.Environment.IsDevelopment())
{
    var kvUri = new Uri(builder.Configuration["Azure:KeyVaultUri"]!);

    // Uses Managed Identity / workload identity in production:
    builder.Configuration.AddAzureKeyVault(kvUri, new DefaultAzureCredential());
}

// Secrets named "Database--Password" in Key Vault
// are accessible as builder.Configuration["Database:Password"]
// (Key Vault uses -- as the : separator)

AWS Secrets Manager

En AWS, use Amazon.Extensions.Configuration.SystemsManager o Secrets Manager directamente para inyectar secretos en la canalización de configuración de .NET.

// dotnet add package Amazon.Extensions.Configuration.SystemsManager

builder.Configuration.AddSystemsManager(
    path: "/myapp/production",     // parameter store prefix
    optional: false,
    reloadAfter: TimeSpan.FromMinutes(30));

// Or Secrets Manager directly:
using Amazon.SecretsManager;
using Amazon.SecretsManager.Model;

var client = new AmazonSecretsManagerClient();
var response = await client.GetSecretValueAsync(new GetSecretValueRequest
{
    SecretId = "myapp/production/db-password"
});
var secret = response.SecretString; // JSON string
// Parse and inject into config

HashiCorp Vault

HashiCorp Vault proporciona secretos dinámicos, rotación de secretos y control de acceso detallado. Use la biblioteca comunitaria VaultSharp o un proveedor de configuración para integrarlo con .NET.

// dotnet add package VaultSharp

using VaultSharp;
using VaultSharp.V1.AuthMethods.Token;

var authMethod = new TokenAuthMethodInfo("vault-token");
var vaultClient = new VaultClient(
    new VaultClientSettings("https://vault.example.com:8200", authMethod));

// Read a secret:
var kv = await vaultClient.V1.Secrets.KeyValue.V2
    .ReadSecretAsync(path: "myapp/database", mountPoint: "secret");

var password = kv.Data.Data["password"].ToString();

// Then store in configuration or pass to IOptions:
builder.Configuration["Database:Password"] = password;

Protección de secretos en memoria

Incluso en memoria, los secretos deben manejarse con cuidado. Use SecureString o limite su ámbito con bloques using, y evite registrar los valores de los secretos.

// NEVER log secrets:
_logger.LogInformation("API Key: {Key}", apiKey); // WRONG!
_logger.LogInformation("API Key configured: {HasKey}", !string.IsNullOrEmpty(apiKey)); // CORRECT

// Mask in diagnostics:
public string KeyHint => apiKey.Length > 8
    ? $"{apiKey[..4]}...{apiKey[^4..]}"
    : "****";

// Scope the secret:
void ProcessWithSecret()
{
    var secret = LoadSecret();
    try   { UseSecret(secret); }
    finally { secret = string.Empty; } // clear reference
}

Secretos en CI/CD

Las canalizaciones de CI/CD (GitHub Actions, Azure DevOps, Jenkins) proporcionan almacenes de variables secretas. Inyecte los secretos como variables de entorno durante la compilación o el despliegue; nunca los incluya directamente en el YAML de la canalización.

# GitHub Actions — store in Settings > Secrets:
# name: Deploy
# on: push
# jobs:
#   deploy:
#     runs-on: ubuntu-latest
#     env:
#       Database__Password: ${{ secrets.DB_PASSWORD }}
#       Jwt__SigningKey: ${{ secrets.JWT_KEY }}
#     steps:
#       - name: Run migration
#         run: dotnet ef database update

# Azure Pipelines:
# variables:
#   - group: my-app-secrets  # from Azure DevOps Variable Group

# The secrets are masked in logs and never stored in plaintext

Caso real: estrategia de secretos para desarrollo y producción

Una estrategia completa de secretos: User Secrets en desarrollo, Azure Key Vault en producción y variables de entorno como alternativa.

var builder = WebApplication.CreateBuilder(args);

if (builder.Environment.IsDevelopment())
{
    // Dev: local secrets.json, never committed
    builder.Configuration.AddUserSecrets<Program>();
}
else
{
    // Production: Azure Key Vault via Managed Identity
    var kvUri = builder.Configuration["Azure:KeyVaultUri"];
    if (!string.IsNullOrEmpty(kvUri))
        builder.Configuration.AddAzureKeyVault(
            new Uri(kvUri), new DefaultAzureCredential());
}

// Always load env vars (works in all environments + containers):
// Already loaded by CreateBuilder — they override Key Vault

// Bind secrets to strongly typed options:
builder.Services
    .AddOptions<JwtOptions>()
    .BindConfiguration("Jwt")
    .ValidateDataAnnotations()
    .ValidateOnStart();

Comprobación rápida

¿Por qué nunca deben almacenarse los secretos en appsettings.json?

Resumen: administración de secretos

Conclusiones clave:

  • Nunca almacene secretos en appsettings.json, ya que se confirma en el control de versiones
  • Desarrollo: use User Secrets (dotnet user-secrets), almacenado fuera del proyecto
  • Producción: variables de entorno, Azure Key Vault, AWS Secrets Manager o HashiCorp Vault
  • CI/CD: almacene los secretos en el almacén de secretos de la canalización e inyéctelos como variables de entorno
  • Nunca registre los valores sin ocultar de los secretos; use indicaciones o máscaras
  • Combine estrategias: User Secrets en desarrollo + Key Vault en producción + variables de entorno como anulación

Preguntas frecuentes

¿La lección «Gestión de secretos» es gratis?

Sí — el texto completo de «Gestión de secretos» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Gestión de secretos»?

Almacene secretos de forma segura mediante .NET User Secrets durante el desarrollo y Azure Key Vault o variables de entorno en producción. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C# Academy?

No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Gestión de secretos»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C# Academy?

Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Orígenes y proveedores de configuración
  2. Options con tipos seguros mediante IOptions
  3. Validación de Options y Options con nombre
  4. Gestión de secretos
← Volver a C# Academy