用于 SQL Server 始终加密操作的 C# 控制台应用程序 - 具有证书身份验证的 Azure Key Vault CMK

问题描述 投票:0回答:1

我希望我的 C# 控制台应用程序能够使用 Azure Key Vault 中的列主密钥对本地数据库中的始终加密列执行 SQL DML,并且我希望使用本地证书存储中存储的 AppId 和证书进行身份验证。我已经注册了应用程序和服务主体、配置了证书并在 Azure CLI 中分配了权限。我已设置加密,已在 SQL Mgmt Studio 中验证。

我能够使用 ODBC 驱动程序连接并执行 SQL https://learn.microsoft.com/en-us/sql/connect/odbc/using-always-encrypted-with-the-odbc-driver?view= sql-server-2017 使用 userid/pwd 和交互模式以及类似这样的连接字符串:

Driver={ODBC Driver 17 for SQL Server};server={instanceName};uid={myUid};trusted_connection=Yes;database={myDBName};columnencryption=Enabled;keystoreauthentication=KeyVaultPassword;keystoreprincipalid={MyADUserId};KeyStoreSecret={MyADPassword}

使用 ODBC,还可以选择在连接字符串中连接 AppId/Secret,但我不想将它们插入到我的应用程序中。

通过 ODBC 的最后一个选项是 ManagedIdentity,但我认为我不能在本地使用它......不确定。

这就是为什么我决定使用 AppId + Cert 进行身份验证。

作为 POC,我可以连接到 AKV 并查看列主密钥,如下所示:

X509Certificate2 cert;
string tenantId = "{my tenant id}";
string appId = "{my app id}";
string keyvaultURI = "https://mykeyvault.vault.azure.net/";

store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates;

var certFound = certs.Find(X509FindType.FindBySubjectDistinguishedName, "CN={myCertSubject}",    false).OfType<X509Certificate2>();
                
if (certFound.Count() > 0)
{
   cert = certFound.Single();
   var credential = new ClientCertificateCredential(tenantId, appId, cert);

   var client = new KeyClient(new Uri(keyvaultURI), credential);
   KeyVaultKey key = client.GetKey("MyColumnMasterKey");
   Console.WriteLine(key.Name);
   Console.WriteLine(key.KeyType);

上面的方法有效,尽管我不确定我是否走在正确的轨道上。我最终想要做的是,使用 Microsoft.Data.SqlClient 实例化 SQLCommand,然后将其连接到 CMK 的 AzureKeyVault。不过,我不知道如何检索令牌,因为我需要传递某种名为“TokenRequestContext”的结构。据说,我可以从上面获得的凭据中检索令牌,并使用如下方式将其连接到 SQL 列加密:

var token = credential.GetToken( t ); // t is "TokenRequestContext"...  what is that???
var x = new SqlColumnEncryptionAzureKeyVaultProvider(token); // pass credentialToken

因此,我可以进行身份验证,但不完全按照我需要的方式进行身份验证,以便从身份验证跳转到在 SQLCommand 中使用该身份验证。

看起来我走在正确的轨道上吗?如何从经过身份验证的 ClientCertificateCredential 获取令牌?

感谢您的帮助。

c# sql-server authentication azure-keyvault always-encrypted
1个回答
0
投票
  • 使用

    Azure.Identity
    创建代币凭证(
    DefaultAzureCredential
    ),简化代币获取。

  • 使用

    SqlColumnEncryptionAzureKeyVaultProvider
    tokenCredential
    注册 Azure Key Vault 提供程序以实现始终加密。

  • 使用下面的代码,我使用证书对应用程序进行了身份验证,并从 Azure Key Vault 访问列主密钥,以在 SQL Server 数据库上启用始终加密操作。

这是更正后的代码


using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Data.SqlClient;
using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider;
using Azure.Identity;
using Azure.Security.KeyVault.Keys;

class Program
{
    static async Task Main(string[] args)
    {

       string keyVaultUrl = configuration["AzureKeyVaultUrl"];
       string columnMasterKeyName = configuration["ColumnMasterKeyName"];

        // Use Azure.Identity to create a token credential
        var tokenCredential = new DefaultAzureCredential();

        // Register the Azure Key Vault provider for Always Encrypted
        SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(tokenCredential);

        Dictionary<string, SqlColumnEncryptionKeyStoreProvider> providers = new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();
        providers.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);

        // register the provider with ADO.net
        SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);

        string connectionString = "Server=localhost;Database=master;Trusted_Connection=True;TrustServerCertificate=True";
        using (var connection = new SqlConnection(connectionString))
        {
            connection.Open();

            // Perform SQL DML operations using Always Encrypted columns
            // Example: Insert, Update, Select with encrypted columns

            connection.Close();
        }
        Console.WriteLine("Accessed ");
    }
}

结果 enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.