C# Academy · Урок

Управление секретами

Безопасно храните секреты с помощью пользовательских секретов .NET при разработке и Azure Key Vault или переменных среды в рабочей среде.

Урок 4 из 412 шагов

«Управление секретами» — бесплатный урок C# Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.

Секреты — не конфигурация

Пароли, ключи API, строки подключения и ключи подписи JWT нельзя хранить в appsettings.json или фиксировать в системе контроля версий. .NET предоставляет несколько специализированных механизмов управления секретами.

Секреты пользователя (разработка)

Секреты пользователя хранят секреты разработки вне каталога проекта в локальном для компьютера файле. Они автоматически загружаются в среде Development и никогда не попадают в исходный код.

# 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

Явная загрузка секретов пользователя

Host.CreateApplicationBuilder автоматически загружает секреты пользователя в среде Development. Вы также можете загружать их явно для сценариев, не связанных с Development, или для тестовых проектов.

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();

Переменные среды для рабочей среды

В рабочей среде передавайте секреты как переменные среды — во время выполнения они считываются из ОС или оркестратора контейнеров и не сохраняются на диске в открытом виде рядом с кодом.

# 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 }

Интеграция с Azure Key Vault

Azure Key Vault — это управляемое хранилище секретов для рабочей среды. Официальный поставщик загружает секреты непосредственно в систему конфигурации, поэтому приложение считывает их как любое другое значение конфигурации.

// 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

В AWS используйте Amazon.Extensions.Configuration.SystemsManager или непосредственно Secrets Manager, чтобы передавать секреты в конвейер конфигурации .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 предоставляет динамические секреты, ротацию секретов и детализированный контроль доступа. Используйте библиотеку сообщества VaultSharp или поставщик конфигурации для интеграции с .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;

Защита секретов в памяти

Даже в памяти с секретами следует обращаться осторожно. Используйте SecureString или ограничивайте область действия с помощью блоков using, а также избегайте записи значений секретов в журнал.

// 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
}

Секреты в CI/CD

Конвейеры CI/CD (GitHub Actions, Azure DevOps, Jenkins) предоставляют хранилища переменных секретов. Передавайте секреты как переменные среды во время сборки или развертывания — никогда не прописывайте их напрямую в YAML конвейера.

# 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

Практический пример: стратегия секретов для разработки и рабочей среды

Полная стратегия работы с секретами: секреты пользователя при разработке, Azure Key Vault в рабочей среде и переменные среды как резервный вариант.

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();

Быстрая проверка

Почему секреты нельзя хранить в appsettings.json?

Итоги: управление секретами

Основные выводы:

  • Никогда не храните секреты в appsettings.json — этот файл добавляется в систему контроля версий
  • Разработка: используйте секреты пользователя (dotnet user-secrets) — они хранятся вне проекта
  • Рабочая среда: переменные среды, Azure Key Vault, AWS Secrets Manager или HashiCorp Vault
  • CI/CD: храните секреты в хранилище секретов конвейера и передавайте их как переменные среды
  • Никогда не записывайте исходные значения секретов в журнал; используйте подсказки или маски
  • Сочетайте стратегии: секреты пользователя при разработке + Key Vault в рабочей среде + переменные среды для переопределения
Можно начать бесплатно

Изучай C# с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
93
Уроки
346

Часто задаваемые вопросы

Урок «Управление секретами» бесплатный?

Да — полный текст урока «Управление секретами» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.

Чему я научусь в уроке «Управление секретами»?

Безопасно храните секреты с помощью пользовательских секретов .NET при разработке и Azure Key Vault или переменных среды в рабочей среде. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C# Academy?

Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Управление секретами»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C# Academy?

Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Источники и поставщики конфигурации
  2. Строго типизированные параметры с IOptions
  3. Проверка параметров и именованные параметры
  4. Управление секретами
← Назад к C# Academy