Last active
October 7, 2019 15:16
-
-
Save veleek/6751f70081e13d5f8bdf3f0cb09d0a4f to your computer and use it in GitHub Desktop.
Minimal repro for KeyVault "No such host is known" error: https://github.com/Azure/azure-sdk-for-net/issues/7873
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>netcoreapp3.0</TargetFramework> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Azure.Identity" Version="1.0.0-preview.4" /> | |
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.0.0-preview.4" /> | |
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.4"> | |
<PrivateAssets>all</PrivateAssets> | |
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |
</PackageReference> | |
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> | |
<PackageReference Include="Serilog" Version="2.8.0" /> | |
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> | |
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" /> | |
</ItemGroup> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Azure; | |
using Azure.Security.KeyVault.Secrets; | |
using Serilog; | |
using Serilog.Context; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Threading.Tasks; | |
using System.Threading.Tasks.Dataflow; | |
namespace ContentKey.Cli | |
{ | |
public static class Program | |
{ | |
public static async Task Main(string[] args) | |
{ | |
string logPath = Path.Combine(Environment.CurrentDirectory, $"ContentKeys.Cli_{DateTime.UtcNow:yyyy-MM-dd_hh-mm-ss}.log"); | |
LoggerConfiguration loggerConfiguration = new LoggerConfiguration() | |
.MinimumLevel.Verbose() | |
.Enrich.FromLogContext() | |
.WriteTo.Console( | |
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}]{Properties} {Message}{NewLine}{Exception}") | |
.WriteTo.File( | |
logPath, | |
outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fffTzzz} {Level:u3}]{Properties} {Message:lj}{NewLine}{Exception}"); | |
Log.Logger = loggerConfiguration.CreateLogger(); | |
var keySource = new KeyVaultContentKeySource(args[0]); | |
var keys = await keySource.LoadKeys(); | |
Log.Information("Loaded {count} keys.", keys.Count); | |
} | |
} | |
public class KeyVaultContentKeySource | |
{ | |
private readonly SecretClient secretClient; | |
public int MaximumParallelRequests { get; set; } = 25; | |
public KeyVaultContentKeySource(string vaultBaseUrl) | |
{ | |
if (string.IsNullOrWhiteSpace(vaultBaseUrl)) | |
{ | |
throw new ArgumentNullException(nameof(vaultBaseUrl)); | |
} | |
Log.Information("Connecting to KeyVault {keyVault}", vaultBaseUrl); | |
var creds = new Azure.Identity.InteractiveBrowserCredential("04b07795-8ddb-461a-bbee-02f9e1bf7b46"); | |
secretClient = new SecretClient(new Uri($"https://{vaultBaseUrl}.vault.azure.net/"), creds); | |
} | |
public async IAsyncEnumerable<ContentKey> EnumerateKeysAsync() | |
{ | |
int count = 0; | |
await foreach (Response<SecretBase> secret in secretClient.GetSecretsAsync()) | |
{ | |
yield return new ContentKey { Id = secret.Value.Name, Updated = secret.Value.Updated }; | |
} | |
} | |
public async Task<ContentKey> LoadKeyAsync(string keyId) | |
{ | |
Log.Debug("Loading key vault secret {secretId}", keyId); | |
Response<Secret> secret = await secretClient.GetAsync(keyId); | |
return new ContentKey | |
{ | |
Id = secret.Value.Name, | |
Updated = secret.Value.Updated, | |
Value = secret.Value.Value | |
}; | |
} | |
public async Task<List<ContentKey>> LoadKeys() | |
{ | |
TransformBlock<ContentKey, ContentKey> loadKeyValue = new TransformBlock<ContentKey, ContentKey>( | |
async key => | |
{ | |
using IDisposable _ = LogContext.PushProperty("KeyId", key.Id); | |
Log.Information("Loading Key: {Updated}", key.Updated); | |
try | |
{ | |
return await this.LoadKeyAsync(key.Id); | |
} | |
catch (Exception e) | |
{ | |
Log.Error(e, "Failed to load key"); | |
return null; | |
} | |
}, | |
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = MaximumParallelRequests == 0 ? 1 : MaximumParallelRequests } | |
); | |
List<ContentKey> contentKeys = new List<ContentKey>(); | |
ActionBlock<ContentKey> addToList = new ActionBlock<ContentKey>(key => | |
{ | |
if (key != null) | |
{ | |
contentKeys.Add(key); | |
} | |
}); | |
loadKeyValue.LinkTo(addToList, new DataflowLinkOptions { PropagateCompletion = true }); | |
await foreach (var contentKey in this.EnumerateKeysAsync()) | |
{ | |
loadKeyValue.Post(contentKey); | |
} | |
loadKeyValue.Complete(); | |
await loadKeyValue.Completion; | |
Log.Information("Updated list contains {count} keys", contentKeys.Count); | |
return contentKeys; | |
} | |
} | |
public class ContentKey | |
{ | |
public string Id { get; set; } | |
public DateTimeOffset? Updated { get; set; } | |
public string Value { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment