.Net कोर 5.0 - Sql Azure + हमेशा एन्क्रिप्टेड + प्रबंधित पहचान

Dec 11 2020

मेरे पास एन्क्रिप्टेड कॉलम (हमेशा एज़्योर कीवॉल्ट के साथ एन्क्रिप्टेड) ​​के साथ एक एज़्योर एसक्यूएल डीबी है। मैं एसएसबी से इस डीबी को एक्सेस कर सकता हूं और मैं डिक्रिप्टेड डेटा देख सकता हूं।

मेरे पास .net Core 5.0 के साथ बनाया गया एक वेब ऐप भी है जो Azure App Service के लिए तैनात है। ऐप सेवा ने प्रबंधित पहचान को चालू कर दिया है और कुंजी वॉल्ट जिसके लिए एसक्यूएल डीबी है, उसके लिए डेटा सेटिंग को एक्सेस करने के लिए इस ऐप सेवा को अनुमति देने के लिए एसक्यूएल डीबी की पहुंच नीति है।

वेब ऐप प्रबंधित पहचान के साथ काम करता है क्योंकि मैं देख सकता हूं कि एन्क्रिप्ट किए गए डेटा को बिना किसी समस्या के पुनर्प्राप्त नहीं किया जाता है।

इसके अलावा, कनेक्शन स्ट्रिंग शामिल है 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'। मान्य (वर्तमान में पंजीकृत) कस्टम कुंजी स्टोर प्रदाता नाम हैं:। कृपया डेटाबेस में कॉलम मास्टर कुंजी परिभाषाओं में मुख्य स्टोर प्रदाता जानकारी को सत्यापित करें, और अपने आवेदन में उपयोग किए गए सभी कस्टम कुंजी स्टोर प्रदाताओं को ठीक से पंजीकृत करें।

ऐसा लगता है कि कुंजी वॉल्ट प्रदाता पंजीकृत नहीं है।

एन्क्रिप्टेड डेटा को क्वेरी करने के लिए मुझे क्या करना चाहिए?

संकुल का उपयोग किया

    <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 में डिक्रिप्टेड डेटा को पढ़ना असंभव है। एमएस पैकेज में एक बग है और ऐप सेवा कभी अधिकृत नहीं है।

आपको सेवा प्राचार्य का उपयोग करना होगा। यह एक आकर्षण की तरह काम करता है!

अपडेट करें

मुझे एमएस इंजीनियरों का शुक्रिया अदा करना चाहिए, जिन्होंने काम करने वाले समाधान की पेशकश की:

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

मैं इस कोड का उपयोग करने में सक्षम था जो उपयोग करता है SqlColumnEnc एन्क्रिप्शन प्रदाता को एक टोकन प्रदान करता है। DefaultAzureCredential एक ऐप सेवा के रूप में तैनात होने पर एक प्रबंधित पहचान देता है:

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

इसे अपने स्टार्टअप से कॉल करें। कॉन्फिगर विधि।