다음을 통해 공유


Azure App Service 및 Azure Functions에서 앱 설정으로 Key Vault 참조 사용

이 문서에서는 Azure Key Vault의 비밀을 Azure App Service 또는 Azure Functions 앱의 앱 설정 또는 연결 문자열 값으로 사용하는 방법을 보여 줍니다.

Key Vault 는 액세스 정책 및 감사 기록을 완전히 제어할 수 있는 중앙 집중식 비밀 관리를 제공하는 서비스입니다. 앱 설정 또는 연결 문자열이 Key Vault 참조인 경우 애플리케이션 코드는 다른 앱 설정 또는 연결 문자열처럼 사용할 수 있습니다. 이렇게 하면 앱의 구성과 별도로 비밀을 유지할 수 있습니다. 앱 설정은 저장 시 안전하게 암호화되지만, 비밀을 관리할 기능이 필요한 경우, 키 보관소에 넣어야 합니다.

키 자격 증명 모음에 앱 액세스 권한 부여

키 보관소에서 비밀을 읽으려면 먼저 보관소를 만들고 앱에 접근 권한을 부여해야 합니다.

  1. Key Vault 빠른 시작에 따라 키 볼트를 만듭니다.

  2. 애플리케이션에 대한 관리 ID를 만듭니다.

    키 자격 증명 모음 참조는 기본적으로 앱의 시스템 할당 ID를 사용하지만 사용자가 할당한 ID를 지정할 수 있습니다.

  3. 만든 관리 ID에 대해 키 자격 증명 모음의 비밀에 대한 읽기 권한을 권한 부여합니다. 이 작업을 수행하는 방법은 키 자격 증명 모음의 권한 모델에 따라 달라집니다.

네트워크 제한 자격 증명 모음 액세스

금고가 네트워크 제한으로 구성된 경우, 애플리케이션에 네트워크 액세스 권한이 있는지 확인하세요. 원본 비밀 요청의 IP 주소가 다를 수 있으므로 볼트는 앱의 공용 아웃바운드 IP 주소에 의존하지 않는 것이 좋습니다. 대신 앱에서 사용하는 가상 네트워크의 트래픽을 허용하도록 보관소를 구성해야 합니다.

  1. App Service 네트워킹 기능Azure Functions 네트워킹 옵션에 설명된 대로 애플리케이션에 구성된 아웃바운드 네트워킹 기능이 있는지 확인합니다.

    현재 프라이빗 엔드포인트에 연결하는 Linux 애플리케이션은 가상 네트워크를 통해 모든 트래픽을 라우팅하도록 명시적으로 구성해야 합니다. 이 설정을 구성하려면 다음 명령을 실행합니다.

    az webapp config set --resource-group <group-name>  --subscription <subscription> --name <app-name> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. 금고의 구성이 앱이 사용하는 네트워크나 서브넷을 통해 액세스할 수 있도록 설정되어 있는지 확인하십시오.

가상 네트워크에서 트래픽을 허용하도록 자격 증명 모음을 올바르게 구성한 경우에도 자격 증명 모음의 감사 로그에는 앱의 공용 아웃바운드 IP에서 발생한(403 - 사용할 수 없음) SecretGet 이벤트가 실패한 것으로 표시될 수 있습니다. 그러면 앱의 개인 IP에서 SecretGet 이벤트가 성공적으로 발생하며, 이것은 의도된 것입니다.

사용자가 할당한 ID를 사용하여 저장소에 액세스

일부 앱은 시스템 할당 ID를 아직 사용할 수 없는 경우 생성 시 비밀을 참조해야 합니다. 이러한 경우 사용자 할당 ID를 만들고 자격 증명 모음에 대한 액세스 권한을 미리 부여합니다.

사용자 할당 ID에 권한을 부여한 후 다음 단계를 수행합니다.

  1. 사용자의 애플리케이션에 ID를 할당합니다.

  2. 속성을 사용자 할당 ID의 리소스 ID로 설정 keyVaultReferenceIdentity 하여 Key Vault 참조 작업에 이 ID를 사용하도록 앱을 구성합니다.

    identityResourceId=$(az identity show --resource-group <group-name> --name <identity-name> --query id -o tsv)
    az webapp update --resource-group <group-name> --name <app-name> --set keyVaultReferenceIdentity=${identityResourceId}
    

이 설정은 앱에 대한 모든 Key Vault 참조에 적용됩니다.

회전을 이해하기

참조에 비밀 버전이 지정되지 않은 경우 앱은 키 자격 증명 모음에 있는 최신 버전을 사용합니다. 회전과 같은 최신 버전을 사용할 수 있게 되면 앱이 자동으로 업데이트되고 24시간 이내에 최신 버전 사용을 시작합니다.

지연은 App Service가 Key Vault 참조의 값을 캐시하고 24시간마다 다시 설정하기 때문입니다. 앱에 대한 구성 변경으로 인해 앱이 다시 시작되고 참조된 모든 비밀이 즉시 다시 생성됩니다.

앱의 Key Vault 참조를 강제로 확인하려면 API 엔드포인트 https://management.azure.com/[Resource ID]/config/configreferences/appsettings/refresh?api-version=2022-03-01에 인증된 POST 요청을 합니다.

Key Vault의 원본 앱 설정 이해

Key Vault 참조를 사용하려면 참조를 설정 값으로 설정합니다. 앱은 키를 사용하여 비밀을 정상적으로 참조할 수 있습니다. 코드 변경은 필요하지 않습니다.

각 환경에 대해 별도의 보안 저장소가 있어야 하므로 Key Vault 참조를 사용하는 대부분의 앱 설정은 슬롯 설정으로 지정해야 합니다.

ko-KR: Key Vault 참조는 @Microsoft.KeyVault({referenceString}) 형식으로, {referenceString}은 다음 형식 중 하나입니다.

참조 문자열 설명
SecretUri=<secretUri> 비밀 저장소에 있는 비밀의 전체 데이터 평면 URI여야 합니다. 예: https://myvault.vault.azure.net/secrets/mysecret. 필요에 따라 .와 같은 https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931버전을 포함합니다.
VaultName=<vaultName>;SecretName=<secretName>;SecretVersion=<secretVersion> VaultName 값은 필수이며 보관함 이름입니다. 값은 SecretName 필수이며 비밀 이름입니다. 값은 SecretVersion 선택 사항이지만 있는 경우 사용할 비밀의 버전을 나타냅니다.

예를 들어 특정 버전이 없는 전체 참조는 다음 문자열과 같습니다.

@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret)

또는 다음과 같습니다.

@Microsoft.KeyVault(VaultName=myvault;SecretName=mysecret)

Azure Files 탑재 시 고려 사항

앱은 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING 애플리케이션 설정을 사용하여 Azure Files를 파일 시스템으로 탑재할 수 있습니다. 이 설정에는 앱이 제대로 시작될 수 있는지 확인하기 위한 유효성 검사가 포함되어 있습니다.

플랫폼은 Azure Files 내에서 콘텐츠 공유를 사용하는 데 의존합니다. 플랫폼은 기본 설정 WEBSITE_CONTENTSHARE을 사용하여 지정된 이름이 없는 경우 기본 이름을 가정합니다. 이러한 설정을 수정하는 모든 요청의 경우 플랫폼은 이 콘텐츠 공유가 존재하는지 확인합니다. 콘텐츠 공유가 없으면 플랫폼에서 콘텐츠 공유를 만들려고 시도합니다. 플랫폼이 콘텐츠 공유를 찾거나 만들 수 없는 경우 요청을 차단합니다.

이 설정에서 Key Vault 참조를 사용하는 경우 들어오는 요청을 처리하는 동안 비밀을 확인할 수 없으므로 유효성 검사에 기본적으로 실패합니다. 문제를 방지하려면 WEBSITE_SKIP_CONTENTSHARE_VALIDATION1으로 설정하여 유효성 검사를 건너뛸 수 있습니다. 이 설정은 App Service에 모든 검사를 무시하도록 지시하고 콘텐츠 공유를 만들지 않습니다. 콘텐츠 공유를 미리 만들어야 합니다.

주의

유효성 검사를 건너뛰고 연결 문자열 또는 콘텐츠 공유가 잘못된 경우 앱이 제대로 시작되지 않고 HTTP 500 오류가 발생합니다.

앱을 만드는 과정의 일환으로 관리 ID 권한이 전파되지 않거나 가상 네트워크 통합이 설정되지 않아 콘텐츠 공유의 탑재 시도가 실패할 수 있습니다. 이 동작을 수용하기 위해 배포 템플릿의 뒷부분까지 Azure Files 설정을 연기할 수 있습니다. 자세한 내용은 이 문서의 뒷부분에 있는 Azure Resource Manager 배포 를 참조하세요.

이 경우 App Service는 Azure Files가 설정될 때까지 기본 파일 시스템을 사용하고 파일은 복사되지 않습니다. Azure Files가 탑재되기 전에 중간 기간 동안 배포 시도가 발생하지 않도록 해야 합니다.

Application Insights 계측에 대한 고려 사항

앱은 APPINSIGHTS_INSTRUMENTATIONKEY 또는 APPLICATIONINSIGHTS_CONNECTION_STRING 애플리케이션 설정을 사용하여 Application Insights와 통합할 수 있습니다.

App Service 및 Azure Functions의 경우 Azure Portal은 이러한 설정을 사용하여 리소스의 원격 분석 데이터를 표시합니다. 이러한 값이 Key Vault에서 참조되는 경우 이 방법을 사용할 수 없습니다. 대신, telemetry를 보기 위해 Application Insights 리소스를 직접 사용해야 합니다. 그러나 이러한 값 은 비밀로 간주되지 않으므로 Key Vault 참조를 사용하는 대신 직접 구성하는 것이 좋습니다.

Azure Resource Manager 배포

Azure Resource Manager 템플릿을 통해 리소스 배포를 자동화하는 경우 특정 순서로 종속성을 시퀀스해야 할 수 있습니다. 앱 정의에서 siteConfig 속성을 사용하는 대신 앱 설정을 자체 리소스로 정의해야 합니다. 시스템 할당 ID가 만들어지고 액세스 정책에서 사용할 수 있도록 먼저 앱을 정의해야 합니다.

다음 가상 템플릿은 함수 앱의 예시입니다.

{
    //...
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[variables('storageAccountName')]",
            //...
        },
        {
            "type": "Microsoft.Insights/components",
            "name": "[variables('appInsightsName')]",
            //...
        },
        {
            "type": "Microsoft.Web/sites",
            "name": "[variables('functionAppName')]",
            "identity": {
                "type": "SystemAssigned"
            },
            //...
            "resources": [
                {
                    "type": "config",
                    "name": "appsettings",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('storageConnectionStringName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('appInsightsKeyName'))]"
                    ],
                    "properties": {
                        "AzureWebJobsStorage": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "APPINSIGHTS_INSTRUMENTATIONKEY": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsKeyName')).secretUriWithVersion, ')')]",
                        "WEBSITE_ENABLE_SYNC_UPDATE_SITE": "true"
                        //...
                    }
                },
                {
                    "type": "sourcecontrols",
                    "name": "web",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.Web/sites/config', variables('functionAppName'), 'appsettings')]"
                    ],
                }
            ]
        },
        {
            "type": "Microsoft.KeyVault/vaults",
            "name": "[variables('keyVaultName')]",
            //...
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]"
            ],
            "properties": {
                //...
                "accessPolicies": [
                    {
                        "tenantId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.tenantId]",
                        "objectId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.principalId]",
                        "permissions": {
                            "secrets": [ "get" ]
                        }
                    }
                ]
            },
            "resources": [
                {
                    "type": "secrets",
                    "name": "[variables('storageConnectionStringName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
                    ],
                    "properties": {
                        "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),'2019-09-01').key1)]"
                    }
                },
                {
                    "type": "secrets",
                    "name": "[variables('appInsightsKeyName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
                    ],
                    "properties": {
                        "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2019-09-01').InstrumentationKey]"
                    }
                }
            ]
        }
    ]
}

참고

이 예제에서 원본 제어 배포는 애플리케이션 설정에 따라 다릅니다. 앱 설정 업데이트가 비동기적으로 동작하기 때문에 이 종속성은 일반적으로 안전하지 않은 동작입니다. 그러나 애플리케이션 설정을 포함했기 WEBSITE_ENABLE_SYNC_UPDATE_SITE 때문에 업데이트가 동기적입니다. 소스 제어 배포는 애플리케이션 설정이 완전히 업데이트된 후에만 시작됩니다. 더 많은 앱 설정은 Azure App Service에서 환경 변수 및 앱 설정을 참조하세요.

Key Vault 참조 문제 해결

참조가 제대로 확인되지 않으면 참조 문자열이 대신 사용됩니다(예 @Microsoft.KeyVault(...): .). 이 경우 다른 값의 비밀이 예상되므로 애플리케이션에서 오류가 발생할 수 있습니다.

해결 오류는 일반적으로 Key Vault 액세스 정책의 잘못된 구성으로 인해 발생합니다. 그러나 그 이유는 비밀이 더 이상 존재하지 않거나 참조에 구문 오류가 포함되어 있을 수도 있습니다.

구문이 올바른 경우 Azure Portal에서 현재 확인 상태를 확인하여 오류의 다른 원인을 볼 수 있습니다. 애플리케이션 설정으로 이동하여 해당 참조에 대한 편집을 선택합니다. 편집 대화 상자에는 오류를 포함한 상태 정보가 표시됩니다. 상태 메시지가 표시되지 않으면 구문이 잘못되었으며 Key Vault 참조로 인식되지 않음을 의미합니다.

또한 기본 제공 탐지기 중 하나를 사용하여 자세한 정보를 얻을 수 있습니다.

App Service에 대한 탐지기를 사용하려면 다음을 수행합니다.

  1. Azure Portal에서 앱으로 이동합니다.
  2. 문제 진단 및 해결을 선택합니다.
  3. 가용성 및 성능>웹앱 다운을 선택합니다.
  4. 검색 상자에서 Key Vault 애플리케이션 설정 진단을 검색하고 선택합니다.

Azure Functions에 대한 탐지기를 사용하려면 다음을 수행합니다.

  1. Azure Portal에서 앱으로 이동합니다.
  2. 플랫폼 기능으로 이동합니다.
  3. 문제 진단 및 해결을 선택합니다.
  4. 가용성 및 성능>함수 앱 다운 또는 보고 오류를 선택합니다.
  5. Key Vault 애플리케이션 설정 진단을 선택합니다.