다음을 통해 공유


하나의 인증 자격 증명 집합을 사용하는 리소스에 대한 비밀 회전 자동화

Azure 서비스에 인증하는 가장 좋은 방법은 관리 ID를 사용하는 것이지만 옵션이 아닌 몇 가지 시나리오가 있습니다. 이러한 경우 액세스 키 또는 비밀이 사용됩니다. 액세스 키 또는 비밀을 주기적으로 회전해야 합니다.

이 자습서에서는 하나의 인증 자격 증명 집합을 사용하는 데이터베이스 및 서비스에 대한 비밀의 주기적 순환을 자동화하는 방법을 보여 줍니다. 다양한 자산 유형에서 자동 이동 개념 및 이점에 대한 포괄적인 개요는 Azure Key Vault의 자동 이동 이해를 참조하세요.

특히 이 자습서에서는 Azure Event Grid 알림에 의해 트리거되는 함수를 사용하여 Azure Key Vault에 저장된 SQL Server 암호를 회전합니다.

회전 솔루션 다이어그램

  1. 비밀 만료 30일 전에 Key Vault는 "만료 임박" 이벤트를 Event Grid에 게시합니다.
  2. Event Grid는 이벤트 구독을 확인하고 HTTP POST를 사용하여 이벤트를 구독하는 함수 앱 엔드포인트를 호출합니다.
  3. 함수 앱에서는 비밀 정보를 수신하고, 임의의 새 암호를 생성하고, Key Vault의 새 암호를 사용하여 새 버전의 비밀을 만듭니다.
  4. 함수 앱에서는 SQL Server를 새 암호로 업데이트합니다.

비고

3단계와 4단계 사이에 지연이 있을 수 있습니다. 이 기간 동안 Key Vault의 비밀은 SQL Server에 인증할 수 없습니다. 단계가 실패하는 경우 Event Grid는 2시간 동안 다시 시도합니다.

필수 조건

기존 Key Vault 및 SQL Server가 없는 경우 다음 배포 링크를 사용할 수 있습니다.

  1. 리소스 그룹에서 새로 만들기를 선택합니다. 그룹에 이름을 지정합니다. 이 자습서에서는 akvrotation 을 사용합니다.
  2. SQL 관리자 로그인 아래에 SQL 관리자 로그인 이름을 입력합니다.
  3. Review + create를 선택합니다.
  4. 만들기를 선택하세요

리소스 그룹 만들기

이제 Key Vault 및 SQL Server 인스턴스가 있습니다. 다음 명령을 실행하여 Azure CLI에서 이 설정을 확인할 수 있습니다.

az resource list -o table -g akvrotation

결과는 다음과 같은 출력으로 표시됩니다.

Name                     ResourceGroup         Location    Type                               Status
-----------------------  --------------------  ----------  ---------------------------------  --------
akvrotation-kv           akvrotation      eastus      Microsoft.KeyVault/vaults
akvrotation-sql          akvrotation      eastus      Microsoft.Sql/servers
akvrotation-sql/master   akvrotation      eastus      Microsoft.Sql/servers/databases
akvrotation-sql2         akvrotation      eastus      Microsoft.Sql/servers
akvrotation-sql2/master  akvrotation      eastus      Microsoft.Sql/servers/databases

SQL Server 암호 회전 함수 만들기 및 배포

중요합니다

이 템플릿을 사용하려면 키 자격 증명 모음, SQL Server 및 Azure Function이 동일한 리소스 그룹에 있어야 합니다.

다음으로, 다른 필수 구성 요소 외에도 시스템 관리 ID를 사용하여 함수 앱을 만들고 SQL Server 암호 회전 함수를 배포합니다.

함수 앱에는 다음 구성 요소가 필요합니다.

  • Azure App Service 계획
  • 이벤트 트리거 및 http 트리거가 있는 SQL 암호 회전 함수가 있는 함수 앱
  • 함수 앱 트리거 관리에 필요한 스토리지 계정
  • 함수 앱의 ID가 키 보관소의 비밀에 접근할 수 있는 접근 정책
  • SecretNearExpiry 이벤트에 대한 Event Grid 이벤트 구독
  1. Azure 템플릿 배포 링크를 선택합니다.

  2. 리소스 그룹 목록에서 akvrotation을 선택합니다.

  3. SQL Server 이름에 회전할 암호가 있는 SQL Server 이름을 입력합니다.

  4. Key Vault 이름에 키 자격 증명 모음 이름을 입력합니다.

  5. 함수 앱 이름에 함수 앱 이름을 입력합니다.

  6. 비밀 이름에 암호가 저장될 비밀 이름을 입력합니다.

  7. 리포지토리 URL에 함수 코드 GitHub 위치(https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp.git)를 입력합니다.

  8. Review + create를 선택합니다.

  9. 선택하고생성합니다.

검토 및 생성 선택

이전 단계를 완료하면 스토리지 계정, 서버 팜 및 함수 앱이 있습니다. 다음 명령을 실행하여 Azure CLI에서 이 설정을 확인할 수 있습니다.

az resource list -o table -g akvrotation

결과는 다음 출력과 같이 표시됩니다.

Name                     ResourceGroup         Location    Type                               Status
-----------------------  --------------------  ----------  ---------------------------------  --------
akvrotation-kv           akvrotation       eastus      Microsoft.KeyVault/vaults
akvrotation-sql          akvrotation       eastus      Microsoft.Sql/servers
akvrotation-sql/master   akvrotation       eastus      Microsoft.Sql/servers/databases
cfogyydrufs5wazfunctions akvrotation       eastus      Microsoft.Storage/storageAccounts
akvrotation-fnapp        akvrotation       eastus      Microsoft.Web/serverFarms
akvrotation-fnapp        akvrotation       eastus      Microsoft.Web/sites
akvrotation-fnapp        akvrotation       eastus      Microsoft.insights/components

함수 앱을 만들고 관리 ID를 사용하여 Key Vault에 액세스하는 방법에 대한 자세한 내용은 Azure Portal에서 함수 앱 만들기, App Service 및 Azure Functions에 관리 ID를 사용하는 방법, Azure Portal을 사용하여 Key Vault 액세스 정책 할당을 참조하세요.

회전 함수

이전 단계에서 배포된 함수는 이벤트를 사용하여 Key Vault와 SQL 데이터베이스를 업데이트함으로써 비밀 회전을 트리거합니다.

함수 트리거 이벤트

이 함수는 이벤트 데이터를 읽고 회전 논리를 실행합니다.

public static class SimpleRotationEventHandler
{
   [FunctionName("AKVSQLRotation")]
   public static void Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
   {
      log.LogInformation("C# Event trigger function processed a request.");
      var secretName = eventGridEvent.Subject;
      var secretVersion = Regex.Match(eventGridEvent.Data.ToString(), "Version\":\"([a-z0-9]*)").Groups[1].ToString();
      var keyVaultName = Regex.Match(eventGridEvent.Topic, ".vaults.(.*)").Groups[1].ToString();
      log.LogInformation($"Key Vault Name: {keyVaultName}");
      log.LogInformation($"Secret Name: {secretName}");
      log.LogInformation($"Secret Version: {secretVersion}");

      SecretRotator.RotateSecret(log, secretName, keyVaultName);
   }
}

비밀 회전 논리

이 회전 메서드는 비밀에서 데이터베이스 정보를 읽고, 새 버전의 비밀을 만들고, 데이터베이스를 새 비밀로 업데이트합니다.

    public class SecretRotator
    {
		private const string CredentialIdTag = "CredentialId";
		private const string ProviderAddressTag = "ProviderAddress";
		private const string ValidityPeriodDaysTag = "ValidityPeriodDays";

		public static void RotateSecret(ILogger log, string secretName, string keyVaultName)
        {
            //Retrieve Current Secret
            var kvUri = "https://" + keyVaultName + ".vault.azure.net";
            var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
            KeyVaultSecret secret = client.GetSecret(secretName);
            log.LogInformation("Secret Info Retrieved");

            //Retrieve Secret Info
            var credentialId = secret.Properties.Tags.ContainsKey(CredentialIdTag) ? secret.Properties.Tags[CredentialIdTag] : "";
            var providerAddress = secret.Properties.Tags.ContainsKey(ProviderAddressTag) ? secret.Properties.Tags[ProviderAddressTag] : "";
            var validityPeriodDays = secret.Properties.Tags.ContainsKey(ValidityPeriodDaysTag) ? secret.Properties.Tags[ValidityPeriodDaysTag] : "";
            log.LogInformation($"Provider Address: {providerAddress}");
            log.LogInformation($"Credential Id: {credentialId}");

            //Check Service Provider connection
            CheckServiceConnection(secret);
            log.LogInformation("Service  Connection Validated");
            
            //Create new password
            var randomPassword = CreateRandomPassword();
            log.LogInformation("New Password Generated");

            //Add secret version with new password to Key Vault
            CreateNewSecretVersion(client, secret, randomPassword);
            log.LogInformation("New Secret Version Generated");

            //Update Service Provider with new password
            UpdateServicePassword(secret, randomPassword);
            log.LogInformation("Password Changed");
            log.LogInformation($"Secret Rotated Successfully");
        }
}

GitHub에서 전체 코드를 찾을 수 있습니다.

Key Vault에 비밀 추가

사용자에게 비밀 관리 권한을 부여하도록 액세스 정책을 설정합니다.

az keyvault set-policy --upn <email-address-of-user> --name akvrotation-kv --secret-permissions set delete get list

SQL Server 리소스 ID, SQL Server 로그인 이름 및 비밀의 유효 기간이 포함된 태그가 있는 새 비밀을 만듭니다. SQL 데이터베이스의 비밀 초기 암호 이름(예: "Simple123")을 제공하고 내일로 설정된 만료 날짜를 포함합니다.

$tomorrowDate = (get-date).AddDays(+1).ToString("yyy-MM-ddThh:mm:ssZ")
az keyvault secret set --name sqlPassword --vault-name akvrotation-kv --value "Simple123" --tags "CredentialId=sqlAdmin" "ProviderAddress=<sql-database-resource-id>" "ValidityPeriodDays=90" --expires $tomorrowDate

만료 날짜가 짧은 비밀을 만들면 15분 내에 이벤트가 게시 SecretNearExpiry 되며, 그러면 함수가 비밀을 회전하도록 트리거됩니다.

테스트 및 확인

비밀이 회전했는지 확인하려면 Key Vault>비밀로 이동합니다.

Key Vault > 비밀에 액세스하는 방법을 보여 주는 스크린샷

sqlPassword 비밀을 열고 원래 버전과 회전된 버전을 봅니다.

비밀로 이동

웹앱 만들기

SQL 자격 증명을 확인하려면 웹앱을 만듭니다. 이 웹앱은 Key Vault에서 비밀을 얻고, 비밀에서 SQL 데이터베이스 정보 및 자격 증명을 추출하고, SQL Server에 대한 연결을 테스트합니다.

웹앱에는 다음 구성 요소가 필요합니다.

  • 시스템 관리 ID를 사용하는 웹앱
  • 웹앱 관리 ID를 통해 Key Vault의 비밀에 액세스하는 액세스 정책
  1. Azure 템플릿 배포 링크를 선택합니다.

  2. akvrotation 리소스 그룹을 선택합니다.

  3. SQL Server 이름에 회전할 암호가 있는 SQL Server 이름을 입력합니다.

  4. Key Vault 이름란에 키 자격 모음 이름을 입력합니다.

  5. 비밀 이름에 암호가 저장되는 비밀 이름을 입력합니다.

  6. 리포지토리 URL에 웹앱 코드 GitHub 위치(https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp-WebApp.git)를 입력합니다.

  7. Review + create를 선택합니다.

  8. 선택하고생성합니다.

웹앱 열기

배포된 애플리케이션 URL로 이동합니다.

https://akvrotation-app.azurewebsites.net/

애플리케이션이 브라우저에서 열리면 생성된 비밀 값 과 데이터베이스 연결된값이 true로 표시됩니다.

더 알아보세요