.Net Core 5.0-Sql Azure + 상시 암호화 + 관리 ID

Dec 11 2020

암호화 된 열이있는 Azure SQL Db (Azure KeyVault로 항상 암호화 됨)가 있습니다. SSMS에서이 DB에 액세스 할 수 있으며 복호화 된 데이터를 볼 수 있습니다.

또한 Azure App Service에 배포 된 .Net Core 5.0으로 만든 웹앱이 있습니다. 앱 서비스에는 관리 ID가 켜져 있고 해당 SQL Db에 대한 enc / dec 키가있는 Key Vault에는이 앱 서비스가 데이터를 해독 할 수 있도록 허용하는 액세스 정책 설정이 있습니다.

웹 앱은 암호화되지 않은 데이터가 문제없이 검색된다는 것을 알 수 있으므로 관리 ID로 작동합니다.

또한 연결 문자열에는 Column Encryption Setting=enabled;. 다음은 연결 문자열입니다.

Server=tcp:server.database.windows.net,1433;Database=somedb;Column Encryption Setting=enabled;

문제는 이런 종류의 설정으로 샘플을 찾을 수 없다는 것입니다. 일부를 찾았고 등록해야 함을 이해합니다 SqlColumnEncryptionAzureKeyVaultProvider. SqlConnection을 얻는 코드는 다음과 같습니다.

    internal static class AzureSqlConnection
    {
        private static bool _isInitialized;

        private static void InitKeyVaultProvider(ILogger logger)
        {
            /*
             * from here - https://github.com/dotnet/SqlClient/blob/master/release-notes/add-ons/AzureKeyVaultProvider/1.2/1.2.0.md
             *      and  - https://github.com/dotnet/SqlClient/blob/master/doc/samples/AzureKeyVaultProviderExample.cs
             *
             */

            try
            {
                // Initialize AKV provider
                SqlColumnEncryptionAzureKeyVaultProvider sqlColumnEncryptionAzureKeyVaultProvider =
                    new SqlColumnEncryptionAzureKeyVaultProvider(AzureActiveDirectoryAuthenticationCallback);

                // Register AKV provider
                SqlConnection.RegisterColumnEncryptionKeyStoreProviders(
                    new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>(1, StringComparer.OrdinalIgnoreCase)
                    {
                        {SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, sqlColumnEncryptionAzureKeyVaultProvider}
                    });

                _isInitialized = true;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Could not register SqlColumnEncryptionAzureKeyVaultProvider");
                throw;
            }
        }

        internal static async Task<SqlConnection> GetSqlConnection(string connectionString, ILogger logger)
        {
            if (!_isInitialized) InitKeyVaultProvider(logger);

            try
            {
                SqlConnection conn = new SqlConnection(connectionString);
                /*
                         * This is Managed Identity (not Always Encrypted)
                         *  https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi#modify-aspnet-core
                         *
                         */
#if !DEBUG
                conn.AccessToken = await new AzureServiceTokenProvider().GetAccessTokenAsync("https://database.windows.net/");
                logger.LogInformation($"token: {conn.AccessToken}"); #endif await conn.OpenAsync(); return conn; } catch (Exception ex) { logger.LogError(ex, "Could not establish a connection to SQL Server"); throw; } } private static async Task<string> AzureActiveDirectoryAuthenticationCallback(string authority, string resource, string scope) { return await new AzureServiceTokenProvider().GetAccessTokenAsync("https://database.windows.net/"); //AuthenticationContext? authContext = new AuthenticationContext(authority); //ClientCredential clientCred = new ClientCredential(s_clientId, s_clientSecret); //AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred); //if (result == null) //{ // throw new InvalidOperationException($"Failed to retrieve an access token for {resource}");
            //}

            //return result.AccessToken;
        }
    }

이 코드는 예외를 발생시키지 않으며 암호화되지 않은 쿼리에 대해 작동합니다. 그러나 암호화 된 쿼리의 경우 다음 오류가 발생합니다.

열 암호화 키를 해독하지 못했습니다. 잘못된 키 저장소 공급자 이름 : 'AZURE_KEY_VAULT'. 키 저장소 공급자 이름은 시스템 키 저장소 공급자 또는 등록 된 사용자 지정 키 저장소 공급자를 나타내야합니다. 유효한 시스템 키 저장소 공급자 이름은 'MSSQL_CERTIFICATE_STORE', 'MSSQL_CNG_STORE', 'MSSQL_CSP_PROVIDER'입니다. 유효한 (현재 등록 된) 사용자 지정 키 저장소 공급자 이름은. 데이터베이스의 열 마스터 키 정의에서 키 저장소 공급자 정보를 확인하고 응용 프로그램에 사용 된 모든 사용자 지정 키 저장소 공급자가 올바르게 등록되었는지 확인하십시오. 열 암호화 키를 해독하지 못했습니다. 잘못된 키 저장소 공급자 이름 : 'AZURE_KEY_VAULT'. 키 저장소 공급자 이름은 시스템 키 저장소 공급자 또는 등록 된 사용자 지정 키 저장소 공급자를 나타내야합니다.유효한 시스템 키 저장소 공급자 이름은 'MSSQL_CERTIFICATE_STORE', 'MSSQL_CNG_STORE', 'MSSQL_CSP_PROVIDER'입니다. 유효한 (현재 등록 된) 사용자 지정 키 저장소 공급자 이름은. 데이터베이스의 열 마스터 키 정의에서 키 저장소 공급자 정보를 확인하고 응용 프로그램에 사용 된 모든 사용자 지정 키 저장소 공급자가 올바르게 등록되었는지 확인하십시오.

Key Vault 공급자가 등록되지 않은 것 같습니다.

암호화 된 데이터를 쿼리하려면 어떻게해야합니까?

사용 된 패키지

    <PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.6.0" />
    <PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.0" />
    <PackageReference Include="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" Version="1.2.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />

답변

2 alvipeo Jan 25 2021 at 23:15

MSI를 사용하면 .NET 5에서 해독 된 데이터를 읽을 수 없습니다. MS 패키지에 버그가 있으며 앱 서비스가 승인되지 않았습니다.

서비스 주체를 사용해야합니다. 이것은 매력처럼 작동합니다!

최신 정보

작업 솔루션을 제공 한 MS 엔지니어에게 감사드립니다.

public static async Task<string> KeyVaultAuthenticationCallback(string authority, string resource, string scope)
{
     return await Task.Run(() => new ManagedIdentityCredential().GetToken(new TokenRequestContext(new string [] {"https://vault.azure.net/.default"})).Token);
     /********************** Alternatively, to use User Assigned Managed Identity ****************/
     // var clientId = {clientId_of_UserAssigned_Identity};
     // return await Task.Run(() => new ManagedIdentityCredential(clientId).GetToken(new TokenRequestContext(new string [] {"https://vault.azure.net/.default"})).Token);
}
SpinDoctor Apr 10 2021 at 04:19

SqlColumnEncryption 공급자에 TokenCredential을 제공하는이 코드를 사용할 수있었습니다. DefaultAzureCredential은 App Service로 배포 될 때 관리 ID를 반환합니다.

            SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new DefaultAzureCredential());
            Dictionary<string, SqlColumnEncryptionKeyStoreProvider> providers = new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>
            {
                { SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider }
            };
            SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);

startup.Configure 메서드에서 호출하십시오.