/// <summary> /// Initializes a new instance of <see cref="Tailspin.Surveys.Security.CertificateCredentialService"/>. /// </summary> /// <param name="options">Configuration options for this instance."/></param> public CertificateCredentialService(IOptions <ConfigurationOptions> options) { var aadOptions = options.Value?.AzureAd; Guard.ArgumentNotNull(aadOptions, "configOptions.AzureAd"); Guard.ArgumentNotNull(aadOptions.Asymmetric, "configOptions.AzureAd.Assymetric"); _credential = new Lazy <Task <AdalCredential> >(() => { X509Certificate2 cert = CertificateUtility.FindCertificateByThumbprint( aadOptions.Asymmetric.StoreName, aadOptions.Asymmetric.StoreLocation, aadOptions.Asymmetric.CertificateThumbprint, aadOptions.Asymmetric.ValidationRequired); string password = null; var certBytes = CertificateUtility.ExportCertificateWithPrivateKey(cert, out password); return(Task.FromResult(new AdalCredential(new ClientAssertionCertificate(aadOptions.ClientId, new X509Certificate2(certBytes, password))))); }); }
/// <summary> /// Loads all secrets which are delimited by : so that they can be retrieved by the config system /// Since KeyVault does not allow : as delimiters in the share secret name, the actual name is not used as key for configuration. /// The Tag property is used instead /// The tag should always be of the form "ConfigKey"="ParentKey1:Child1:.." /// </summary> /// <param name="token"></param> /// <returns></returns> private async Task LoadAsync(CancellationToken token) { string password; var cert = CertificateUtility.FindCertificateByThumbprint(_storeName, _storeLocation, _certificateThumbprint, _validateCertificate); var certBytes = CertificateUtility.ExportCertificateWithPrivateKey(cert, out password); _assertion = new ClientAssertionCertificate(_appClientId, certBytes, password); Data = new Dictionary <string, string>(); // This returns a list of identifiers which are uris to the secret, you need to use the identifier to get the actual secrets again. var kvClient = new KeyVaultClient(GetTokenAsync); var secretsResponseList = await kvClient.GetSecretsAsync(_vault, MaxSecrets, token); foreach (var secretItem in secretsResponseList.Value ?? new List <SecretItem>()) { //The actual config key is stored in a tag with the Key "ConfigKey" since : is not supported in a shared secret name by KeyVault if (secretItem.Tags != null && secretItem.Tags.ContainsKey(ConfigKey)) { var secret = await kvClient.GetSecretAsync(secretItem.Id, token); Data.Add(secret.Tags[ConfigKey], secret.Value); } } }