ASP.NET Core의 Azure Key Vault 구성 공급자

이 문서에서는 Azure Key Vault 구성 공급자를 사용하여 Azure Key Vault 비밀에서 앱 구성 값을 로드하는 방법을 설명합니다. Azure Key Vault는 앱 및 서비스에서 사용하는 암호화 키 및 비밀을 보호하는 데 유용한 클라우드 기반 서비스입니다. ASP.NET Core 앱에서 Azure Key Vault를 사용하는 일반적인 시나리오는 다음과 같습니다.

  • 중요한 구성 데이터에 대한 액세스 제어
  • 구성 데이터를 저장할 때 FIPS 140-2 수준 2 유효성이 검사된 HSM(하드웨어 보안 모듈)에 대한 요구 사항 충족

패키지

다음 패키지에 대한 패키지 참조를 추가합니다.

샘플 앱

샘플 앱은 맨 위에 Program.cs있는 전처리기 지시문에 의해 #define 결정되는 두 가지 모드 중 하나에서 실행됩니다.

  • Certificate: Azure Key Vault 클라이언트 ID 및 X.509 인증서를 사용하여 Azure Key Vault에 저장된 비밀에 액세스하는 방법을 보여 줍니다. 이 샘플은 Azure App Service에 배포되든, ASP.NET Core 앱을 제공할 수 있는 호스트에 배포되든, 어디에서든지 실행할 수 있습니다.
  • Managed: Azure 리소스에 대해 관리 ID를 사용하는 방법을 보여 줍니다. 관리형 ID는 앱의 코드 또는 구성에 자격 증명을 저장하지 않고 Azure AD(Active Directory) 인증으로 Azure Key Vault 앱을 인증합니다. 샘플의 Managed 버전을 Azure에 배포해야 합니다. Azure 리소스에 대해 관리 ID 사용 섹션의 지침을 따릅니다.

전처리기 지시문(#define)을 사용하여 샘플 앱을 구성하는 방법에 대한 자세한 내용은 ASP.NET Core의 개요를 참조하세요.

샘플 코드 보기 및 다운로드(다운로드 방법)

개발 환경의 비밀 스토리지

비밀 관리자를 사용하여 비밀을 로컬로 설정합니다. 샘플 앱이 개발 환경의 로컬 머신에서 실행되는 경우 비밀은 로컬 사용자 비밀 저장소에서 로드됩니다.

비밀 관리자에는 앱의 프로젝트 파일에 <UserSecretsId> 속성이 있어야 합니다. 속성 값({GUID})을 고유한 GUID로 설정합니다.

<PropertyGroup>
  <UserSecretsId>{GUID}</UserSecretsId>
</PropertyGroup>

비밀은 이름 값 쌍으로 생성됩니다. 계층 값(구성 섹션)은 ASP.NET Core 구성 키 이름에서 :(콜론)을 구분 기호로 사용합니다.

비밀 관리자는 프로젝트의 콘텐츠 루트로 열린 명령 셸에서 사용됩니다. 여기서 {SECRET NAME}은 이름이고 {SECRET VALUE}는 값입니다.

dotnet user-secrets set "{SECRET NAME}" "{SECRET VALUE}"

프로젝트의 콘텐츠 루트에서 명령 셸을 통해 다음 명령을 실행하여 샘플 앱에 대한 비밀을 설정합니다.

dotnet user-secrets set "SecretName" "secret_value_1_dev"
dotnet user-secrets set "Section:SecretName" "secret_value_2_dev"

이러한 비밀이 Azure Key Vault를 사용하는 프로덕션 환경의 비밀 스토리지 섹션의 Azure Key Vault에 저장되는 경우 _dev 접미사가 _prod로 변경됩니다. 이 접미사는 구성 값의 소스를 나타내기 위해 앱의 출력에 표시되는 시각적 표시를 제공합니다.

Azure Key Vault를 사용하는 프로덕션 환경의 비밀 스토리지

다음 단계를 완료하여 Azure Key Vault를 만들고 샘플 앱의 비밀을 저장합니다. 자세한 내용은 빠른 시작: Azure CLI를 사용하여 Azure Key Vault에서 비밀 설정 및 검색을 참조하세요.

  1. Azure Portal에서 다음 방법 중 하나를 사용하여 Azure Cloud Shell을 엽니다.

    • 코드 블록의 오른쪽 위 모서리에서 사용을 선택합니다. 텍스트 상자에 “Azure CLI” 검색 문자열을 사용합니다.
    • Cloud Shell 시작 단추를 사용하여 브라우저에서 Cloud Shell을 엽니다.
    • Azure Portal의 오른쪽 위 구석에 있는 메뉴에서 Cloud Shell 단추를 선택합니다.

    자세한 내용은 Azure CLIAzure Cloud Shell 개요를 참조하세요.

  2. 아직 인증받지 않은 경우 az login 명령을 사용하여 로그인합니다.

  3. 다음 명령을 사용하여 리소스 그룹을 만듭니다. 여기서 {RESOURCE GROUP NAME}은 새 리소스 그룹의 이름이 {LOCATION}은 Azure 지역입니다.

    az group create --name "{RESOURCE GROUP NAME}" --location {LOCATION}
    
  4. 다음 명령을 사용하여 리소스 그룹에 Key Vault를 만듭니다. 여기서 새 자격 증명 모음의 이름은 Azure {KEY VAULT NAME} 지역입니다 {LOCATION} .

    az keyvault create --name {KEY VAULT NAME} --resource-group "{RESOURCE GROUP NAME}" --location {LOCATION}
    
  5. 자격 증명 모음에서 이름-값 쌍으로 비밀을 만듭니다.

    Azure Key Vault 비밀 이름은 영숫자 문자와 대시로 제한됩니다. 키 자격 증명 모음 비밀 이름에는 콜론이 허용되지 않으므로 계층적 값(구성 섹션)은 구분 기호로 (두 대시)를 사용합니다 -- . 콜론은 ASP.NET Core 구성의 하위 키에서 섹션을 구분합니다. 비밀을 앱의 구성으로 로드할 때 대시 2개가 콜론으로 바뀝니다.

    다음 비밀은 샘플 앱에서 사용하기 위한 것입니다. 값은 비밀 관리자에서 개발 환경에 로드된 _dev 접미사 값과 구분하기 위해 _prod 접미사를 포함합니다. 이전 단계에서 만든 Key Vault의 이름으로 바꿉 {KEY VAULT NAME} 니다.

    az keyvault secret set --vault-name {KEY VAULT NAME} --name "SecretName" --value "secret_value_1_prod"
    az keyvault secret set --vault-name {KEY VAULT NAME} --name "Section--SecretName" --value "secret_value_2_prod"
    

Azure에서 호스트되지 않는 앱에 애플리케이션 ID 및 x.509 인증서 사용

앱이 Azure 외부에서 호스트될 때 Azure AD 애플리케이션 ID 및 X.509 인증서를 사용하여 자격 증명 모음에 인증하도록 Azure AD, Azure Key Vault 및 앱을 구성합니다. 자세한 내용은 키, 비밀 및 인증서 정보를 참조 하세요.

참고 항목

애플리케이션 ID 및 x.509 인증서를 사용하는 것은 Azure에서 호스트되는 앱에서는 지원되지만 권장되지 않습니다. 대신, Azure에서 앱을 호스트할 때 Azure 리소스에 대해 관리 ID를 사용합니다. 관리 ID는 앱 또는 개발 환경에서 인증서를 저장할 필요가 없습니다.

샘플 앱은 맨 위에 Program.cs 있는 전처리기 지시문이 <>#define/>로 설정된 경우 애플리케이션 ID 및 X.509 인증서를 Certificate사용합니다.

  1. PKCS#12 보관(.pfx) 인증서를 만듭니다. 인증서를 만들기 위한 옵션에는 Windows의 New-SelfSignedCertificateOpenSSL이 포함됩니다.
  2. 현재 사용자의 개인 인증서 저장소에 인증서를 설치합니다. 키를 내보낼 수 있는 것으로 표시하는 것은 선택 사항입니다. 이 프로세스의 뒷부분에서 사용되는 인증서의 지문을 적어 둡니다.
  3. PKCS#12 보관(.pfx) 인증서를 DER로 인코딩된 인증서(.cer)로 내보냅니다.
  4. Azure AD에 앱을 등록합니다(앱 등록).
  5. AZURE AD에 DER로 인코딩된 인증서(.cer)를 업로드합니다.
    1. Azure AD에서 앱을 선택합니다.
    2. 인증서 및 비밀로 이동합니다.
    3. 인증서 업로드를 선택하여 퍼블릭 키가 포함된 인증서를 업로드합니다. .cer, .pem또는 .crt 인증서를 사용할 수 있습니다.
  6. Key Vault 이름, 애플리케이션 ID 및 인증서 지문을 앱 appsettings.json 파일에 저장합니다.
  7. Azure Portal에서 Key Vault로 이동합니다.
  8. Azure Key Vault 섹션을 사용하여 프로덕션 환경의 Secret Storage에서 만든 Key Vault 를 선택합니다.
  9. 액세스 정책을 선택합니다.
  10. 액세스 정책 추가 선택.
  11. 비밀 권한을 열고 가져오기나열 권한을 사용하여 앱을 제공합니다.
  12. 보안 주체 선택을 선택하고 등록된 앱을 이름으로 선택합니다. 선택 단추를 누릅니다.
  13. 확인을 선택합니다.
  14. 저장을 선택합니다.
  15. 앱을 배포합니다.

Certificate 샘플 앱은 IConfigurationRoot에서 비밀 이름과 동일한 이름을 갖는 해당 구성 값을 가져옵니다.

  • 비계층적 값: SecretName 값은 config["SecretName"]를 사용하여 가져옵니다.
  • 계층적 값(섹션): :(콜론) 표기법 또는 GetSection 메서드를 사용합니다. 다음 방법 중 하나를 사용하여 구성 값을 가져옵니다.
    • config["Section:SecretName"]
    • config.GetSection("Section")["SecretName"]

X.509 인증서는 OS에서 관리됩니다. 앱은 appsettings.json 파일에서 제공하는 값을 사용하여 AddAzureKeyVault를 호출합니다.


using System.Security.Cryptography.X509Certificates;
using Azure.Identity;

var builder = WebApplication.CreateBuilder(args);

if (builder.Environment.IsProduction())
{
    using var x509Store = new X509Store(StoreLocation.CurrentUser);

    x509Store.Open(OpenFlags.ReadOnly);

    var x509Certificate = x509Store.Certificates
        .Find(
            X509FindType.FindByThumbprint,
            builder.Configuration["AzureADCertThumbprint"],
            validOnly: false)
        .OfType<X509Certificate2>()
        .Single();

    builder.Configuration.AddAzureKeyVault(
        new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
        new ClientCertificateCredential(
            builder.Configuration["AzureADDirectoryId"],
            builder.Configuration["AzureADApplicationId"],
            x509Certificate));
}

var app = builder.Build();

예제 값:

  • Key Vault 이름: contosovault
  • 애플리케이션 ID: 627e911e-43cc-61d4-992e-12db9c81b413
  • 인증서 지문: fe14593dd66b2406c5269d742d04b6e1ab03adb1

appsettings.json:

{
  "KeyVaultName": "Key Vault Name",
  "AzureADApplicationId": "Azure AD Application ID",
  "AzureADCertThumbprint": "Azure AD Certificate Thumbprint",
  "AzureADDirectoryId": "Azure AD Directory ID"
}

앱을 실행하면 웹 페이지에 로드된 비밀 값이 표시됩니다. 개발 환경에서 비밀 값은 _dev 접미사를 사용하여 로드됩니다. 프로덕션 환경에서 값은 _prod 접미사를 사용하여 로드됩니다.

Azure 리소스에 관리 ID 사용

Azure에 배포된 앱Azure 리소스에 대한 관리 ID를 활용할 수 있습니다. 관리형 ID를 사용하여 앱의 코드 또는 구성에서 자격 증명을 저장하지 않고 Azure AD 인증을 사용하여 앱에서 Azure Key Vault를 인증하는 방법을 보여 줍니다.

샘플 앱은 Program.cs 맨 위에 있는 #define 전처리기 지시문이 Managed로 설정된 경우 시스템이 할당한 관리형 ID를 사용합니다. Azure App Service 앱에 대한 관리형 ID를 만들려면 App Service 및 Azure Functions 관리형 ID를 사용하는 방법을 참조하세요. 관리형 ID가 만들어지면 App Service Identity 패널의 Azure Portal에 표시된 앱의 개체 ID를 확인합니다.

앱의 appsettings.json 파일에 자격 증명 모음 이름을 입력합니다. 샘플 앱에는 Managed 버전으로 설정된 경우 애플리케이션 ID 및 암호(클라이언트 비밀)가 필요하지 않으므로 이러한 구성 항목을 무시해도 됩니다. 앱이 Azure에 배포되고 Azure는 appsettings.json 파일에 저장된 자격 증명 모음 이름만 사용하여 Azure Key Vault에 액세스하도록 앱을 인증합니다.

샘플 앱을 Azure App Service에 배포합니다.

Azure CLI 및 앱의 개체 ID를 사용하여 자격 증명 모음에 액세스할 수 있는 권한과 get 권한을 list 앱에 제공합니다.

az keyvault set-policy --name {KEY VAULT NAME} --object-id {OBJECT ID} --secret-permissions get list

Azure CLI, PowerShell 또는 Azure Portal를 사용하여 앱을 다시 시작합니다.

샘플 앱은 DefaultAzureCredential 클래스의 인스턴스를 만듭니다. 자격 증명은 Azure 리소스에 대한 환경에서 액세스 토큰을 가져오려고 시도합니다.

using Azure.Identity;

var builder = WebApplication.CreateBuilder(args);

if (builder.Environment.IsProduction())
{
    builder.Configuration.AddAzureKeyVault(
        new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
        new DefaultAzureCredential());
}

Key Vault 이름 예제 값: contosovault

appsettings.json:

{
  "KeyVaultName": "Key Vault Name"
}

사용자 할당 관리형 ID를 사용하는 앱의 경우 다음 방법 중 하나를 사용하여 관리형 ID의 클라이언트 ID를 구성합니다.

  1. AZURE_CLIENT_ID 환경 변수를 설정합니다.

  2. AddAzureKeyVault를 호출할 때 DefaultAzureCredentialOptions.ManagedIdentityClientId 속성을 설정합니다.

    builder.Configuration.AddAzureKeyVault(
        new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
        new DefaultAzureCredential(new DefaultAzureCredentialOptions
        {
            ManagedIdentityClientId = builder.Configuration["AzureADManagedIdentityClientId"]
        }));
    

앱을 실행하면 웹 페이지에 로드된 비밀 값이 표시됩니다. 개발 환경에서 비밀 값은 비밀 관리자가 제공하므로 _dev 접미사를 포함합니다. 프로덕션 환경에서 이 값은 Azure Key Vault에서 제공되므로 _prod 접미사를 사용하여 로드됩니다.

오류가 발생하면 Access denied 앱이 Azure AD에 등록되어 있고 자격 증명 모음에 대한 액세스 권한이 제공되었는지 확인합니다. Azure에서 서비스를 다시 시작했는지 확인합니다.

관리 ID와 Azure Pipelines에서 공급자를 사용하는 방법에 대한 내용은 관리 서비스 ID를 사용하여 VM에 대한 Azure Resource Manager 서비스 연결 만들기를 참조하세요.

구성 옵션

AddAzureKeyVaultAzureKeyVaultConfigurationOptions 개체를 수락할 수 있습니다.

// using Azure.Extensions.AspNetCore.Configuration.Secrets;

builder.Configuration.AddAzureKeyVault(
    new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
    new DefaultAzureCredential(),
    new AzureKeyVaultConfigurationOptions
    {
        // ...
    });

AzureKeyVaultConfigurationOptions 개체에는 다음 속성이 있습니다.

속성 설명
Manager 비밀 로드를 제어하는 데 사용되는 KeyVaultSecretManager 인스턴스입니다.
ReloadInterval TimeSpan 변경 내용을 위해 자격 증명 모음을 폴링하는 시도 사이에 대기합니다. 기본값은 null입니다(구성이 다시 로드되지 않음).

키 이름 접두사 사용

AddAzureKeyVault 에서는 Key Vault 비밀을 구성 키로 변환하는 방법을 제어할 수 있는 구현 KeyVaultSecretManager을 허용하는 오버로드를 제공합니다. 예를 들어, 앱 시작 시 제공하는 접두사 값을 기준으로 비밀 값을 로드하도록 인터페이스를 구현할 수 있습니다. 예를 들어 이 기술을 사용하면 앱 버전에 따라 비밀을 로드할 수 있습니다.

Warning

Key Vault 비밀에 접두사를 사용하여 다음을 수행하지 마세요.

  • 여러 앱에 대한 비밀을 동일한 자격 증명 모음에 배치합니다.
  • 환경 비밀(예: ‘개발’ 및 ‘프로덕션’ 비밀)을 동일한 자격 증명 모음에 배치합니다.

다양한 앱 및 개발/프로덕션 환경에서는 별도의 Key Vault를 사용하여 최고 수준의 보안을 위해 앱 환경을 격리해야 합니다.

다음 예제에서는 Key Vault 비밀 이름에서 마침표가 허용되지 않는 경우 Key Vault에 비밀이 설정됩니다(개발 환경에 Secret 5000-AppSecret Manager 사용). 이 비밀은 앱 버전 5.0.0.0에 대한 앱 비밀을 나타냅니다. 앱의 다른 버전인 5.1.0.0의 경우 비밀이 자격 증명 모음에 추가되고 비밀 관리자 5100-AppSecret를 사용합니다. 각 앱 버전은 해당 버전의 비밀 값을 해당 구성에 AppSecret로 로드하고 비밀을 로드할 때 해당 버전을 제거합니다.

AddAzureKeyVault는 사용자 지정 KeyVaultSecretManager 구현을 통해 호출됩니다.

// using Azure.Extensions.AspNetCore.Configuration.Secrets;

builder.Configuration.AddAzureKeyVault(
    new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
    new DefaultAzureCredential(),
    new SamplePrefixKeyVaultSecretManager("5000"));

구현은 비밀의 버전 접두사에 반응하여 적절한 비밀을 구성에 로드합니다.

  • Load는 이름이 접두사로 시작하는 경우 비밀을 로드합니다. 다른 비밀은 로드되지 않습니다.
  • GetKey:
    • 비밀 이름에서 접두사를 제거합니다.
    • 이름에 있는 대시 2개는 구성에서 사용되는 구분 기호(일반적으로 콜론)인 KeyDelimiter로 바꿉니다. Azure Key Vault에서는 비밀 이름에 콜론을 허용하지 않습니다.
public class SamplePrefixKeyVaultSecretManager : KeyVaultSecretManager
{
    private readonly string _prefix;

    public SamplePrefixKeyVaultSecretManager(string prefix)
        => _prefix = $"{prefix}-";

    public override bool Load(SecretProperties properties)
        => properties.Name.StartsWith(_prefix);

    public override string GetKey(KeyVaultSecret secret)
        => secret.Name[_prefix.Length..].Replace("--", ConfigurationPath.KeyDelimiter);
}

Load 메서드는 버전 접두사가 있는 비밀을 찾기 위해 자격 증명 모음 비밀을 반복하는 공급자 알고리즘에 의해 호출됩니다. Load에 버전 접두사가 있으면 이 알고리즘은 GetKey 메서드를 사용하여 비밀 이름의 구성 이름을 반환합니다. 비밀 이름에서 버전 접두사를 제거합니다. 앱의 구성 이름 값 쌍에 로드하기 위해 나머지 비밀 이름이 반환됩니다.

이 방법을 구현하는 경우 다음이 적용됩니다.

  1. 앱의 프로젝트 파일에 앱 버전이 지정됩니다. 다음 예제에서 앱 버전은 5.0.0.0으로 설정됩니다.

    <PropertyGroup>
      <Version>5.0.0.0</Version>
    </PropertyGroup>
    
  2. 앱의 프로젝트 파일에 <UserSecretsId> 속성이 있는지 확인합니다. {GUID}는 사용자가 제공한 GUID입니다.

    <PropertyGroup>
      <UserSecretsId>{GUID}</UserSecretsId>
    </PropertyGroup>
    

    비밀 관리자를 사용하여 다음 비밀을 로컬로 저장합니다.

    dotnet user-secrets set "5000-AppSecret" "5.0.0.0_secret_value_dev"
    dotnet user-secrets set "5100-AppSecret" "5.1.0.0_secret_value_dev"
    
  3. 비밀은 다음 Azure CLI 명령을 사용하여 Azure Key Vault에 저장됩니다.

    az keyvault secret set --vault-name {KEY VAULT NAME} --name "5000-AppSecret" --value "5.0.0.0_secret_value_prod"
    az keyvault secret set --vault-name {KEY VAULT NAME} --name "5100-AppSecret" --value "5.1.0.0_secret_value_prod"
    
  4. 앱이 실행되면 Key Vault 비밀이 로드됩니다. 5000-AppSecret에 대한 문자열 비밀이 앱의 프로젝트 파일(5.0.0.0)에 지정된 앱 버전과 일치합니다.

  5. 버전 5000(대시 포함)이 키 이름에서 제거됩니다. 앱 전체에서 키 AppSecret를 사용하여 구성을 읽으면 비밀 값이 로드됩니다.

  6. 앱 버전이 프로젝트 파일에서 5.1.0.0으로 변경되고 앱이 다시 실행되는 경우 반환되는 비밀 값은 개발 환경에서는 5.1.0.0_secret_value_dev이고, 프로덕션 환경에서는 5.1.0.0_secret_value_prod입니다.

참고 항목

AddAzureKeyVault에 대해 사용자 고유의 SecretClient 구현을 만들 수도 있습니다. 사용자 지정 클라이언트는 앱 전체에서 클라이언트의 단일 인스턴스 공유를 허용합니다.

클래스에 배열 바인딩

공급자는 POCO 배열에 바인딩하기 위해 구성 값을 배열로 읽을 수 있습니다.

키에 콜론(:) 구분 기호를 포함할 수 있는 구성 소스에서 읽을 때 숫자 키 세그먼트가 배열(:0:, :1:, … :{n}:)을 구성하는 키를 구분하는 데 사용됩니다. 자세한 내용은 구성: 클래스에 배열 바인딩을 참조하세요.

Azure Key Vault는 콜론을 구분 기호로 사용할 수 없습니다. 이 문서에서 설명하는 접근 방식에서는 이중 대시(--)를 계층적 값(섹션) 구분 기호로 사용합니다. 배열 키는 이중 대시 및 숫자 키 세그먼트(--0--, --1--,… --{n}--)를 사용하여 Azure Key Vault에 저장됩니다.

JSON 파일에서 제공하는 다음과 같은 Serilog 로깅 공급자 구성을 검토합니다. 출력 로깅의 대상을 설명하는 두 개의 Serilog ‘싱크’를 반영하는 두 개의 개체 리터럴이 WriteTo 배열에 정의되어 있습니다.

"Serilog": {
  "WriteTo": [
    {
      "Name": "AzureTableStorage",
      "Args": {
        "storageTableName": "logs",
        "connectionString": "DefaultEnd...ountKey=Eby8...GMGw=="
      }
    },
    {
      "Name": "AzureDocumentDB",
      "Args": {
        "endpointUrl": "https://contoso.documents.azure.com:443",
        "authorizationKey": "Eby8...GMGw=="
      }
    }
  ]
}

위의 JSON 파일에 표시된 구성은 이중 대시(--) 표기법 및 숫자 세그먼트를 사용하여 Azure Key Vault에 저장됩니다.

Serilog--WriteTo--0--Name AzureTableStorage
Serilog--WriteTo--0--Args--storageTableName logs
Serilog--WriteTo--0--Args--connectionString DefaultEnd...ountKey=Eby8...GMGw==
Serilog--WriteTo--1--Name AzureDocumentDB
Serilog--WriteTo--1--Args--endpointUrl https://contoso.documents.azure.com:443
Serilog--WriteTo--1--Args--authorizationKey Eby8...GMGw==

비밀 다시 로드

기본적으로 비밀은 앱의 수명 동안 구성 공급자에 의해 캐시됩니다. 이후에 자격 증명 모음에서 사용하지 않도록 설정되거나 업데이트된 비밀은 앱에서 무시됩니다.

비밀을 다시 로드하려면 IConfigurationRoot.Reload를 호출합니다.

config.Reload();

비밀을 주기적으로 다시 로드하려면 지정된 간격으로 AzureKeyVaultConfigurationOptions.ReloadInterval 속성을 설정합니다. 자세한 내용은 구성 옵션을 참조하세요.

사용하지 않도록 설정한 비밀 및 만료된 비밀

만료된 비밀은 기본적으로 구성 공급자에 포함됩니다. 앱 구성에서 이러한 비밀에 대한 값을 제외하려면 만료된 비밀을 업데이트하거나 사용자 지정 구성 공급자를 사용하여 구성을 제공합니다.

class SampleKeyVaultSecretManager : KeyVaultSecretManager
{
  public override bool Load(SecretProperties properties) =>
    properties.ExpiresOn.HasValue &&
    properties.ExpiresOn.Value > DateTimeOffset.Now;
}

이 사용자 지정 KeyVaultSecretManagerAddAzureKeyVault에 전달합니다.

// using Azure.Extensions.AspNetCore.Configuration.Secrets;

builder.Configuration.AddAzureKeyVault(
    new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
    new DefaultAzureCredential(),
    new SampleKeyVaultSecretManager());

사용하지 않도록 설정된 비밀은 Key Vault에서 검색할 수 없으며 포함되지 않습니다.

문제 해결

앱이 공급자를 사용하여 구성을 로드하지 못하면 ASP.NET Core 로깅 인프라에 오류 메시지가 기록됩니다. 다음 조건에서는 구성이 로드되지 않습니다.

  • 앱 또는 인증서가 Azure AD에서 올바르게 구성되지 않았습니다.
  • 자격 증명 모음은 Azure Key Vault에 없습니다.
  • 앱은 자격 증명 모음에 액세스할 권한이 없습니다.
  • 액세스 정책에는 GetList 사용 권한이 포함되어 있지 않습니다.
  • 자격 증명 모음에서 구성 데이터(이름-값 쌍)의 이름이 잘못 지정되었거나 누락되었거나 비활성화되었습니다.
  • 앱에 잘못된 Key Vault 이름(KeyVaultName), Azure AD 애플리케이션 ID(AzureADApplicationId) 또는 Azure AD 인증서 지문(AzureADCertThumbprint) 또는 Azure AD 디렉터리 ID(AzureADDirectoryId)가 있습니다.
  • 앱에 대한 Key Vault 액세스 정책을 추가할 때 정책이 만들어졌지만 액세스 정책 UI에서 저장 단추가 선택되지 않았습니다.

추가 리소스

이 문서에서는 Azure Key Vault 구성 공급자를 사용하여 Azure Key Vault 비밀에서 앱 구성 값을 로드하는 방법을 설명합니다. Azure Key Vault는 앱 및 서비스에서 사용하는 암호화 키 및 비밀을 보호하는 데 유용한 클라우드 기반 서비스입니다. ASP.NET Core 앱에서 Azure Key Vault를 사용하는 일반적인 시나리오는 다음과 같습니다.

  • 중요한 구성 데이터에 대한 액세스 제어
  • 구성 데이터를 저장할 때 FIPS 140-2 수준 2 유효성이 검사된 HSM(하드웨어 보안 모듈)에 대한 요구 사항 충족

패키지

다음 패키지에 대한 패키지 참조를 추가합니다.

샘플 앱

샘플 앱은 맨 위에 Program.cs있는 전처리기 지시문에 의해 #define 결정되는 두 가지 모드 중 하나에서 실행됩니다.

  • Certificate: Azure Key Vault 클라이언트 ID 및 X.509 인증서를 사용하여 Azure Key Vault에 저장된 비밀에 액세스하는 방법을 보여 줍니다. 이 샘플은 Azure App Service에 배포되든, ASP.NET Core 앱을 제공할 수 있는 호스트에 배포되든, 어디에서든지 실행할 수 있습니다.
  • Managed: Azure 리소스에 대해 관리 ID를 사용하는 방법을 보여 줍니다. 관리 ID는 앱의 코드 또는 구성에 저장된 자격 증명 없이 Azure AD(Active Directory) 인증으로 Azure Key Vault 앱을 인증합니다. 관리 ID를 사용하여 인증하는 경우 Azure AD 애플리케이션 ID 및 암호(클라이언트 비밀)가 필요하지 않습니다. 샘플의 Managed 버전을 Azure에 배포해야 합니다. Azure 리소스에 대해 관리 ID 사용 섹션의 지침을 따릅니다.

전처리기 지시문(#define)을 사용하여 샘플 앱을 구성하는 방법에 대한 자세한 내용은 ASP.NET Core의 개요를 참조하세요.

샘플 코드 보기 및 다운로드(다운로드 방법)

개발 환경의 비밀 스토리지

비밀 관리자를 사용하여 비밀을 로컬로 설정합니다. 샘플 앱이 개발 환경의 로컬 머신에서 실행되는 경우 비밀은 로컬 사용자 비밀 저장소에서 로드됩니다.

비밀 관리자에는 앱의 프로젝트 파일에 <UserSecretsId> 속성이 있어야 합니다. 속성 값({GUID})을 고유한 GUID로 설정합니다.

<PropertyGroup>
  <UserSecretsId>{GUID}</UserSecretsId>
</PropertyGroup>

비밀은 이름 값 쌍으로 생성됩니다. 계층 값(구성 섹션)은 ASP.NET Core 구성 키 이름에서 :(콜론)을 구분 기호로 사용합니다.

비밀 관리자는 프로젝트의 콘텐츠 루트로 열린 명령 셸에서 사용됩니다. 여기서 {SECRET NAME}은 이름이고 {SECRET VALUE}는 값입니다.

dotnet user-secrets set "{SECRET NAME}" "{SECRET VALUE}"

프로젝트의 콘텐츠 루트에서 명령 셸을 통해 다음 명령을 실행하여 샘플 앱에 대한 비밀을 설정합니다.

dotnet user-secrets set "SecretName" "secret_value_1_dev"
dotnet user-secrets set "Section:SecretName" "secret_value_2_dev"

이러한 비밀이 Azure Key Vault를 사용하는 프로덕션 환경의 비밀 스토리지 섹션의 Azure Key Vault에 저장되는 경우 _dev 접미사가 _prod로 변경됩니다. 이 접미사는 구성 값의 소스를 나타내기 위해 앱의 출력에 표시되는 시각적 표시를 제공합니다.

Azure Key Vault를 사용하는 프로덕션 환경의 비밀 스토리지

다음 단계를 완료하여 Azure Key Vault를 만들고 샘플 앱의 비밀을 저장합니다. 자세한 내용은 빠른 시작: Azure CLI를 사용하여 Azure Key Vault에서 비밀 설정 및 검색을 참조하세요.

  1. Azure Portal에서 다음 방법 중 하나를 사용하여 Azure Cloud Shell을 엽니다.

    • 코드 블록의 오른쪽 위 모서리에서 사용을 선택합니다. 텍스트 상자에 “Azure CLI” 검색 문자열을 사용합니다.
    • Cloud Shell 시작 단추를 사용하여 브라우저에서 Cloud Shell을 엽니다.
    • Azure Portal의 오른쪽 위 구석에 있는 메뉴에서 Cloud Shell 단추를 선택합니다.

    자세한 내용은 Azure CLIAzure Cloud Shell 개요를 참조하세요.

  2. 아직 인증받지 않은 경우 az login 명령을 사용하여 로그인합니다.

  3. 다음 명령을 사용하여 리소스 그룹을 만듭니다. 여기서 {RESOURCE GROUP NAME}은 새 리소스 그룹의 이름이 {LOCATION}은 Azure 지역입니다.

    az group create --name "{RESOURCE GROUP NAME}" --location {LOCATION}
    
  4. 다음 명령을 사용하여 리소스 그룹에 Key Vault를 만듭니다. 여기서 새 자격 증명 모음의 이름은 Azure {KEY VAULT NAME} 지역입니다 {LOCATION} .

    az keyvault create --name {KEY VAULT NAME} --resource-group "{RESOURCE GROUP NAME}" --location {LOCATION}
    
  5. 자격 증명 모음에서 이름-값 쌍으로 비밀을 만듭니다.

    Azure Key Vault 비밀 이름은 영숫자 문자와 대시로 제한됩니다. 키 자격 증명 모음 비밀 이름에는 콜론이 허용되지 않으므로 계층적 값(구성 섹션)은 구분 기호로 (두 대시)를 사용합니다 -- . 콜론은 ASP.NET Core 구성의 하위 키에서 섹션을 구분합니다. 비밀을 앱의 구성으로 로드할 때 대시 2개가 콜론으로 바뀝니다.

    다음 비밀은 샘플 앱에서 사용하기 위한 것입니다. 값은 비밀 관리자에서 개발 환경에 로드된 _dev 접미사 값과 구분하기 위해 _prod 접미사를 포함합니다. 이전 단계에서 만든 Key Vault의 이름으로 바꿉 {KEY VAULT NAME} 니다.

    az keyvault secret set --vault-name {KEY VAULT NAME} --name "SecretName" --value "secret_value_1_prod"
    az keyvault secret set --vault-name {KEY VAULT NAME} --name "Section--SecretName" --value "secret_value_2_prod"
    

Azure에서 호스트되지 않는 앱에 애플리케이션 ID 및 x.509 인증서 사용

앱이 Azure 외부에서 호스트될 때 Azure AD 애플리케이션 ID 및 X.509 인증서를 사용하여 자격 증명 모음에 인증하도록 Azure AD, Azure Key Vault 및 앱을 구성합니다. 자세한 내용은 키, 비밀 및 인증서 정보를 참조 하세요.

참고 항목

애플리케이션 ID 및 x.509 인증서를 사용하는 것은 Azure에서 호스트되는 앱에서는 지원되지만 권장되지 않습니다. 대신, Azure에서 앱을 호스트할 때 Azure 리소스에 대해 관리 ID를 사용합니다. 관리 ID는 앱 또는 개발 환경에서 인증서를 저장할 필요가 없습니다.

샘플 앱은 맨 위에 Program.cs 있는 전처리기 지시문이 <>#define/>로 설정된 경우 애플리케이션 ID 및 X.509 인증서를 Certificate사용합니다.

  1. PKCS#12 보관(.pfx) 인증서를 만듭니다. 인증서를 만들기 위한 옵션에는 Windows의 New-SelfSignedCertificateOpenSSL이 포함됩니다.
  2. 현재 사용자의 개인 인증서 저장소에 인증서를 설치합니다. 키를 내보낼 수 있는 것으로 표시하는 것은 선택 사항입니다. 이 프로세스의 뒷부분에서 사용되는 인증서의 지문을 적어 둡니다.
  3. PKCS#12 보관(.pfx) 인증서를 DER로 인코딩된 인증서(.cer)로 내보냅니다.
  4. Azure AD에 앱을 등록합니다(앱 등록).
  5. AZURE AD에 DER로 인코딩된 인증서(.cer)를 업로드합니다.
    1. Azure AD에서 앱을 선택합니다.
    2. 인증서 및 비밀로 이동합니다.
    3. 인증서 업로드를 선택하여 퍼블릭 키가 포함된 인증서를 업로드합니다. .cer, .pem또는 .crt 인증서를 사용할 수 있습니다.
  6. Key Vault 이름, 애플리케이션 ID 및 인증서 지문을 앱 appsettings.json 파일에 저장합니다.
  7. Azure Portal에서 Key Vault로 이동합니다.
  8. Azure Key Vault 섹션을 사용하여 프로덕션 환경의 Secret Storage에서 만든 Key Vault 를 선택합니다.
  9. 액세스 정책을 선택합니다.
  10. 액세스 정책 추가 선택.
  11. 비밀 권한을 열고 가져오기나열 권한을 사용하여 앱을 제공합니다.
  12. 보안 주체 선택을 선택하고 등록된 앱을 이름으로 선택합니다. 선택 단추를 누릅니다.
  13. 확인을 선택합니다.
  14. 저장을 선택합니다.
  15. 앱을 배포합니다.

Certificate 샘플 앱은 IConfigurationRoot에서 비밀 이름과 동일한 이름을 갖는 해당 구성 값을 가져옵니다.

  • 비계층적 값: SecretName 값은 config["SecretName"]를 사용하여 가져옵니다.
  • 계층적 값(섹션): :(콜론) 표기법 또는 GetSection 메서드를 사용합니다. 다음 방법 중 하나를 사용하여 구성 값을 가져옵니다.
    • config["Section:SecretName"]
    • config.GetSection("Section")["SecretName"]

X.509 인증서는 OS에서 관리됩니다. 앱은 appsettings.json 파일에서 제공하는 값을 사용하여 AddAzureKeyVault를 호출합니다.

// using System.Linq;
// using System.Security.Cryptography.X509Certificates;
// using Azure.Extensions.AspNetCore.Configuration.Secrets;
// using Azure.Identity;

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            if (context.HostingEnvironment.IsProduction())
            {
                var builtConfig = config.Build();

                using var store = new X509Store(StoreLocation.CurrentUser);
                store.Open(OpenFlags.ReadOnly);
                var certs = store.Certificates.Find(
                    X509FindType.FindByThumbprint,
                    builtConfig["AzureADCertThumbprint"], false);

                config.AddAzureKeyVault(new Uri($"https://{builtConfig["KeyVaultName"]}.vault.azure.net/"),
                                        new ClientCertificateCredential(builtConfig["AzureADDirectoryId"], builtConfig["AzureADApplicationId"], certs.OfType<X509Certificate2>().Single()),
                                        new KeyVaultSecretManager());

                store.Close();
            }
        })
        .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());

예제 값:

  • Key Vault 이름: contosovault
  • 애플리케이션 ID: 627e911e-43cc-61d4-992e-12db9c81b413
  • 인증서 지문: fe14593dd66b2406c5269d742d04b6e1ab03adb1

appsettings.json:

{
  "KeyVaultName": "Key Vault Name",
  "AzureADApplicationId": "Azure AD Application ID",
  "AzureADCertThumbprint": "Azure AD Certificate Thumbprint",
  "AzureADDirectoryId": "Azure AD Directory ID"
}

앱을 실행하면 웹 페이지에 로드된 비밀 값이 표시됩니다. 개발 환경에서 비밀 값은 _dev 접미사를 사용하여 로드됩니다. 프로덕션 환경에서 값은 _prod 접미사를 사용하여 로드됩니다.

Azure 리소스에 관리 ID 사용

Azure에 배포된 앱Azure 리소스에 대한 관리 ID를 활용할 수 있습니다. 관리 ID를 사용하면 앱은 앱에 저장된 자격 증명(애플리케이션 ID 및 암호/클라이언트 비밀) 없이도 Azure AD 인증을 사용하여 Azure Key Vault에서 인증을 받을 수 있습니다.

샘플 앱은 맨 위에 있는 전처리기 지시문이 로 설정된 경우 #define Azure 리소스에 Program.cs 대한 관리 ID를 Managed사용합니다.

앱의 appsettings.json 파일에 자격 증명 모음 이름을 입력합니다. 샘플 앱에는 Managed 버전으로 설정된 경우 애플리케이션 ID 및 암호(클라이언트 비밀)가 필요하지 않으므로 이러한 구성 항목을 무시해도 됩니다. 앱이 Azure에 배포되고 Azure는 appsettings.json 파일에 저장된 자격 증명 모음 이름만 사용하여 Azure Key Vault에 액세스하도록 앱을 인증합니다.

샘플 앱을 Azure App Service에 배포합니다.

Azure App Service에 배포된 앱은 서비스를 만들 때 Azure AD에 자동으로 등록됩니다. 다음 명령에서 사용하기 위해 배포에서 개체 ID를 가져옵니다. 개체 ID는 Azure Portal에서 App Service의 Identity 패널에 표시됩니다.

Azure CLI 및 앱의 개체 ID를 사용하여 자격 증명 모음에 액세스할 수 있는 권한과 get 권한을 list 앱에 제공합니다.

az keyvault set-policy --name {KEY VAULT NAME} --object-id {OBJECT ID} --secret-permissions get list

Azure CLI, PowerShell 또는 Azure Portal를 사용하여 앱을 다시 시작합니다.

샘플 앱:

  • DefaultAzureCredential 클래스의 인스턴스를 만듭니다. 자격 증명은 Azure 리소스에 대한 환경에서 액세스 토큰을 가져오려고 시도합니다.
  • DefaultAzureCredential 인스턴스를 통해 새 SecretClient가 만들어집니다.
  • SecretClient 인스턴스는 비밀 값을 로드하고 키 이름에서 이중 대시(--)를 콜론(:)으로 바꾸는 KeyVaultSecretManager 인스턴스와 함께 사용됩니다.
// using Azure.Security.KeyVault.Secrets;
// using Azure.Identity;
// using Azure.Extensions.AspNetCore.Configuration.Secrets;

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            if (context.HostingEnvironment.IsProduction())
            {
                var builtConfig = config.Build();
                var secretClient = new SecretClient(
                    new Uri($"https://{builtConfig["KeyVaultName"]}.vault.azure.net/"),
                    new DefaultAzureCredential());
                config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
            }
        })
        .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());

Key Vault 이름 예제 값: contosovault

appsettings.json:

{
  "KeyVaultName": "Key Vault Name"
}

앱을 실행하면 웹 페이지에 로드된 비밀 값이 표시됩니다. 개발 환경에서 비밀 값은 비밀 관리자가 제공하므로 _dev 접미사를 포함합니다. 프로덕션 환경에서 이 값은 Azure Key Vault에서 제공되므로 _prod 접미사를 사용하여 로드됩니다.

오류가 발생하면 Access denied 앱이 Azure AD에 등록되어 있고 자격 증명 모음에 대한 액세스 권한이 제공되었는지 확인합니다. Azure에서 서비스를 다시 시작했는지 확인합니다.

관리 ID와 Azure Pipelines에서 공급자를 사용하는 방법에 대한 내용은 관리 서비스 ID를 사용하여 VM에 대한 Azure Resource Manager 서비스 연결 만들기를 참조하세요.

구성 옵션

AddAzureKeyVaultAzureKeyVaultConfigurationOptions 개체를 수락할 수 있습니다.

config.AddAzureKeyVault(
    new SecretClient(
        new Uri("Your Key Vault Endpoint"),
        new DefaultAzureCredential(),
        new AzureKeyVaultConfigurationOptions())
    {
        ...
    });

AzureKeyVaultConfigurationOptions 개체에는 다음 속성이 있습니다.

속성 설명
Manager 비밀 로드를 제어하는 데 사용되는 KeyVaultSecretManager 인스턴스입니다.
ReloadInterval TimeSpan 변경 내용을 위해 자격 증명 모음을 폴링하는 시도 사이에 대기합니다. 기본값은 null입니다(구성이 다시 로드되지 않음).

키 이름 접두사 사용

AddAzureKeyVault 에서는 Key Vault 비밀을 구성 키로 변환하는 방법을 제어할 수 있는 구현 KeyVaultSecretManager을 허용하는 오버로드를 제공합니다. 예를 들어, 앱 시작 시 제공하는 접두사 값을 기준으로 비밀 값을 로드하도록 인터페이스를 구현할 수 있습니다. 예를 들어 이 기술을 사용하면 앱 버전에 따라 비밀을 로드할 수 있습니다.

Warning

Key Vault 비밀에 접두사를 사용하여 다음을 수행하지 마세요.

  • 여러 앱에 대한 비밀을 동일한 자격 증명 모음에 배치합니다.
  • 환경 비밀(예: ‘개발’ 및 ‘프로덕션’ 비밀)을 동일한 자격 증명 모음에 배치합니다.

다양한 앱 및 개발/프로덕션 환경에서는 별도의 Key Vault를 사용하여 최고 수준의 보안을 위해 앱 환경을 격리해야 합니다.

다음 예제에서는 Key Vault 비밀 이름에서 마침표가 허용되지 않는 경우 Key Vault에 비밀이 설정됩니다(개발 환경에 Secret 5000-AppSecret Manager 사용). 이 비밀은 앱 버전 5.0.0.0에 대한 앱 비밀을 나타냅니다. 앱의 다른 버전인 5.1.0.0의 경우 비밀이 자격 증명 모음에 추가되고 비밀 관리자 5100-AppSecret를 사용합니다. 각 앱 버전은 해당 버전의 비밀 값을 해당 구성에 AppSecret로 로드하고 비밀을 로드할 때 해당 버전을 제거합니다.

AddAzureKeyVault는 사용자 지정 KeyVaultSecretManager 구현을 통해 호출됩니다.

config.AddAzureKeyVault(
    $"https://{builtConfig["KeyVaultName"]}.vault.azure.net/",
    builtConfig["AzureADApplicationId"],
    certs.OfType<X509Certificate2>().Single(),
    new PrefixKeyVaultSecretManager(versionPrefix));

구현은 비밀의 버전 접두사에 반응하여 적절한 비밀을 구성에 로드합니다.

  • Load는 이름이 접두사로 시작하는 경우 비밀을 로드합니다. 다른 비밀은 로드되지 않습니다.
  • GetKey:
    • 비밀 이름에서 접두사를 제거합니다.
    • 이름에 있는 대시 2개는 구성에서 사용되는 구분 기호(일반적으로 콜론)인 KeyDelimiter로 바꿉니다. Azure Key Vault에서는 비밀 이름에 콜론을 허용하지 않습니다.
public class PrefixKeyVaultSecretManager : KeyVaultSecretManager
{
    private readonly string _prefix;

    public PrefixKeyVaultSecretManager(string prefix)
    {
        _prefix = $"{prefix}-";
    }

    public override bool Load(SecretProperties secret)
    {
        return secret.Name.StartsWith(_prefix);
    }

    public override string GetKey(KeyVaultSecret secret)
    {
        return secret.Name
            .Substring(_prefix.Length)
            .Replace("--", ConfigurationPath.KeyDelimiter);
    }
}

Load 메서드는 버전 접두사가 있는 비밀을 찾기 위해 자격 증명 모음 비밀을 반복하는 공급자 알고리즘에 의해 호출됩니다. Load에 버전 접두사가 있으면 이 알고리즘은 GetKey 메서드를 사용하여 비밀 이름의 구성 이름을 반환합니다. 비밀 이름에서 버전 접두사를 제거합니다. 앱의 구성 이름 값 쌍에 로드하기 위해 나머지 비밀 이름이 반환됩니다.

이 방법을 구현하는 경우 다음이 적용됩니다.

  1. 앱의 프로젝트 파일에 앱 버전이 지정됩니다. 다음 예제에서 앱 버전은 5.0.0.0으로 설정됩니다.

    <PropertyGroup>
      <Version>5.0.0.0</Version>
    </PropertyGroup>
    
  2. 앱의 프로젝트 파일에 <UserSecretsId> 속성이 있는지 확인합니다. {GUID}는 사용자가 제공한 GUID입니다.

    <PropertyGroup>
      <UserSecretsId>{GUID}</UserSecretsId>
    </PropertyGroup>
    

    비밀 관리자를 사용하여 다음 비밀을 로컬로 저장합니다.

    dotnet user-secrets set "5000-AppSecret" "5.0.0.0_secret_value_dev"
    dotnet user-secrets set "5100-AppSecret" "5.1.0.0_secret_value_dev"
    
  3. 비밀은 다음 Azure CLI 명령을 사용하여 Azure Key Vault에 저장됩니다.

    az keyvault secret set --vault-name {KEY VAULT NAME} --name "5000-AppSecret" --value "5.0.0.0_secret_value_prod"
    az keyvault secret set --vault-name {KEY VAULT NAME} --name "5100-AppSecret" --value "5.1.0.0_secret_value_prod"
    
  4. 앱이 실행되면 Key Vault 비밀이 로드됩니다. 5000-AppSecret에 대한 문자열 비밀이 앱의 프로젝트 파일(5.0.0.0)에 지정된 앱 버전과 일치합니다.

  5. 버전 5000(대시 포함)이 키 이름에서 제거됩니다. 앱 전체에서 키 AppSecret를 사용하여 구성을 읽으면 비밀 값이 로드됩니다.

  6. 앱 버전이 프로젝트 파일에서 5.1.0.0으로 변경되고 앱이 다시 실행되는 경우 반환되는 비밀 값은 개발 환경에서는 5.1.0.0_secret_value_dev이고, 프로덕션 환경에서는 5.1.0.0_secret_value_prod입니다.

참고 항목

AddAzureKeyVault에 대해 사용자 고유의 SecretClient 구현을 만들 수도 있습니다. 사용자 지정 클라이언트는 앱 전체에서 클라이언트의 단일 인스턴스 공유를 허용합니다.

클래스에 배열 바인딩

공급자는 POCO 배열에 바인딩하기 위해 구성 값을 배열로 읽을 수 있습니다.

키에 콜론(:) 구분 기호를 포함할 수 있는 구성 소스에서 읽을 때 숫자 키 세그먼트가 배열(:0:, :1:, … :{n}:)을 구성하는 키를 구분하는 데 사용됩니다. 자세한 내용은 구성: 클래스에 배열 바인딩을 참조하세요.

Azure Key Vault는 콜론을 구분 기호로 사용할 수 없습니다. 이 문서에서 설명하는 접근 방식에서는 이중 대시(--)를 계층적 값(섹션) 구분 기호로 사용합니다. 배열 키는 이중 대시 및 숫자 키 세그먼트(--0--, --1--,… --{n}--)를 사용하여 Azure Key Vault에 저장됩니다.

JSON 파일에서 제공하는 다음과 같은 Serilog 로깅 공급자 구성을 검토합니다. 출력 로깅의 대상을 설명하는 두 개의 Serilog ‘싱크’를 반영하는 두 개의 개체 리터럴이 WriteTo 배열에 정의되어 있습니다.

"Serilog": {
  "WriteTo": [
    {
      "Name": "AzureTableStorage",
      "Args": {
        "storageTableName": "logs",
        "connectionString": "DefaultEnd...ountKey=Eby8...GMGw=="
      }
    },
    {
      "Name": "AzureDocumentDB",
      "Args": {
        "endpointUrl": "https://contoso.documents.azure.com:443",
        "authorizationKey": "Eby8...GMGw=="
      }
    }
  ]
}

위의 JSON 파일에 표시된 구성은 이중 대시(--) 표기법 및 숫자 세그먼트를 사용하여 Azure Key Vault에 저장됩니다.

Serilog--WriteTo--0--Name AzureTableStorage
Serilog--WriteTo--0--Args--storageTableName logs
Serilog--WriteTo--0--Args--connectionString DefaultEnd...ountKey=Eby8...GMGw==
Serilog--WriteTo--1--Name AzureDocumentDB
Serilog--WriteTo--1--Args--endpointUrl https://contoso.documents.azure.com:443
Serilog--WriteTo--1--Args--authorizationKey Eby8...GMGw==

비밀 다시 로드

비밀은 IConfigurationRoot.Reload가 호출될 때까지 캐시됩니다. 이후에 자격 증명 모음에서 사용하지 않도록 설정되거나 업데이트된 비밀은 실행될 때까지 Reload 앱에서 적용되지 않습니다.

Configuration.Reload();

사용하지 않도록 설정한 비밀 및 만료된 비밀

만료된 비밀은 기본적으로 구성 공급자에 포함됩니다. 앱 구성에서 이러한 비밀에 대한 값을 제외하려면 만료된 비밀을 업데이트하거나 사용자 지정 구성 공급자를 사용하여 구성을 제공합니다.

class SampleKeyVaultSecretManager : KeyVaultSecretManager
{
  public override bool Load(SecretProperties properties) =>
    properties.ExpiresOn.HasValue &&
    properties.ExpiresOn.Value > DateTimeOffset.Now;
}

이 사용자 지정 KeyVaultSecretManagerAddAzureKeyVault에 전달합니다.

// using Azure.Extensions.AspNetCore.Configuration.Secrets;

config.AddAzureKeyVault(
    new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
    new DefaultAzureCredential(),
    new SampleKeyVaultSecretManager());

사용하지 않도록 설정된 비밀은 Key Vault에서 검색할 수 없으며 포함되지 않습니다.

문제 해결

앱이 공급자를 사용하여 구성을 로드하지 못하면 ASP.NET Core 로깅 인프라에 오류 메시지가 기록됩니다. 다음 조건에서는 구성이 로드되지 않습니다.

  • 앱 또는 인증서가 Azure AD에서 올바르게 구성되지 않았습니다.
  • 자격 증명 모음은 Azure Key Vault에 없습니다.
  • 앱은 자격 증명 모음에 액세스할 권한이 없습니다.
  • 액세스 정책에는 GetList 사용 권한이 포함되어 있지 않습니다.
  • 자격 증명 모음에서 구성 데이터(이름-값 쌍)의 이름이 잘못 지정되었거나 누락되었거나 비활성화되었습니다.
  • 앱에 잘못된 Key Vault 이름(KeyVaultName), Azure AD 애플리케이션 ID(AzureADApplicationId) 또는 Azure AD 인증서 지문(AzureADCertThumbprint) 또는 Azure AD 디렉터리 ID(AzureADDirectoryId)가 있습니다.
  • 앱에 대한 Key Vault 액세스 정책을 추가할 때 정책이 만들어졌지만 액세스 정책 UI에서 저장 단추가 선택되지 않았습니다.

추가 리소스