web-dev-qa-db-ja.com

Azure KeyVaultから接続文字列を取得する方法は?

架空のWebサイトは現在、以下を使用して接続しています。

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 Key Vaultから何かを取得するにはどうすればよいですか?

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を作成しただけです。 actualAPIとは何ですか?

未検証の試み

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;
}

ボーナスリーディング

20
Ian Boyd

実際のAPIとは何ですか?

GetSecret API を使用して値を取得できます。

準備:

レジストリAzure Active Directoryアプリケーションとロールの割り当て

手順:

1. KeyVaultを作成し、Azureポータルからシークレットを追加します

enter image description here

2.Configアクセスポリシー

enter image description here

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を使用したテスト

enter image description here

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関数に次のコードを追加してテストします。

enter image description here

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>

また、前述のCtrlDot document から詳細情報を取得することもできます。

24
Tom Sun

Key Vaultには何もありません(素晴らしい製品だと思います!)、しかし、私は自分自身を助けることはできませんが、あなたはこれを過剰に設計していると思います。

組み込みの 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;
}

WebConfigurationManagerと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;
}
16
evilSnobu