DeviceBridge/Providers/SecretsProvider.cs (97 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.KeyVault.Models;
using Microsoft.Azure.Services.AppAuthentication;
using NLog;
namespace DeviceBridge.Providers
{
public class SecretsProvider : ISecretsProvider
{
public const string IotcIdScope = "iotc-id-scope";
public const string IotcSasKey = "iotc-sas-key";
public const string IotcEncryptionKey = "iotc-encryption-key";
public const string SqlServer = "sql-server";
public const string SqlPassword = "sql-password";
public const string SqlUsername = "sql-username";
public const string SqlDatabase = "sql-database";
public const string ApiKeyName = "apiKey";
private readonly KeyVaultClient kvClient;
private readonly string kvUrl;
private string apiKey;
public SecretsProvider(string kvUrl)
{
var tokenProvider = new AzureServiceTokenProvider();
kvClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(tokenProvider.KeyVaultTokenCallback));
this.kvUrl = kvUrl;
}
public async Task PutSecretAsync(Logger logger, string secretName, string secretValue)
{
logger.Info("Adding secret {secretName} to Key Vault", secretName);
await kvClient.SetSecretAsync($"{kvUrl}", secretName, secretValue);
}
public async Task<string> GetIdScopeAsync(Logger logger)
{
return await GetSecretValueAsync(logger, IotcIdScope);
}
public async Task<string> GetIotcSasKeyAsync(Logger logger)
{
return await GetSecretValueAsync(logger, IotcSasKey);
}
public async Task<string> GetSqlPasswordAsync(Logger logger)
{
return await GetSecretValueAsync(logger, SqlPassword);
}
public async Task<string> GetSqlUsernameAsync(Logger logger)
{
return await GetSecretValueAsync(logger, SqlUsername);
}
public async Task<string> GetSqlServerAsync(Logger logger)
{
return await GetSecretValueAsync(logger, SqlServer);
}
public async Task<string> GetSqlDatabaseAsync(Logger logger)
{
return await GetSecretValueAsync(logger, SqlDatabase);
}
public async Task<string> GetApiKey(Logger logger)
{
if (apiKey == null)
{
apiKey = await GetSecretValueAsync(logger, ApiKeyName);
}
return apiKey;
}
public async Task<SecretBundle> GetEncryptionKey(Logger logger, string version = null)
{
return await GetSecretAsync(logger, IotcEncryptionKey, version);
}
public async Task PutEncryptionKey(Logger logger, string value)
{
await PutSecretAsync(logger, IotcEncryptionKey, value);
}
public async Task<IDictionary<string, SecretBundle>> GetEncryptionKeyVersions(Logger logger)
{
var versions = await kvClient.GetSecretVersionsAsync(kvUrl, IotcEncryptionKey);
var secrets = new Dictionary<string, SecretBundle>();
do
{
foreach (var version in versions)
{
secrets.Add(version.Identifier.Version, await GetEncryptionKey(logger, version.Identifier.Version));
}
}
while (versions.NextPageLink != null && (versions = await kvClient.GetSecretVersionsNextAsync(versions.NextPageLink)) != null);
return secrets;
}
private async Task<string> GetSecretValueAsync(Logger logger, string secretName, string secretVersion = null)
{
return (await GetSecretAsync(logger, secretName, secretVersion)).Value;
}
private async Task<SecretBundle> GetSecretAsync(Logger logger, string secretName, string secretVersion = null)
{
logger.Info("Getting secret {secretName} from Key Vault", secretName);
return (secretVersion == null) ? await kvClient.GetSecretAsync($"{kvUrl}", secretName) : await kvClient.GetSecretAsync($"{kvUrl}", secretName, secretVersion);
}
}
}