【问题标题】:How to get connection string out of Azure KeyVault?如何从 Azure KeyVault 中获取连接字符串?
【发布时间】:2017-09-29 00:59:21
【问题描述】:

一个假设的网站当前连接使用:

public SqlConnection CreateConnection()
{
   DbConnection connection = new SqlConnection();
   connection.ConnectionString = GetConnectionString();
   connection.Open();

   return connection;
}

神奇的连接字符串存放在web.config

String GetConnectionString()
{
   //Get the connection string info from web.config
   ConnectionStringSettings cs = ConfigurationManager.ConnectionStrings["db"];

   if (cs == null)
      throw new Exception("Could not locate DB connection string");

   return cs.ConnectionString;
}

现在我想将连接字符串从 web.config 文件移到 Azure KeyVault。如何从 Azure 密钥保管库中检索任何内容?

String GetConnectionString()
{
   //Get the connection string info from Azure KeyVault
   String connectionString = GetAzureSecret("dbConnectionString");

   if (String.IsNullOrWhitespace(connectionString)
      throw new Exception.Create("Could not connection string of Azure Key Vault");

   return connectionString;
}

除了我刚刚编写了易于使用的 Azure API。 实际 api是什么?

未经测试的尝试

string GetAzureSecret(string key)
{
    KeyVaultClient vault = new KeyVaultClient();
    vault.OnAuthenticate += VaultClientAuthenticate;

    var sec = await vault.GetSecretAsync(Key);
    return sec.Value;
}

public static async Task<string> VaultClientAuthenticate(string authority, string resource, string scope)
{
   String clientID = "8675209";
   String clientSecret = "correct battery horse pencil";

   var authContext = new AuthenticationContext(authority);
   ClientCredential clientCred = new ClientCredential(clientID, clientSecret);
   AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);

   if (result == null)
      throw new Exception("Could not acquire token");

   return result.AccessToken;
}

阅读奖励

【问题讨论】:

标签: c# azure security connection-string azure-keyvault


【解决方案1】:

其他人已经就如何与 Web 应用程序或 Azure 函数集成提供了很好的答案,但这里是开始使用 Key Vault 机密 SDK 的权威参考。

.NET

Java

JavaScript

Python

【讨论】:

    【解决方案2】:

    2020 年 8 月更新

    现在有一种通过 Key Vault 引用使用零自定义代码从应用服务调用 Key Vault 的低仪式方式。 https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references

    从 Key Vault 填充值的应用设置示例:

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

    如果您不想要版本标识符:

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

    您需要先在应用服务实例和 Key Vault 之间设置托管标识,才能使用 Key Vault 引用。

    我没有反对 Key Vault(我认为它是一个很棒的产品!),但是我忍不住认为你过度设计了这个。

    我会简单地使用内置的Application Settings functionality in Azure App Service

    连接字符串

    对于 .NET 应用,这些连接字符串会在运行时注入到您的 .NET 配置 connectionStrings 设置中,覆盖键等于链接数据库名称的现有条目。

    Web 应用 → 应用程序设置 → 连接字符串 → 添加连接字符串并将其命名为 db

    String GetConnectionString()
    {
       // Get the Connection String from Application Settings (App Service) 
       // with graceful fallback to web.config
       string cs = WebConfigurationManager.ConnectionStrings["db"].ConnectionString;
    
       if (cs == null)
          throw new Exception("Could not locate DB connection string");
    
       return cs;
    }
    

    What's the difference between the WebConfigurationManager and the ConfigurationManager?

    2018 年 5 月更新:

    自从Managed Service Identity 成为一件事后,获取访问令牌不再需要存储在您的服务中的机密(服务主体凭据)来访问 Key Vault,这是一个更好的提议。这是一个 Node.js 示例,只是为了给这个答案增添一点趣味:

    // Get an access token from Managed Service Identity
    // on an Azure IaaS VM
    async function getAccessTokenWithMSI() {
      let msi = await axios.get('http://169.254.169.254/metadata/identity/oauth2/token',
        {
          params: {
            'api-version': '2018-02-01',
            'resource': 'https://vault.azure.net'
          },
          headers: {
            'Metadata': 'true'
          },
          timeout: 2000
        });
    
      return msi.data.access_token;
    }
    

    然后:

    // Get a secret from Key Vault
    async function getSecret(accessToken, secretUrl) {
      let response;
      try {
        response = await axios.get(secretUrl,
          {
             params: { 'api-version': '2016-10-01' },
             headers: { 'Authorization': `Bearer ${accessToken}` },
             timeout: 3000
          });
      }
      catch (e) {
        console.log('\nError calling Key Vault:,
            e.response.status, e.response.statusText, e.response.data);
      }
      console.log('\nGet Secret response from Key Vault: ',
          JSON.stringify(response.data, null, 4));
    
      return response.data;
    }
    

    【讨论】:

    • 你解决了我的问题,但汤姆回答了问题。所以他不得不接受。但你会得到一个赞成票。
    【解决方案3】:

    对于 .net Core 并且已经安装了 Azure Key Vault。现在这非常容易。假设您的连接字符串在您的 appsettings.json 中:

    {
       "ConnectionStrings": {
          "MyDatabase": "server=127.0.0.1;port=5678;database=mydb;user=FullMontyBurns;password=hunter2"
       } 
    }
    

    然后您在Startup.cs 中进行设置:

    string connectionString = configuration.GetConnectionString("MyDatabase");
    

    在 Azure Key Vault 中,创建一个机密:

    • 姓名: ConnectionStrings--MyDatabase
    • 价值: server=127.0.0.1;port=5678;database=mydb;user=FullMontyBurns;password=hunter2

    IConfiguration.GetConnectionString("MyDatabase") 现在从 Key Vault 中获取值。

    【讨论】:

    • 那个密码对我来说只是星号... :p
    【解决方案4】:

    实际的 api 是什么?

    我们可以使用GetSecret API 来获取价值。

    准备工作:

    Registry Azure Active Directory application and assign Role

    步骤:

    1.从 Azure 门户创建 KeyVault 并添加机密

    2.配置访问策略

    3.获取访问令牌

     var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
                ClientCredential clientCredential = new ClientCredential(appId, secretKey);
                var tokenResponse =await context.AcquireTokenAsync("https://vault.azure.net", clientCredential);
                var accessToken = tokenResponse.AccessToken;
                return accessToken;
    

    注意:Keyvault 的资源是https://vault.azure.net

    4.使用 Fiddler 进行测试

    我们也可以通过 SDK 轻松做到这一点:

    1.创建一个控制台项目和一个Utils.cs文件

    public static string EncryptSecret { get; set; }
            static string appId = "Application ID";
            static string secretKey = "Secert key";
            static string tenantId = "TenantId";
    
            public static async Task<string> GetAccessToken(string azureTenantId,string azureAppId,string azureSecretKey)
            {
    
                var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
                ClientCredential clientCredential = new ClientCredential(appId, secretKey);
                var tokenResponse =await context.AcquireTokenAsync("https://vault.azure.net", clientCredential);
                var accessToken = tokenResponse.AccessToken;
                return accessToken;
            }
    

    2.在main函数中添加如下代码并测试。

    packages.config 文件

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="Hyak.Common" version="1.0.2" targetFramework="net452" />
      <package id="Microsoft.Azure.Common" version="2.0.4" targetFramework="net452" />
      <package id="Microsoft.Azure.Common.Dependencies" version="1.0.0" targetFramework="net452" />
      <package id="Microsoft.Azure.KeyVault" version="1.0.0" targetFramework="net452" />
      <package id="Microsoft.Bcl" version="1.1.9" targetFramework="net452" />
      <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net452" />
      <package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net452" />
      <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.13.9" targetFramework="net452" />
      <package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net452" />
      <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" />
    </packages>
    

    我们也可以通过document提到的CtrlDot获取更多信息。

    【讨论】:

      猜你喜欢
      • 2021-03-02
      • 2020-04-10
      • 2022-12-11
      • 2019-07-08
      • 2022-10-20
      • 2021-12-23
      • 2019-04-23
      • 2019-09-29
      • 2018-12-17
      相关资源
      最近更新 更多