From fb7334ace15b475326fa3c85cab98701987283a1 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 2 Jul 2019 15:40:39 -0700 Subject: [PATCH 01/17] Add credential support to ASP.NET Core integration layer --- eng/Directory.Build.Data.props | 5 +- eng/Packages.Data.props | 13 +- .../Azure.Core.Extensions.Samples.csproj | 11 ++ .../samples/CustomPolicy.cs | 24 ++++ .../Azure.Core.Extensions/samples/Program.cs | 20 +++ .../Azure.Core.Extensions/samples/Startup.cs | 64 +++++++++ .../samples/appsettings.json | 19 +++ .../src/Azure.Core.Extensions.csproj | 1 + .../src/AzureClientFactory.cs | 15 ++- .../src/AzureClientOptions.cs | 12 ++ .../src/AzureClientsBuilder.cs | 86 +++++++++++- .../src/AzureClientsGlobalOptions.cs | 16 +++ .../src/ClientInformation.cs | 8 +- .../src/ConfigurationClientFactory.cs | 59 +++++++- .../src/DefaultClientOptionsSetup.cs | 34 +++++ .../DefaultCredentialClientOptionsSetup.cs | 30 +++++ .../src/EventSourceLogForwarder.cs | 7 +- .../tests/AzureClientFactoryTests.cs | 126 ++++++++++++++++++ .../tests/ConfigurationClientFactoryTests.cs | 61 ++++++++- .../Azure.Core.Extensions/tests/TestClient.cs | 10 ++ .../tests/TestClientOptions.cs | 5 +- .../tests/TestClientWithCredentials.cs | 17 +++ .../tests/TestClientsBuilderExtensions.cs | 15 +++ sdk/core/Azure.Core/Azure.Core.All.sln | 85 +++++++----- .../Azure.Core/src/IAzureClientsBuilder.cs | 8 +- .../IAzureClientsBuilderWithConfiguration.cs | 4 +- .../src/IAzureClientsBuilderWithCredential.cs | 13 ++ .../Azure.Identity/src/Azure.Identity.csproj | 3 +- .../src/ClientCertificateCredential.cs | 19 +-- .../src/ClientSecretCredential.cs | 22 +-- .../Azure.Security.KeyVault.Secrets.csproj | 3 +- .../KeyVaultAzureClientBuilderExtensions.cs | 30 +++++ 32 files changed, 753 insertions(+), 92 deletions(-) create mode 100644 sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj create mode 100644 sdk/core/Azure.Core.Extensions/samples/CustomPolicy.cs create mode 100644 sdk/core/Azure.Core.Extensions/samples/Program.cs create mode 100644 sdk/core/Azure.Core.Extensions/samples/Startup.cs create mode 100644 sdk/core/Azure.Core.Extensions/samples/appsettings.json create mode 100644 sdk/core/Azure.Core.Extensions/src/AzureClientOptions.cs create mode 100644 sdk/core/Azure.Core.Extensions/src/AzureClientsGlobalOptions.cs create mode 100644 sdk/core/Azure.Core.Extensions/src/DefaultClientOptionsSetup.cs create mode 100644 sdk/core/Azure.Core.Extensions/src/DefaultCredentialClientOptionsSetup.cs create mode 100644 sdk/core/Azure.Core.Extensions/tests/TestClientWithCredentials.cs create mode 100644 sdk/core/Azure.Core/src/IAzureClientsBuilderWithCredential.cs create mode 100644 sdk/keyvault/Azure.Security.KeyVault.Secrets/src/KeyVaultAzureClientBuilderExtensions.cs diff --git a/eng/Directory.Build.Data.props b/eng/Directory.Build.Data.props index dfde50f2d44f6..fba7d98dcaae0 100644 --- a/eng/Directory.Build.Data.props +++ b/eng/Directory.Build.Data.props @@ -39,9 +39,10 @@ true + true true - true - true + true + true diff --git a/eng/Packages.Data.props b/eng/Packages.Data.props index ff46108bede64..83e47a9c05bf6 100755 --- a/eng/Packages.Data.props +++ b/eng/Packages.Data.props @@ -13,6 +13,7 @@ + @@ -38,14 +39,14 @@ - - + + - - - - + + + + diff --git a/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj b/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj new file mode 100644 index 0000000000000..52e8ccc4d4f75 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj @@ -0,0 +1,11 @@ + + + netcoreapp2.1 + $(RequiredTargetFrameworks) + + + + + + + diff --git a/sdk/core/Azure.Core.Extensions/samples/CustomPolicy.cs b/sdk/core/Azure.Core.Extensions/samples/CustomPolicy.cs new file mode 100644 index 0000000000000..47578e0a11eb5 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/samples/CustomPolicy.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Pipeline; +using Microsoft.AspNetCore.Hosting; + +namespace Azure.Core.Extensions.Samples +{ + internal class DIEnabledPolicy : SynchronousHttpPipelinePolicy + { + private readonly IHostingEnvironment _environment; + + public DIEnabledPolicy(IHostingEnvironment environment) + { + this._environment = environment; + } + + public override void OnSendingRequest(HttpPipelineMessage message) + { + message.Request.Headers.Add("application-name", _environment.ApplicationName); + base.OnSendingRequest(message); + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/samples/Program.cs b/sdk/core/Azure.Core.Extensions/samples/Program.cs new file mode 100644 index 0000000000000..8ad09e68bc66a --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/samples/Program.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; + +namespace Azure.Core.Extensions.Samples +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IWebHostBuilder CreateHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs new file mode 100644 index 0000000000000..6f873084e1f31 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.ApplicationModel.Configuration; +using Azure.Core.Pipeline; +using Azure.Core.Pipeline.Policies; +using Azure.Identity; +using Azure.Security.KeyVault.Secrets; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Azure.Core.Extensions.Samples +{ + public class Startup + { + public IConfiguration Configuration { get; } + + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); + + services.AddAzureClients(builder => { + builder.AddKeyVaultSecrets("Default", Configuration.GetSection("KeyVault")); + + // This would use configuration for auth and client settings + builder.UseDefaultConfiguration(Configuration.GetSection("Default")); + + // Configure global defaults + builder.ConfigureDefaults((options, provider) => options.AddPolicy(HttpPipelinePosition.PerCall, provider.GetService())); + + // Configure default credential + // builder.UseDefaultCredential(new ClientSecretCredential("tenantId","clientId","clientSecret")); + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, SecretClient secretClient) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.Run(async context => { + context.Response.ContentType = "text"; + foreach (var secret in secretClient.GetSecrets()) + { + await context.Response.WriteAsync(secret.Value.Name + Environment.NewLine); + } + }); + } + } +} diff --git a/sdk/core/Azure.Core.Extensions/samples/appsettings.json b/sdk/core/Azure.Core.Extensions/samples/appsettings.json new file mode 100644 index 0000000000000..f382ea8b545b3 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/samples/appsettings.json @@ -0,0 +1,19 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug" + } + }, + "AllowedHosts": "*", + "Default": { + "ClientId": "", + "ClientSecret": "", + "TenantId": "", + "TelemetryPolicy": { + "ApplicationId": "AppId" + } + }, + "KeyVault": { + "VaultUri": "https://pakrym-keyvault.vault.azure.net/" + } +} diff --git a/sdk/core/Azure.Core.Extensions/src/Azure.Core.Extensions.csproj b/sdk/core/Azure.Core.Extensions/src/Azure.Core.Extensions.csproj index cd2cdf8b5005e..ee60eae6ca018 100644 --- a/sdk/core/Azure.Core.Extensions/src/Azure.Core.Extensions.csproj +++ b/sdk/core/Azure.Core.Extensions/src/Azure.Core.Extensions.csproj @@ -29,6 +29,7 @@ + diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientFactory.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientFactory.cs index 7518dd431396c..22b9c1c38666e 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientFactory.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientFactory.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using Microsoft.Extensions.Options; namespace Azure.Core.Extensions @@ -12,11 +11,19 @@ internal class AzureClientFactory: IAzureClientFactory> _clientRegistrations; + private readonly IServiceProvider _serviceProvider; + + private readonly IOptionsMonitor> _clientsOptions; + private readonly IOptionsMonitor _monitor; private readonly EventSourceLogForwarder _logForwarder; - public AzureClientFactory(IEnumerable> clientRegistrations, IOptionsMonitor monitor, EventSourceLogForwarder logForwarder) + public AzureClientFactory( + IServiceProvider serviceProvider, + IOptionsMonitor> clientsOptions, + IEnumerable> clientRegistrations, IOptionsMonitor monitor, + EventSourceLogForwarder logForwarder) { _clientRegistrations = new Dictionary>(); foreach (var registration in clientRegistrations) @@ -24,6 +31,8 @@ public AzureClientFactory(IEnumerable> cli _clientRegistrations[registration.Name] = registration; } + _serviceProvider = serviceProvider; + _clientsOptions = clientsOptions; _monitor = monitor; _logForwarder = logForwarder; } @@ -35,7 +44,7 @@ public TClient CreateClient(string name) throw new InvalidOperationException($"Unable to find client registration with type '{typeof(TClient).Name}' and name '{name}'."); } - return registration.GetClient(_monitor.Get(name)); + return registration.GetClient(_monitor.Get(name), _clientsOptions.Get(name).CredentialFactory(_serviceProvider)); } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientOptions.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientOptions.cs new file mode 100644 index 0000000000000..471d25ced1ae2 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientOptions.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Core.Extensions +{ + internal class AzureClientOptions + { + public Func CredentialFactory { get; set; } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs index 862c9f8bfba33..b97d787f0e253 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs @@ -2,16 +2,20 @@ // Licensed under the MIT License. using System; +using Azure.Core.Pipeline; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; namespace Azure.Core.Extensions { - public sealed class AzureClientsBuilder : IAzureClientsBuilderWithConfiguration + public sealed class AzureClientsBuilder : IAzureClientsBuilderWithConfiguration, IAzureClientsBuilderWithCredential { private readonly IServiceCollection _serviceCollection; + private const string DefaultClientName = "Default"; + internal AzureClientsBuilder(IServiceCollection serviceCollection) { _serviceCollection = serviceCollection; @@ -20,23 +24,93 @@ internal AzureClientsBuilder(IServiceCollection serviceCollection) } void IAzureClientsBuilder.RegisterClient(string name, Func clientFactory, Action configureOptions) + { + ((IAzureClientsBuilderWithCredential)this).RegisterClient( + name, + (options, _) => clientFactory(options), + configureOptions, + null); + } + + void IAzureClientsBuilderWithConfiguration.RegisterClient(string name, IConfiguration configuration) + { + ((IAzureClientsBuilderWithCredential)this).RegisterClient( + name, + (options, credentials) => (TClient)ClientFactory.CreateClient(typeof(TClient), typeof(TOptions), options, configuration, credentials), + options => configuration.Bind(options), + ClientFactory.CreateCredentials(configuration)); + } + + public AzureClientsBuilder ConfigureDefaults(Action configureOptions) + { + ConfigureDefaults((options, provider) => configureOptions(options)); + return this; + } + + public AzureClientsBuilder ConfigureDefaults(Action configureOptions) + { + _serviceCollection.Configure(options => options.ConfigureOptions.Add(configureOptions)); + + return this; + } + + public AzureClientsBuilder UseDefaultConfiguration(IConfiguration configuration) + { + ConfigureDefaults(options => configuration.Bind(options)); + + var credentialsFromConfig = ClientFactory.CreateCredentials(configuration); + + if (credentialsFromConfig != null) + { + UseDefaultCredential(credentialsFromConfig); + } + + return this; + } + + void IAzureClientsBuilderWithCredential.RegisterClient(string name, Func clientFactory, Action configureOptions, TokenCredential providedCredential) { _serviceCollection.AddSingleton(new ClientRegistration(name, clientFactory)); + _serviceCollection.TryAddSingleton(typeof(IConfigureOptions>), typeof(DefaultCredentialClientOptionsSetup)); + _serviceCollection.TryAddSingleton(typeof(IConfigureOptions), typeof(DefaultClientOptionsSetup)); _serviceCollection.TryAddSingleton(typeof(IAzureClientFactory), typeof(AzureClientFactory)); + _serviceCollection.TryAddSingleton( + typeof(TClient), + provider => provider.GetService>().CreateClient(DefaultClientName)); if (configureOptions != null) { _serviceCollection.Configure(name, configureOptions); } + + if (providedCredential != null) + { + UseCredential(name, providedCredential); + } } - void IAzureClientsBuilderWithConfiguration.RegisterClient(string name, IConfiguration configuration) + + public AzureClientsBuilder UseDefaultCredential(TokenCredential tokenCredential) { - ((IAzureClientsBuilder)this).RegisterClient( - name, - options => (TClient)ConfigurationClientFactory.CreateClient(typeof(TClient), typeof(TOptions), options, configuration), - options => configuration.Bind(options)); + return UseDefaultCredential(_ => tokenCredential); + } + + public AzureClientsBuilder UseDefaultCredential(Func tokenCredentialFactory) + { + _serviceCollection.Configure(options => options.Credential = tokenCredentialFactory); + return this; + } + + public AzureClientsBuilder UseCredential(string name, TokenCredential tokenCredential) + { + return UseCredential(name, _ => tokenCredential); + } + + public AzureClientsBuilder UseCredential(string name, Func tokenCredentialFactory) + { + _serviceCollection.Configure>(name, options => options.CredentialFactory = tokenCredentialFactory); + return this; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsGlobalOptions.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientsGlobalOptions.cs new file mode 100644 index 0000000000000..da6212949573f --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientsGlobalOptions.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Azure.Core.Pipeline; +using Azure.Identity; + +namespace Azure.Core.Extensions +{ + internal class AzureClientsGlobalOptions + { + public Func Credential { get; set; } = _ => new DefaultAzureCredential(); + public List> ConfigureOptions { get; } = new List>(); + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/ClientInformation.cs b/sdk/core/Azure.Core.Extensions/src/ClientInformation.cs index f086e78d327bc..81bc0cf2da0b3 100644 --- a/sdk/core/Azure.Core.Extensions/src/ClientInformation.cs +++ b/sdk/core/Azure.Core.Extensions/src/ClientInformation.cs @@ -10,7 +10,7 @@ internal class ClientRegistration { public string Name { get; } - private readonly Func _factory; + private readonly Func _factory; private readonly object _cacheLock = new object(); @@ -18,13 +18,13 @@ internal class ClientRegistration private ExceptionDispatchInfo _cachedException; - public ClientRegistration(string name, Func factory) + public ClientRegistration(string name, Func factory) { Name = name; _factory = factory; } - public TClient GetClient(TOptions options) + public TClient GetClient(TOptions options, TokenCredential tokenCredential) { _cachedException?.Throw(); @@ -44,7 +44,7 @@ public TClient GetClient(TOptions options) try { - _cachedClient = _factory(options); + _cachedClient = _factory(options, tokenCredential); } catch (Exception e) { diff --git a/sdk/core/Azure.Core.Extensions/src/ConfigurationClientFactory.cs b/sdk/core/Azure.Core.Extensions/src/ConfigurationClientFactory.cs index f648877698c78..b2b246849382c 100644 --- a/sdk/core/Azure.Core.Extensions/src/ConfigurationClientFactory.cs +++ b/sdk/core/Azure.Core.Extensions/src/ConfigurationClientFactory.cs @@ -4,14 +4,16 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Security.Cryptography.X509Certificates; using System.Text; +using Azure.Identity; using Microsoft.Extensions.Configuration; namespace Azure.Core.Extensions { - internal class ConfigurationClientFactory + internal class ClientFactory { - public static object CreateClient(Type clientType, Type optionsType, object options, IConfiguration configuration) + public static object CreateClient(Type clientType, Type optionsType, object options, IConfiguration configuration, TokenCredential credential) { List arguments = new List(); foreach (var constructor in clientType.GetConstructors()) @@ -26,6 +28,12 @@ public static object CreateClient(Type clientType, Type optionsType, object opti bool match = true; foreach (var parameter in constructor.GetParameters()) { + if (IsCredentialParameter(parameter)) + { + arguments.Add(credential); + continue; + } + if (IsOptionsParameter(parameter, optionsType)) { break; @@ -54,6 +62,53 @@ public static object CreateClient(Type clientType, Type optionsType, object opti throw new InvalidOperationException(BuildErrorMessage(clientType, optionsType)); } + internal static TokenCredential CreateCredentials(IConfiguration configuration, IdentityClientOptions identityClientOptions = null) + { + var clientId = configuration["clientId"]; + var tenantId = configuration["tenantId"]; + var clientSecret = configuration["clientSecret"]; + var certificate = configuration["clientCertificate"]; + var certificateStore = configuration["clientCertificateStore"]; + + if (!string.IsNullOrWhiteSpace(tenantId) && + !string.IsNullOrWhiteSpace(clientId) && + !string.IsNullOrWhiteSpace(clientSecret)) + { + return new ClientSecretCredential(tenantId, clientId, clientSecret, identityClientOptions); + } + + if (!string.IsNullOrWhiteSpace(tenantId) && + !string.IsNullOrWhiteSpace(clientId) && + !string.IsNullOrWhiteSpace(certificate)) + { + var storeLocation = string.Equals(certificateStore, "machine", StringComparison.OrdinalIgnoreCase) + ? StoreLocation.LocalMachine + : StoreLocation.CurrentUser;; + + using var store = new X509Store(storeLocation); + store.Open(OpenFlags.ReadOnly); + X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, certificate, false); + + if (certs.Count == 0) + { + throw new InvalidOperationException($"Unable to find a certificate with thumbprint '{certificate}'"); + } + + var credential = new ClientCertificateCredential(tenantId, clientId, certs[0], identityClientOptions); + store.Close(); + + return credential; + } + + // TODO: More logging + return null; + } + + private static bool IsCredentialParameter(ParameterInfo parameter) + { + return parameter.ParameterType == typeof(TokenCredential); + } + private static bool IsOptionsParameter(ParameterInfo parameter, Type optionsType) { return parameter.ParameterType.IsAssignableFrom(optionsType) && diff --git a/sdk/core/Azure.Core.Extensions/src/DefaultClientOptionsSetup.cs b/sdk/core/Azure.Core.Extensions/src/DefaultClientOptionsSetup.cs new file mode 100644 index 0000000000000..69bf0ccf828fc --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/src/DefaultClientOptionsSetup.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Pipeline; +using Microsoft.Extensions.Options; + +namespace Azure.Core.Extensions +{ + internal class DefaultClientOptionsSetup : IConfigureNamedOptions where T : ClientOptions + { + private readonly IOptions _defaultOptions; + private readonly IServiceProvider _serviceProvider; + + public DefaultClientOptionsSetup(IOptions defaultOptions, IServiceProvider serviceProvider) + { + _defaultOptions = defaultOptions; + _serviceProvider = serviceProvider; + } + + public void Configure(T options) + { + foreach (var globalConfigureOption in _defaultOptions.Value.ConfigureOptions) + { + globalConfigureOption(options, _serviceProvider); + } + } + + public void Configure(string name, T options) + { + Configure(options); + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/DefaultCredentialClientOptionsSetup.cs b/sdk/core/Azure.Core.Extensions/src/DefaultCredentialClientOptionsSetup.cs new file mode 100644 index 0000000000000..9ec5a382e49e5 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/src/DefaultCredentialClientOptionsSetup.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Extensions.Options; + +namespace Azure.Core.Extensions +{ + internal class DefaultCredentialClientOptionsSetup : IConfigureNamedOptions> + { + private readonly IOptions _defaultOptions; + + public DefaultCredentialClientOptionsSetup(IOptions defaultOptions) + { + _defaultOptions = defaultOptions; + } + + public void Configure(AzureClientOptions options) + { + if (options.CredentialFactory == null) + { + options.CredentialFactory = _defaultOptions.Value.Credential; + } + } + + public void Configure(string name, AzureClientOptions options) + { + Configure(options); + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/EventSourceLogForwarder.cs b/sdk/core/Azure.Core.Extensions/src/EventSourceLogForwarder.cs index e070224be3ad5..33b8252dd8e89 100644 --- a/sdk/core/Azure.Core.Extensions/src/EventSourceLogForwarder.cs +++ b/sdk/core/Azure.Core.Extensions/src/EventSourceLogForwarder.cs @@ -39,18 +39,13 @@ public EventSourceLogForwarder(ILoggerFactory loggerFactory = null) protected override void OnEventSourceCreated(EventSource eventSource) { - if (_loggerFactory == null) - { - return; - } - base.OnEventSourceCreated(eventSource); if (_filter == null) { _eventSources.Add(eventSource); } - else if (_filter(eventSource)) + else if (_filter(eventSource) && _loggerFactory != null) { var logger = _loggerFactory.CreateLogger(eventSource.Name); _loggers[eventSource.Name] = logger; diff --git a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs index 037ac8b411ead..acc647865e807 100644 --- a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs +++ b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Azure.Identity; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; @@ -179,6 +180,131 @@ public void RetrhowsExceptionFromClientCreation() Assert.AreEqual(exception.Message, "Throwing"); } + [Test] + public void CanSetGlobalOptions() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddAzureClients(builder => { + builder.AddTestClient("Default", "TestClient1"); + builder.AddTestClientWithCredentials("Default", new Uri("http://localhost")); + builder.ConfigureDefaults(options => options.TelemetryPolicy.ApplicationId = "GlobalAppId"); + }); + ServiceProvider provider = serviceCollection.BuildServiceProvider(); + + TestClient testClient = provider.GetService>().CreateClient("Default"); + TestClientWithCredentials testClientWithCredentials = provider.GetService>().CreateClient("Default"); + + Assert.AreEqual("GlobalAppId", testClient.Options.TelemetryPolicy.ApplicationId); + Assert.AreEqual("GlobalAppId", testClientWithCredentials.Options.TelemetryPolicy.ApplicationId); + } + + [Test] + public void CanSetGlobalOptionsUsingConfiguration() + { + var configuration = GetConfiguration(new KeyValuePair("TelemetryPolicy:ApplicationId", "GlobalAppId")); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddAzureClients(builder => { + builder.AddTestClient("Default", "TestClient1"); + builder.AddTestClientWithCredentials("Default", new Uri("http://localhost")); + builder.UseDefaultConfiguration(configuration); + }); + ServiceProvider provider = serviceCollection.BuildServiceProvider(); + + TestClient testClient = provider.GetService>().CreateClient("Default"); + TestClientWithCredentials testClientWithCredentials = provider.GetService>().CreateClient("Default"); + + Assert.AreEqual("GlobalAppId", testClient.Options.TelemetryPolicy.ApplicationId); + Assert.AreEqual("GlobalAppId", testClientWithCredentials.Options.TelemetryPolicy.ApplicationId); + } + + [Test] + public void ResolvesDefaultClientByDefault() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", "Connection string")); + ServiceProvider provider = serviceCollection.BuildServiceProvider(); + var client = provider.GetService(); + + Assert.AreEqual("Connection string", client.ConnectionString); + } + + [Test] + public void UsesProvidedCredentialIfOverGlobal() + { + var serviceCollection = new ServiceCollection(); + var defaultAzureCredential = new ManagedIdentityCredential(); + serviceCollection.AddAzureClients(builder => builder.AddTestClientWithCredentials("Default", new Uri("http://localhost"), defaultAzureCredential)); + + ServiceProvider provider = serviceCollection.BuildServiceProvider(); + TestClientWithCredentials client = provider.GetService(); + + Assert.AreSame(defaultAzureCredential, client.Credential); + } + + [Test] + public void UsesGlobalCredential() + { + var serviceCollection = new ServiceCollection(); + var defaultAzureCredential = new ManagedIdentityCredential(); + serviceCollection.AddAzureClients(builder => builder + .AddTestClientWithCredentials("Default", new Uri("http://localhost")) + .UseDefaultCredential(defaultAzureCredential)); + + ServiceProvider provider = serviceCollection.BuildServiceProvider(); + TestClientWithCredentials client = provider.GetService(); + + Assert.AreSame(defaultAzureCredential, client.Credential); + } + + [Test] + public void UsesCredentialFromGlobalConfiguration() + { + var configuration = GetConfiguration(new KeyValuePair("clientId", "ConfigurationClientId"), + new KeyValuePair("clientSecret", "ConfigurationClientSecret"), + new KeyValuePair("tenantId", "ConfigurationTenantId")); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddAzureClients(builder => builder + .AddTestClientWithCredentials("Default", new Uri("http://localhost")) + .UseDefaultConfiguration(configuration)); + + ServiceProvider provider = serviceCollection.BuildServiceProvider(); + TestClientWithCredentials client = provider.GetService(); + + Assert.IsInstanceOf(client.Credential); + var clientSecretCredential = (ClientSecretCredential)client.Credential; + + Assert.AreEqual("ConfigurationClientId", clientSecretCredential.ClientId); + Assert.AreEqual("ConfigurationClientSecret", clientSecretCredential.ClientSecret); + Assert.AreEqual("ConfigurationTenantId", clientSecretCredential.TenantId); + } + + [Test] + public void UsesCredentialFromConfiguration() + { + var configuration = GetConfiguration( + new KeyValuePair("uri", "http://localhost/"), + new KeyValuePair("clientId", "ConfigurationClientId"), + new KeyValuePair("clientSecret", "ConfigurationClientSecret"), + new KeyValuePair("tenantId", "ConfigurationTenantId")); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddAzureClients(builder => builder + .AddTestClientWithCredentials("Default", configuration)); + + ServiceProvider provider = serviceCollection.BuildServiceProvider(); + TestClientWithCredentials client = provider.GetService(); + + Assert.IsInstanceOf(client.Credential); + var clientSecretCredential = (ClientSecretCredential)client.Credential; + + Assert.AreEqual("http://localhost/", client.Uri.ToString()); + Assert.AreEqual("ConfigurationClientId", clientSecretCredential.ClientId); + Assert.AreEqual("ConfigurationClientSecret", clientSecretCredential.ClientSecret); + Assert.AreEqual("ConfigurationTenantId", clientSecretCredential.TenantId); + } + private IConfiguration GetConfiguration(params KeyValuePair[] items) { return new ConfigurationBuilder().AddInMemoryCollection(items).Build(); diff --git a/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs b/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs index 1ef3bc702c25d..e997d2dae63a0 100644 --- a/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs +++ b/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs @@ -3,21 +3,23 @@ using System; using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using Azure.Identity; using Microsoft.Extensions.Configuration; using NUnit.Framework; namespace Azure.Core.Extensions.Tests { - public class ConfigurationClientFactoryTests + public class ClientFactoryTests { [Test] public void SelectsConstructorBaseOnConfiguration() { IConfiguration configuration = GetConfiguration(new KeyValuePair("connectionstring", "CS")); - var factory = new ConfigurationClientFactory(); + var factory = new ClientFactory(); var clientOptions = new TestClientOptions(); - var client = (TestClient)ConfigurationClientFactory.CreateClient(typeof(TestClient), typeof(TestClientOptions), clientOptions, configuration); + var client = (TestClient)ClientFactory.CreateClient(typeof(TestClient), typeof(TestClientOptions), clientOptions, configuration, null); Assert.AreEqual("CS", client.ConnectionString); Assert.AreSame(clientOptions, client.Options); @@ -28,9 +30,9 @@ public void ConvertsUriConstructorParameters() { IConfiguration configuration = GetConfiguration(new KeyValuePair("uri", "http://localhost")); - var factory = new ConfigurationClientFactory(); + var factory = new ClientFactory(); var clientOptions = new TestClientOptions(); - var client = (TestClient)ConfigurationClientFactory.CreateClient(typeof(TestClient), typeof(TestClientOptions), clientOptions, configuration); + var client = (TestClient)ClientFactory.CreateClient(typeof(TestClient), typeof(TestClientOptions), clientOptions, configuration, null); Assert.AreEqual("http://localhost/", client.Uri.ToString()); Assert.AreSame(clientOptions, client.Options); @@ -42,13 +44,60 @@ public void ThrowsExceptionWithInformationAboutArguments() IConfiguration configuration = GetConfiguration(); var clientOptions = new TestClientOptions(); - var exception = Assert.Throws(() => ConfigurationClientFactory.CreateClient(typeof(TestClient), typeof(TestClientOptions), clientOptions, configuration)); + var exception = Assert.Throws(() => ClientFactory.CreateClient(typeof(TestClient), typeof(TestClientOptions), clientOptions, configuration, null)); Assert.AreEqual("Unable to find matching constructor. Define one of the follow sets of configuration parameters:" + Environment.NewLine + "1. connectionString" + Environment.NewLine + "2. uri" + Environment.NewLine, exception.Message); } + [Theory] + [TestCase("user", StoreLocation.CurrentUser)] + [TestCase("machine", StoreLocation.LocalMachine)] + [TestCase(null, StoreLocation.CurrentUser)] + public void CreatesCertificateCredentials(string storeName, StoreLocation expectedStore) + { + var localCert = new X509Store(expectedStore); + localCert.Open(OpenFlags.ReadOnly); + var someLocalCert = localCert.Certificates[0].Thumbprint; + localCert.Close(); + + IConfiguration configuration = GetConfiguration( + new KeyValuePair("clientId", "ConfigurationClientId"), + new KeyValuePair("clientCertificate", someLocalCert), + new KeyValuePair("clientCertificateStore", storeName), + new KeyValuePair("tenantId", "ConfigurationTenantId") + ); + + var credential = ClientFactory.CreateCredentials(configuration); + + Assert.IsInstanceOf(credential); + var clientCertificateCredential = (ClientCertificateCredential)credential; + + Assert.AreEqual("ConfigurationClientId", clientCertificateCredential.ClientId); + Assert.AreEqual(someLocalCert, clientCertificateCredential.ClientCertificate.Thumbprint); + Assert.AreEqual("ConfigurationTenantId", clientCertificateCredential.TenantId); + } + + [Test] + public void CreatesClientSecretCredentials() + { + IConfiguration configuration = GetConfiguration( + new KeyValuePair("clientId", "ConfigurationClientId"), + new KeyValuePair("clientSecret", "ConfigurationClientSecret"), + new KeyValuePair("tenantId", "ConfigurationTenantId") + ); + + var credential = ClientFactory.CreateCredentials(configuration); + + Assert.IsInstanceOf(credential); + var clientSecretCredential = (ClientSecretCredential)credential; + + Assert.AreEqual("ConfigurationClientId", clientSecretCredential.ClientId); + Assert.AreEqual("ConfigurationClientSecret", clientSecretCredential.ClientSecret); + Assert.AreEqual("ConfigurationTenantId", clientSecretCredential.TenantId); + } + private IConfiguration GetConfiguration(params KeyValuePair[] items) { return new ConfigurationBuilder().AddInMemoryCollection(items).Build(); diff --git a/sdk/core/Azure.Core.Extensions/tests/TestClient.cs b/sdk/core/Azure.Core.Extensions/tests/TestClient.cs index 984c298910db2..db7c6ac3de947 100644 --- a/sdk/core/Azure.Core.Extensions/tests/TestClient.cs +++ b/sdk/core/Azure.Core.Extensions/tests/TestClient.cs @@ -5,6 +5,16 @@ namespace Azure.Core.Extensions.Tests { + internal class TestClientWithCredentials : TestClient + { + public TokenCredential Credential { get; } + + public TestClientWithCredentials(Uri uri, TokenCredential credential, TestClientOptions options) : base(uri, options) + { + Credential = credential; + } + } + internal class TestClient { public Uri Uri { get; } diff --git a/sdk/core/Azure.Core.Extensions/tests/TestClientOptions.cs b/sdk/core/Azure.Core.Extensions/tests/TestClientOptions.cs index b992506bb3b32..8a24e5c271448 100644 --- a/sdk/core/Azure.Core.Extensions/tests/TestClientOptions.cs +++ b/sdk/core/Azure.Core.Extensions/tests/TestClientOptions.cs @@ -1,8 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. + +using Azure.Core.Pipeline; + namespace Azure.Core.Extensions.Tests { - internal class TestClientOptions + internal class TestClientOptions: ClientOptions { public string Property { get; set; } public int IntProperty { get; set; } diff --git a/sdk/core/Azure.Core.Extensions/tests/TestClientWithCredentials.cs b/sdk/core/Azure.Core.Extensions/tests/TestClientWithCredentials.cs new file mode 100644 index 0000000000000..413b355d0ac3d --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/tests/TestClientWithCredentials.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Core.Extensions.Tests +{ + internal class TestClientWithCredentials : TestClient + { + public TokenCredential Credential { get; } + + public TestClientWithCredentials(Uri uri, TokenCredential credential, TestClientOptions options) : base(uri, options) + { + Credential = credential; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs b/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs index 9abd25c4cbb59..c19cd8c1955ef 100644 --- a/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs +++ b/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs @@ -27,5 +27,20 @@ public static TBuilder AddTestClient(this TBuilder bui builder.RegisterClient(name, configuration); return builder; } + + public static TBuilder AddTestClientWithCredentials(this TBuilder builder, string name, TConfiguration configuration) + where TBuilder: IAzureClientsBuilderWithConfiguration + { + builder.RegisterClient(name, configuration); + return builder; + } + + public static TBuilder AddTestClientWithCredentials(this TBuilder builder, string name, Uri uri, TokenCredential tokenCredential = null, Action configureOptions = null) + where TBuilder: IAzureClientsBuilderWithCredential + { + builder.RegisterClient(name, (options, cred) => new TestClientWithCredentials(uri, cred, options), configureOptions, tokenCredential); + return builder; + } + } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/Azure.Core.All.sln b/sdk/core/Azure.Core/Azure.Core.All.sln index a4201ce2863d8..e7de07bb211db 100644 --- a/sdk/core/Azure.Core/Azure.Core.All.sln +++ b/sdk/core/Azure.Core/Azure.Core.All.sln @@ -1,63 +1,67 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28803.462 MinimumVisualStudioVersion = 15.0.26124.0 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.ApplicationModel.Configuration", "..\..\appconfiguration\Azure.ApplicationModel.Configuration\src\Azure.ApplicationModel.Configuration.csproj", "{79FCA629-424A-4E32-A523-8A04DB14C4B5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.ApplicationModel.Configuration", "..\..\appconfiguration\Azure.ApplicationModel.Configuration\src\Azure.ApplicationModel.Configuration.csproj", "{79FCA629-424A-4E32-A523-8A04DB14C4B5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.ApplicationModel.Configuration.Performance", "..\..\appconfiguration\Azure.ApplicationModel.Configuration\tests\Performance\Azure.ApplicationModel.Configuration.Performance.csproj", "{EFE3808B-54A7-4417-8288-389F5065CD87}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.ApplicationModel.Configuration.Performance", "..\..\appconfiguration\Azure.ApplicationModel.Configuration\tests\Performance\Azure.ApplicationModel.Configuration.Performance.csproj", "{EFE3808B-54A7-4417-8288-389F5065CD87}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.ApplicationModel.Configuration.Samples.Tests", "..\..\appconfiguration\Azure.ApplicationModel.Configuration\samples\Azure.ApplicationModel.Configuration.Samples.Tests.csproj", "{729F33CF-8A69-4BD7-85C5-54A64DDDEEA3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.ApplicationModel.Configuration.Samples.Tests", "..\..\appconfiguration\Azure.ApplicationModel.Configuration\samples\Azure.ApplicationModel.Configuration.Samples.Tests.csproj", "{729F33CF-8A69-4BD7-85C5-54A64DDDEEA3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.ApplicationModel.Configuration.Tests", "..\..\appconfiguration\Azure.ApplicationModel.Configuration\tests\Azure.ApplicationModel.Configuration.Tests.csproj", "{E7AB65A7-2FA6-4648-81C5-6176E3302F11}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.ApplicationModel.Configuration.Tests", "..\..\appconfiguration\Azure.ApplicationModel.Configuration\tests\Azure.ApplicationModel.Configuration.Tests.csproj", "{E7AB65A7-2FA6-4648-81C5-6176E3302F11}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core", "src\Azure.Core.csproj", "{CA90A9FA-F955-49DC-A191-6DEE6FA2E493}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core", "src\Azure.Core.csproj", "{CA90A9FA-F955-49DC-A191-6DEE6FA2E493}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core.Extensions", "..\Azure.Core.Extensions\src\Azure.Core.Extensions.csproj", "{F8B2A9A5-1730-4EC6-B2E5-9029F1066D4D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.Extensions", "..\Azure.Core.Extensions\src\Azure.Core.Extensions.csproj", "{F8B2A9A5-1730-4EC6-B2E5-9029F1066D4D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core.Extensions.Tests", "..\Azure.Core.Extensions\tests\Azure.Core.Extensions.Tests.csproj", "{30AAFF15-4204-493D-9E61-407194FF2330}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.Extensions.Tests", "..\Azure.Core.Extensions\tests\Azure.Core.Extensions.Tests.csproj", "{30AAFF15-4204-493D-9E61-407194FF2330}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core.Tests", "tests\Azure.Core.Tests.csproj", "{84491222-6C36-4FA7-BBAE-1FA804129151}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.Tests", "tests\Azure.Core.Tests.csproj", "{84491222-6C36-4FA7-BBAE-1FA804129151}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Identity", "..\..\identity\Azure.Identity\src\Azure.Identity.csproj", "{B6BC0994-65AF-49C3-B6DE-485BAF478A81}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Identity", "..\..\identity\Azure.Identity\src\Azure.Identity.csproj", "{B6BC0994-65AF-49C3-B6DE-485BAF478A81}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Identity.Tests", "..\..\identity\Azure.Identity\tests\Azure.Identity.Tests.csproj", "{8D5CC7C7-A578-4EE7-AE15-49607A8B0DA5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Identity.Tests", "..\..\identity\Azure.Identity\tests\Azure.Identity.Tests.csproj", "{8D5CC7C7-A578-4EE7-AE15-49607A8B0DA5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Messaging.EventHubs", "..\..\eventhub\Azure.Messaging.EventHubs\src\Azure.Messaging.EventHubs.csproj", "{E503DD93-D9FE-4DD1-943F-05F489FE53C8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Messaging.EventHubs", "..\..\eventhub\Azure.Messaging.EventHubs\src\Azure.Messaging.EventHubs.csproj", "{E503DD93-D9FE-4DD1-943F-05F489FE53C8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Messaging.EventHubs.Samples", "..\..\eventhub\Azure.Messaging.EventHubs\samples\Azure.Messaging.EventHubs.Samples.csproj", "{B8EA98EB-3F74-4736-9ABF-47229423C2EF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Messaging.EventHubs.Samples", "..\..\eventhub\Azure.Messaging.EventHubs\samples\Azure.Messaging.EventHubs.Samples.csproj", "{B8EA98EB-3F74-4736-9ABF-47229423C2EF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Messaging.EventHubs.Tests", "..\..\eventhub\Azure.Messaging.EventHubs\tests\Azure.Messaging.EventHubs.Tests.csproj", "{A15C624A-26D0-45DE-8554-C8A6C1B5E78F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Messaging.EventHubs.Tests", "..\..\eventhub\Azure.Messaging.EventHubs\tests\Azure.Messaging.EventHubs.Tests.csproj", "{A15C624A-26D0-45DE-8554-C8A6C1B5E78F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Security.KeyVault.Certificates", "..\..\keyvault\Azure.Security.KeyVault.Certificates\src\Azure.Security.KeyVault.Certificates.csproj", "{5C132576-95B2-464B-B255-157C488023D3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Security.KeyVault.Certificates", "..\..\keyvault\Azure.Security.KeyVault.Certificates\src\Azure.Security.KeyVault.Certificates.csproj", "{5C132576-95B2-464B-B255-157C488023D3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Security.KeyVault.Keys", "..\..\keyvault\Azure.Security.KeyVault.Keys\src\Azure.Security.KeyVault.Keys.csproj", "{4EE7C497-BA39-4AA7-80B5-7170D3017AB4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Security.KeyVault.Keys", "..\..\keyvault\Azure.Security.KeyVault.Keys\src\Azure.Security.KeyVault.Keys.csproj", "{4EE7C497-BA39-4AA7-80B5-7170D3017AB4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Security.KeyVault.Keys.Samples", "..\..\keyvault\Azure.Security.KeyVault.Keys\samples\Azure.Security.KeyVault.Keys.Samples.csproj", "{FBA9C9BF-4493-409E-9DC1-1724A4926F83}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Security.KeyVault.Keys.Samples", "..\..\keyvault\Azure.Security.KeyVault.Keys\samples\Azure.Security.KeyVault.Keys.Samples.csproj", "{FBA9C9BF-4493-409E-9DC1-1724A4926F83}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Security.KeyVault.Keys.Tests", "..\..\keyvault\Azure.Security.KeyVault.Keys\tests\Azure.Security.KeyVault.Keys.Tests.csproj", "{4E7A6C5C-76B5-457C-9227-4C06F037F35F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Security.KeyVault.Keys.Tests", "..\..\keyvault\Azure.Security.KeyVault.Keys\tests\Azure.Security.KeyVault.Keys.Tests.csproj", "{4E7A6C5C-76B5-457C-9227-4C06F037F35F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Security.KeyVault.Secrets", "..\..\keyvault\Azure.Security.KeyVault.Secrets\src\Azure.Security.KeyVault.Secrets.csproj", "{12807134-361A-4CD9-B0AB-D47304961146}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Security.KeyVault.Secrets", "..\..\keyvault\Azure.Security.KeyVault.Secrets\src\Azure.Security.KeyVault.Secrets.csproj", "{12807134-361A-4CD9-B0AB-D47304961146}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Security.KeyVault.Secrets.Samples", "..\..\keyvault\Azure.Security.KeyVault.Secrets\samples\Azure.Security.KeyVault.Secrets.Samples.csproj", "{0C0000AF-01E1-446E-B537-AE83B000977D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Security.KeyVault.Secrets.Samples", "..\..\keyvault\Azure.Security.KeyVault.Secrets\samples\Azure.Security.KeyVault.Secrets.Samples.csproj", "{0C0000AF-01E1-446E-B537-AE83B000977D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Security.KeyVault.Secrets.Tests", "..\..\keyvault\Azure.Security.KeyVault.Secrets\tests\Azure.Security.KeyVault.Secrets.Tests.csproj", "{A802522D-1246-4D91-A2A9-DE98F043F526}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Security.KeyVault.Secrets.Tests", "..\..\keyvault\Azure.Security.KeyVault.Secrets\tests\Azure.Security.KeyVault.Secrets.Tests.csproj", "{A802522D-1246-4D91-A2A9-DE98F043F526}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Storage.Blobs", "..\..\storage\Azure.Storage.Blobs\src\Azure.Storage.Blobs.csproj", "{96D80C1F-8555-4C62-A4E8-54CCF8D902AD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Storage.Blobs", "..\..\storage\Azure.Storage.Blobs\src\Azure.Storage.Blobs.csproj", "{96D80C1F-8555-4C62-A4E8-54CCF8D902AD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Storage.Blobs.Tests", "..\..\storage\Azure.Storage.Blobs\tests\Azure.Storage.Blobs.Tests.csproj", "{87983ABE-928B-48F7-8C96-4CA67E278334}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Storage.Blobs.Tests", "..\..\storage\Azure.Storage.Blobs\tests\Azure.Storage.Blobs.Tests.csproj", "{87983ABE-928B-48F7-8C96-4CA67E278334}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Storage.Common", "..\..\storage\Azure.Storage.Common\src\Azure.Storage.Common.csproj", "{2DD2B13D-726C-47B5-AD0A-23D282DABA62}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Storage.Common", "..\..\storage\Azure.Storage.Common\src\Azure.Storage.Common.csproj", "{2DD2B13D-726C-47B5-AD0A-23D282DABA62}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Storage.Common.Tests", "..\..\storage\Azure.Storage.Common\tests\Azure.Storage.Common.Tests.csproj", "{D76C7E8D-44CE-4BEB-8549-64040E858935}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Storage.Common.Tests", "..\..\storage\Azure.Storage.Common\tests\Azure.Storage.Common.Tests.csproj", "{D76C7E8D-44CE-4BEB-8549-64040E858935}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Storage.Files", "..\..\storage\Azure.Storage.Files\src\Azure.Storage.Files.csproj", "{76B37AE9-B9A5-4152-9C67-CD8867F71537}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Storage.Files", "..\..\storage\Azure.Storage.Files\src\Azure.Storage.Files.csproj", "{76B37AE9-B9A5-4152-9C67-CD8867F71537}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Storage.Files.Tests", "..\..\storage\Azure.Storage.Files\tests\Azure.Storage.Files.Tests.csproj", "{829EE42D-07D5-4AD5-969A-20563A9129C4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Storage.Files.Tests", "..\..\storage\Azure.Storage.Files\tests\Azure.Storage.Files.Tests.csproj", "{829EE42D-07D5-4AD5-969A-20563A9129C4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Storage.Queues", "..\..\storage\Azure.Storage.Queues\src\Azure.Storage.Queues.csproj", "{69B8D748-0443-4D44-82BB-65F09DC0F79F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Storage.Queues", "..\..\storage\Azure.Storage.Queues\src\Azure.Storage.Queues.csproj", "{69B8D748-0443-4D44-82BB-65F09DC0F79F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Storage.Queues.Tests", "..\..\storage\Azure.Storage.Queues\tests\Azure.Storage.Queues.Tests.csproj", "{5FF035D1-F5CC-4CD5-9F4F-E04EE2E65A31}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Storage.Queues.Tests", "..\..\storage\Azure.Storage.Queues\tests\Azure.Storage.Queues.Tests.csproj", "{5FF035D1-F5CC-4CD5-9F4F-E04EE2E65A31}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1BC0D7C7-2E71-4CAA-830C-856E9E2D71A4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.Extensions.Samples", "..\Azure.Core.Extensions\samples\Azure.Core.Extensions.Samples.csproj", "{C772E341-1EC6-451A-BDAB-647B02BF262B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -68,9 +72,6 @@ Global Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {79FCA629-424A-4E32-A523-8A04DB14C4B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {79FCA629-424A-4E32-A523-8A04DB14C4B5}.Debug|Any CPU.Build.0 = Debug|Any CPU @@ -408,5 +409,23 @@ Global {5FF035D1-F5CC-4CD5-9F4F-E04EE2E65A31}.Release|x64.Build.0 = Release|Any CPU {5FF035D1-F5CC-4CD5-9F4F-E04EE2E65A31}.Release|x86.ActiveCfg = Release|Any CPU {5FF035D1-F5CC-4CD5-9F4F-E04EE2E65A31}.Release|x86.Build.0 = Release|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Debug|x64.ActiveCfg = Debug|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Debug|x64.Build.0 = Debug|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Debug|x86.ActiveCfg = Debug|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Debug|x86.Build.0 = Debug|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Release|Any CPU.Build.0 = Release|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Release|x64.ActiveCfg = Release|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Release|x64.Build.0 = Release|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Release|x86.ActiveCfg = Release|Any CPU + {C772E341-1EC6-451A-BDAB-647B02BF262B}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ED6A6A69-8AD2-4DC8-95FB-4FF2162A3BDD} EndGlobalSection EndGlobal diff --git a/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs b/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs index 0adbc3b185863..d3158c9396ccb 100644 --- a/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs +++ b/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs @@ -2,11 +2,17 @@ // Licensed under the MIT License. using System; +using Azure.Core.Pipeline; namespace Azure.Core { public interface IAzureClientsBuilder { - void RegisterClient(string name, Func clientFactory, Action configureOptions) where TOptions : class; + void RegisterClient(string name, Func clientFactory, Action configureOptions) where TOptions : ClientOptions; + } + + public interface IAzureClientsBuilderWithCredential + { + void RegisterClient(string name, Func clientFactory, Action configureOptions, TokenCredential providedCredential) where TOptions : ClientOptions; } } diff --git a/sdk/core/Azure.Core/src/IAzureClientsBuilderWithConfiguration.cs b/sdk/core/Azure.Core/src/IAzureClientsBuilderWithConfiguration.cs index 2c48380a5fcfb..10862071c7010 100644 --- a/sdk/core/Azure.Core/src/IAzureClientsBuilderWithConfiguration.cs +++ b/sdk/core/Azure.Core/src/IAzureClientsBuilderWithConfiguration.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Azure.Core.Pipeline; + namespace Azure.Core { public interface IAzureClientsBuilderWithConfiguration: IAzureClientsBuilder { - void RegisterClient(string name, TConfiguration configuration) where TOptions : class; + void RegisterClient(string name, TConfiguration configuration) where TOptions : ClientOptions; } } diff --git a/sdk/core/Azure.Core/src/IAzureClientsBuilderWithCredential.cs b/sdk/core/Azure.Core/src/IAzureClientsBuilderWithCredential.cs new file mode 100644 index 0000000000000..1bdc5b845a6e3 --- /dev/null +++ b/sdk/core/Azure.Core/src/IAzureClientsBuilderWithCredential.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Pipeline; + +namespace Azure.Core +{ + public interface IAzureClientsBuilderWithCredential + { + void RegisterClient(string name, Func clientFactory, Action configureOptions, TokenCredential providedCredential) where TOptions : ClientOptions; + } +} diff --git a/sdk/identity/Azure.Identity/src/Azure.Identity.csproj b/sdk/identity/Azure.Identity/src/Azure.Identity.csproj index 98b6502a864d0..7fc298e144738 100644 --- a/sdk/identity/Azure.Identity/src/Azure.Identity.csproj +++ b/sdk/identity/Azure.Identity/src/Azure.Identity.csproj @@ -14,6 +14,7 @@ $(NoWarn);3021 true false + true @@ -25,7 +26,7 @@ - + \ No newline at end of file diff --git a/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs b/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs index 1733baeea2797..4601290827aea 100644 --- a/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs +++ b/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs @@ -17,10 +17,11 @@ namespace Azure.Identity /// public class ClientCertificateCredential : TokenCredential { - private string _tenantId; - private string _clientId; - private X509Certificate2 _clientCertificate; - private AadIdentityClient _client; + public string TenantId { get; } + public string ClientId { get; } + public X509Certificate2 ClientCertificate { get; } + + private readonly AadIdentityClient _client; /// /// Creates an instance of the ClientCertificateCredential with the details needed to authenticate against Azure Active Directory with the specified certificate. @@ -42,11 +43,11 @@ public ClientCertificateCredential(string tenantId, string clientId, X509Certifi /// Options that allow to configure the management of the requests sent to the Azure Active Directory service. public ClientCertificateCredential(string tenantId, string clientId, X509Certificate2 clientCertificate, IdentityClientOptions options) { - _tenantId = tenantId ?? throw new ArgumentNullException(nameof(tenantId)); + TenantId = tenantId ?? throw new ArgumentNullException(nameof(tenantId)); - _clientId = clientId ?? throw new ArgumentNullException(nameof(clientId)); + ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId)); - _clientCertificate = clientCertificate ?? throw new ArgumentNullException(nameof(clientCertificate)); + ClientCertificate = clientCertificate ?? throw new ArgumentNullException(nameof(clientCertificate)); _client = (options != null) ? new AadIdentityClient(options) : AadIdentityClient.SharedClient; } @@ -59,7 +60,7 @@ public ClientCertificateCredential(string tenantId, string clientId, X509Certifi /// An which can be used to authenticate service client calls. public override AccessToken GetToken(string[] scopes, CancellationToken cancellationToken = default) { - return _client.Authenticate(_tenantId, _clientId, _clientCertificate, scopes, cancellationToken); + return _client.Authenticate(TenantId, ClientId, ClientCertificate, scopes, cancellationToken); } /// @@ -70,7 +71,7 @@ public override AccessToken GetToken(string[] scopes, CancellationToken cancella /// An which can be used to authenticate service client calls. public override async Task GetTokenAsync(string[] scopes, CancellationToken cancellationToken = default) { - return await _client.AuthenticateAsync(_tenantId, _clientId, _clientCertificate, scopes, cancellationToken).ConfigureAwait(false); + return await _client.AuthenticateAsync(TenantId, ClientId, ClientCertificate, scopes, cancellationToken).ConfigureAwait(false); } } } diff --git a/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs b/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs index 2b4beb640d3f5..86041c4da2287 100644 --- a/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs +++ b/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs @@ -10,16 +10,18 @@ namespace Azure.Identity { /// /// Enables authentication to Azure Active Directory using a client secret that was generated for an App Registration. More information on how - /// to configure a client secret can be found here: + /// to configure a client secret can be found here: /// https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application /// public class ClientSecretCredential : TokenCredential { - private string _tenantId; - private string _clientId; - private string _clientSecret; - private AadIdentityClient _client; + private readonly AadIdentityClient _client; + public string TenantId { get; } + + public string ClientId { get; } + + public string ClientSecret { get; } /// /// Creates an instance of the ClientSecretCredential with the details needed to authenticate against Azure Active Directory with a client secret. @@ -41,9 +43,9 @@ public ClientSecretCredential(string tenantId, string clientId, string clientSec /// Options that allow to configure the management of the requests sent to the Azure Active Directory service. public ClientSecretCredential(string tenantId, string clientId, string clientSecret, IdentityClientOptions options) { - _tenantId = tenantId; - _clientId = clientId; - _clientSecret = clientSecret; + TenantId = tenantId; + ClientId = clientId; + ClientSecret = clientSecret; _client = (options != null) ? new AadIdentityClient(options) : AadIdentityClient.SharedClient; } @@ -56,7 +58,7 @@ public ClientSecretCredential(string tenantId, string clientId, string clientSec /// An which can be used to authenticate service client calls. public override async Task GetTokenAsync(string[] scopes, CancellationToken cancellationToken = default) { - return await this._client.AuthenticateAsync(_tenantId, _clientId, _clientSecret, scopes, cancellationToken).ConfigureAwait(false); + return await this._client.AuthenticateAsync(TenantId, ClientId, ClientSecret, scopes, cancellationToken).ConfigureAwait(false); } /// @@ -67,7 +69,7 @@ public override async Task GetTokenAsync(string[] scopes, Cancellat /// An which can be used to authenticate service client calls. public override AccessToken GetToken(string[] scopes, CancellationToken cancellationToken = default) { - return this._client.Authenticate(_tenantId, _clientId, _clientSecret, scopes, cancellationToken); + return this._client.Authenticate(TenantId, ClientId, ClientSecret, scopes, cancellationToken); } } } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj index 8e6542ef5b984..26e1bab2d3359 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj @@ -12,11 +12,12 @@ $(RequiredTargetFrameworks) $(NoWarn);3021 true + true - + diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/KeyVaultAzureClientBuilderExtensions.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/KeyVaultAzureClientBuilderExtensions.cs new file mode 100644 index 0000000000000..c71163db84a64 --- /dev/null +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/KeyVaultAzureClientBuilderExtensions.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core; +using Azure.Security.KeyVault.Secrets; + +namespace Azure.ApplicationModel.Configuration +{ + public static class KeyVaultAzureClientBuilderExtensions + { + public static TBuilder AddKeyVaultSecrets(this TBuilder builder, + string name, + Uri vaultUri, + TokenCredential tokenCredential = null, + Action configureOptions = null) + where TBuilder: IAzureClientsBuilderWithCredential + { + builder.RegisterClient(name, (options, cred) => new SecretClient(vaultUri, tokenCredential, options), configureOptions, tokenCredential); + return builder; + } + + public static TBuilder AddKeyVaultSecrets(this TBuilder builder, string name, TConfiguration configuration) + where TBuilder: IAzureClientsBuilderWithConfiguration + { + builder.RegisterClient(name, configuration); + return builder; + } + } +} From 9326eee5513c11c09c9e574b91a7f204ba7818f6 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 2 Jul 2019 15:53:03 -0700 Subject: [PATCH 02/17] Ctrl+s --- sdk/core/Azure.Core.Extensions/tests/TestClient.cs | 10 ---------- sdk/core/Azure.Core/src/IAzureClientsBuilder.cs | 5 ----- 2 files changed, 15 deletions(-) diff --git a/sdk/core/Azure.Core.Extensions/tests/TestClient.cs b/sdk/core/Azure.Core.Extensions/tests/TestClient.cs index db7c6ac3de947..984c298910db2 100644 --- a/sdk/core/Azure.Core.Extensions/tests/TestClient.cs +++ b/sdk/core/Azure.Core.Extensions/tests/TestClient.cs @@ -5,16 +5,6 @@ namespace Azure.Core.Extensions.Tests { - internal class TestClientWithCredentials : TestClient - { - public TokenCredential Credential { get; } - - public TestClientWithCredentials(Uri uri, TokenCredential credential, TestClientOptions options) : base(uri, options) - { - Credential = credential; - } - } - internal class TestClient { public Uri Uri { get; } diff --git a/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs b/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs index d3158c9396ccb..f231209038c63 100644 --- a/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs +++ b/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs @@ -10,9 +10,4 @@ public interface IAzureClientsBuilder { void RegisterClient(string name, Func clientFactory, Action configureOptions) where TOptions : ClientOptions; } - - public interface IAzureClientsBuilderWithCredential - { - void RegisterClient(string name, Func clientFactory, Action configureOptions, TokenCredential providedCredential) where TOptions : ClientOptions; - } } From 7935f6045052de9badc85c0a0f9d77bc858155cc Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 3 Jul 2019 09:24:03 -0700 Subject: [PATCH 03/17] Some feedback --- sdk/core/Azure.Core.Extensions/samples/Startup.cs | 10 +++++++++- .../Azure.Core.Extensions/samples/appsettings.json | 1 + .../Azure.Core.Extensions/src/AzureClientsBuilder.cs | 8 ++++---- .../tests/AzureClientFactoryTests.cs | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index 6f873084e1f31..dd045bc7dbd7a 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -32,12 +32,20 @@ public void ConfigureServices(IServiceCollection services) services.AddAzureClients(builder => { builder.AddKeyVaultSecrets("Default", Configuration.GetSection("KeyVault")); + builder.AddKeyVaultSecrets("SomeClient", new Uri("http://my.keyvault.com")); + + builder.UseCredential(new DefaultAzureCredential()); + builder.UseCredential("Default", new ChainedTokenCredential()); + // This would use configuration for auth and client settings builder.UseDefaultConfiguration(Configuration.GetSection("Default")); // Configure global defaults - builder.ConfigureDefaults((options, provider) => options.AddPolicy(HttpPipelinePosition.PerCall, provider.GetService())); + builder.ConfigureDefaults(options => options.RetryPolicy.Mode = RetryMode.Exponential); + + // Advanced configure global defaults + builder.ConfigureDefaults((options, provider) => options.AddPolicy(HttpPipelinePosition.PerCall, provider.GetService())); // Configure default credential // builder.UseDefaultCredential(new ClientSecretCredential("tenantId","clientId","clientSecret")); diff --git a/sdk/core/Azure.Core.Extensions/samples/appsettings.json b/sdk/core/Azure.Core.Extensions/samples/appsettings.json index f382ea8b545b3..f1860fdd610b0 100644 --- a/sdk/core/Azure.Core.Extensions/samples/appsettings.json +++ b/sdk/core/Azure.Core.Extensions/samples/appsettings.json @@ -9,6 +9,7 @@ "ClientId": "", "ClientSecret": "", "TenantId": "", + "TelemetryPolicy": { "ApplicationId": "AppId" } diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs index b97d787f0e253..416f857fdd74a 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs @@ -62,7 +62,7 @@ public AzureClientsBuilder UseDefaultConfiguration(IConfiguration configuration) if (credentialsFromConfig != null) { - UseDefaultCredential(credentialsFromConfig); + UseCredential(credentialsFromConfig); } return this; @@ -91,12 +91,12 @@ void IAzureClientsBuilderWithCredential.RegisterClient(string } - public AzureClientsBuilder UseDefaultCredential(TokenCredential tokenCredential) + public AzureClientsBuilder UseCredential(TokenCredential tokenCredential) { - return UseDefaultCredential(_ => tokenCredential); + return UseCredential(_ => tokenCredential); } - public AzureClientsBuilder UseDefaultCredential(Func tokenCredentialFactory) + public AzureClientsBuilder UseCredential(Func tokenCredentialFactory) { _serviceCollection.Configure(options => options.Credential = tokenCredentialFactory); return this; diff --git a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs index acc647865e807..6f05c264b9c94 100644 --- a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs +++ b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs @@ -249,7 +249,7 @@ public void UsesGlobalCredential() var defaultAzureCredential = new ManagedIdentityCredential(); serviceCollection.AddAzureClients(builder => builder .AddTestClientWithCredentials("Default", new Uri("http://localhost")) - .UseDefaultCredential(defaultAzureCredential)); + .UseCredential(defaultAzureCredential)); ServiceProvider provider = serviceCollection.BuildServiceProvider(); TestClientWithCredentials client = provider.GetService(); From 7bb6bc04cdb2efea52ff0c460689956777612361 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 3 Jul 2019 12:42:31 -0700 Subject: [PATCH 04/17] Fluent --- ...nfigurationAzureClientBuilderExtensions.cs | 28 ---------- ...zure.ApplicationModel.Configuration.csproj | 1 + .../ConfigurationClientBuilderExtensions.cs | 22 ++++++++ .../Azure.Core.Extensions/samples/Startup.cs | 11 ++-- .../src/AzureClientBuilderExtensions.cs | 53 ++++++++++++++++++ .../src/AzureClientsBuilder.cs | 49 +++++------------ .../src/Internal/AzureClientBuilder.cs | 19 +++++++ .../src/{ => Internal}/AzureClientFactory.cs | 4 +- .../src/{ => Internal}/AzureClientOptions.cs | 2 +- .../AzureClientServiceCollectionExtensions.cs | 0 .../AzureClientsGlobalOptions.cs | 0 .../src/{ => Internal}/ClientInformation.cs | 2 +- .../ConfigurationClientFactory.cs | 0 .../Internal/ConfigureClientCredentials.cs | 34 ++++++++++++ .../src/Internal/ConfigureClientOptions.cs | 36 ++++++++++++ .../DefaultClientOptionsSetup.cs | 0 .../DefaultCredentialClientOptionsSetup.cs | 6 +- .../{ => Internal}/EventSourceLogForwarder.cs | 0 .../tests/AzureClientFactoryTests.cs | 55 ++++++++++--------- .../tests/TestClientsBuilderExtensions.cs | 25 ++++----- .../src/Extensions/IAzureClientBuilder.cs | 11 ++++ .../{ => Extensions}/IAzureClientsBuilder.cs | 4 +- .../IAzureClientsBuilderWithConfiguration.cs | 5 +- .../IAzureClientsBuilderWithCredential.cs | 13 +++++ .../src/IAzureClientsBuilderWithCredential.cs | 13 ----- .../KeyVaultAzureClientBuilderExtensions.cs | 30 ---------- .../src/SecretClientBuilderExtensions.cs | 23 ++++++++ 27 files changed, 283 insertions(+), 163 deletions(-) delete mode 100644 sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AppConfigurationAzureClientBuilderExtensions.cs create mode 100644 sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs create mode 100644 sdk/core/Azure.Core.Extensions/src/AzureClientBuilderExtensions.cs create mode 100644 sdk/core/Azure.Core.Extensions/src/Internal/AzureClientBuilder.cs rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/AzureClientFactory.cs (90%) rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/AzureClientOptions.cs (81%) rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/AzureClientServiceCollectionExtensions.cs (100%) rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/AzureClientsGlobalOptions.cs (100%) rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/ClientInformation.cs (97%) rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/ConfigurationClientFactory.cs (100%) create mode 100644 sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientCredentials.cs create mode 100644 sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientOptions.cs rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/DefaultClientOptionsSetup.cs (100%) rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/DefaultCredentialClientOptionsSetup.cs (77%) rename sdk/core/Azure.Core.Extensions/src/{ => Internal}/EventSourceLogForwarder.cs (100%) create mode 100644 sdk/core/Azure.Core/src/Extensions/IAzureClientBuilder.cs rename sdk/core/Azure.Core/src/{ => Extensions}/IAzureClientsBuilder.cs (51%) rename sdk/core/Azure.Core/src/{ => Extensions}/IAzureClientsBuilderWithConfiguration.cs (58%) create mode 100644 sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithCredential.cs delete mode 100644 sdk/core/Azure.Core/src/IAzureClientsBuilderWithCredential.cs delete mode 100644 sdk/keyvault/Azure.Security.KeyVault.Secrets/src/KeyVaultAzureClientBuilderExtensions.cs create mode 100644 sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AppConfigurationAzureClientBuilderExtensions.cs b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AppConfigurationAzureClientBuilderExtensions.cs deleted file mode 100644 index ba10e74618180..0000000000000 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AppConfigurationAzureClientBuilderExtensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Azure.Core; - -namespace Azure.ApplicationModel.Configuration -{ - public static class AppConfigurationAzureClientBuilderExtensions - { - public static TBuilder AddAppConfiguration(this TBuilder builder, - string name, - string connectionString, - Action configureOptions = null) - where TBuilder: IAzureClientsBuilder - { - builder.RegisterClient(name, options => new ConfigurationClient(connectionString, options), configureOptions); - return builder; - } - - public static TBuilder AddAppConfiguration(this TBuilder builder, string name, TConfiguration configuration) - where TBuilder: IAzureClientsBuilderWithConfiguration - { - builder.RegisterClient(name, configuration); - return builder; - } - } -} diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj index 92019df4b546f..ee45c821f7125 100644 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj @@ -13,6 +13,7 @@ $(RequiredTargetFrameworks) $(NoWarn);3021 true + true diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs new file mode 100644 index 0000000000000..f0ec4e41aec73 --- /dev/null +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Extensions; + +namespace Azure.ApplicationModel.Configuration +{ + public static class ConfigurationClientBuilderExtensions + { + public static IAzureClientBuilder AddAppConfiguration(this TBuilder builder, string connectionString) + where TBuilder: IAzureClientsBuilder + { + return builder.RegisterClient(options => new ConfigurationClient(connectionString, options)); + } + + public static IAzureClientBuilder AddAppConfiguration(this TBuilder builder, TConfiguration configuration) + where TBuilder: IAzureClientsBuilderWithConfiguration + { + return builder.RegisterClient(configuration); + } + } +} diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index dd045bc7dbd7a..2acc92f784041 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -31,12 +31,15 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddAzureClients(builder => { - builder.AddKeyVaultSecrets("Default", Configuration.GetSection("KeyVault")); - builder.AddKeyVaultSecrets("SomeClient", new Uri("http://my.keyvault.com")); - builder.UseCredential(new DefaultAzureCredential()); - builder.UseCredential("Default", new ChainedTokenCredential()); + builder.AddKeyVaultSecrets(Configuration.GetSection("KeyVault")) + .WithName("Default") + .WithCredential(new DefaultAzureCredential()) + .ConfigureOptions(options => options.RetryPolicy.MaxRetries = 10); + + builder.AddKeyVaultSecrets(new Uri("http://my.keyvault.com")); + builder.UseCredential(new DefaultAzureCredential()); // This would use configuration for auth and client settings builder.UseDefaultConfiguration(Configuration.GetSection("Default")); diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientBuilderExtensions.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientBuilderExtensions.cs new file mode 100644 index 0000000000000..20d91846b6029 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientBuilderExtensions.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Azure.Core.Extensions +{ + public static class AzureClientBuilderExtensions + { + public static IAzureClientBuilder WithName(this IAzureClientBuilder builder, string name) where TOptions : class + { + builder.ToBuilderImpl().Registration.Name = name; + return builder; + } + + public static IAzureClientBuilder WithCredential(this IAzureClientBuilder builder, TokenCredential credential) where TOptions : class + { + return builder.WithCredential(_ => credential); + } + + public static IAzureClientBuilder WithCredential(this IAzureClientBuilder builder, Func credentialFactory) where TOptions : class + { + var impl = builder.ToBuilderImpl(); + impl.ServiceCollection.AddSingleton>>(new ConfigureClientCredentials(impl.Registration, credentialFactory)); + return builder; + } + + public static IAzureClientBuilder ConfigureOptions(this IAzureClientBuilder builder, Action configureOptions) where TOptions : class + { + return builder.ConfigureOptions((options, _) => configureOptions(options)); + } + + public static IAzureClientBuilder ConfigureOptions(this IAzureClientBuilder builder, IConfiguration configuration) where TOptions : class + { + return builder.ConfigureOptions(options => configuration.Bind(options)); + } + + public static IAzureClientBuilder ConfigureOptions(this IAzureClientBuilder builder, Action configureOptions) where TOptions : class + { + var impl = builder.ToBuilderImpl(); + impl.ServiceCollection.AddSingleton>(provider => new ConfigureClientOptions(provider, impl.Registration, configureOptions));; + return builder; + } + + private static AzureClientBuilder ToBuilderImpl(this IAzureClientBuilder builder) where TOptions : class + { + return (AzureClientBuilder)builder; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs index 416f857fdd74a..9cae314fd69d4 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs @@ -14,7 +14,7 @@ public sealed class AzureClientsBuilder : IAzureClientsBuilderWithConfiguration< { private readonly IServiceCollection _serviceCollection; - private const string DefaultClientName = "Default"; + internal const string DefaultClientName = "Default"; internal AzureClientsBuilder(IServiceCollection serviceCollection) { @@ -23,22 +23,17 @@ internal AzureClientsBuilder(IServiceCollection serviceCollection) _serviceCollection.TryAddSingleton(); } - void IAzureClientsBuilder.RegisterClient(string name, Func clientFactory, Action configureOptions) + IAzureClientBuilder IAzureClientsBuilder.RegisterClient(Func clientFactory) { - ((IAzureClientsBuilderWithCredential)this).RegisterClient( - name, - (options, _) => clientFactory(options), - configureOptions, - null); + return ((IAzureClientsBuilderWithCredential)this).RegisterClient((options, _) => clientFactory(options)); } - void IAzureClientsBuilderWithConfiguration.RegisterClient(string name, IConfiguration configuration) + IAzureClientBuilder IAzureClientsBuilderWithConfiguration.RegisterClient(IConfiguration configuration) { - ((IAzureClientsBuilderWithCredential)this).RegisterClient( - name, - (options, credentials) => (TClient)ClientFactory.CreateClient(typeof(TClient), typeof(TOptions), options, configuration, credentials), - options => configuration.Bind(options), - ClientFactory.CreateCredentials(configuration)); + return ((IAzureClientsBuilderWithCredential)this).RegisterClient( + (options, credentials) => (TClient)ClientFactory.CreateClient(typeof(TClient), typeof(TOptions), options, configuration, credentials)) + .ConfigureOptions(configuration) + .WithCredential(ClientFactory.CreateCredentials(configuration)); } public AzureClientsBuilder ConfigureDefaults(Action configureOptions) @@ -68,26 +63,19 @@ public AzureClientsBuilder UseDefaultConfiguration(IConfiguration configuration) return this; } - void IAzureClientsBuilderWithCredential.RegisterClient(string name, Func clientFactory, Action configureOptions, TokenCredential providedCredential) + IAzureClientBuilder IAzureClientsBuilderWithCredential.RegisterClient(Func clientFactory) { - _serviceCollection.AddSingleton(new ClientRegistration(name, clientFactory)); + var clientRegistration = new ClientRegistration(DefaultClientName, clientFactory); + _serviceCollection.AddSingleton(clientRegistration); - _serviceCollection.TryAddSingleton(typeof(IConfigureOptions>), typeof(DefaultCredentialClientOptionsSetup)); + _serviceCollection.TryAddSingleton(typeof(IConfigureOptions>), typeof(DefaultCredentialClientOptionsSetup)); _serviceCollection.TryAddSingleton(typeof(IConfigureOptions), typeof(DefaultClientOptionsSetup)); _serviceCollection.TryAddSingleton(typeof(IAzureClientFactory), typeof(AzureClientFactory)); _serviceCollection.TryAddSingleton( typeof(TClient), provider => provider.GetService>().CreateClient(DefaultClientName)); - if (configureOptions != null) - { - _serviceCollection.Configure(name, configureOptions); - } - - if (providedCredential != null) - { - UseCredential(name, providedCredential); - } + return new AzureClientBuilder(clientRegistration, _serviceCollection); } @@ -101,16 +89,5 @@ public AzureClientsBuilder UseCredential(Func _serviceCollection.Configure(options => options.Credential = tokenCredentialFactory); return this; } - - public AzureClientsBuilder UseCredential(string name, TokenCredential tokenCredential) - { - return UseCredential(name, _ => tokenCredential); - } - - public AzureClientsBuilder UseCredential(string name, Func tokenCredentialFactory) - { - _serviceCollection.Configure>(name, options => options.CredentialFactory = tokenCredentialFactory); - return this; - } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientBuilder.cs b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientBuilder.cs new file mode 100644 index 0000000000000..0608d8c7dbabf --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientBuilder.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Extensions.DependencyInjection; + +namespace Azure.Core.Extensions +{ + internal sealed class AzureClientBuilder: IAzureClientBuilder where TOptions : class + { + public ClientRegistration Registration { get; } + public IServiceCollection ServiceCollection { get; } + + internal AzureClientBuilder(ClientRegistration clientRegistration, IServiceCollection serviceCollection) + { + Registration = clientRegistration; + ServiceCollection = serviceCollection; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientFactory.cs b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientFactory.cs similarity index 90% rename from sdk/core/Azure.Core.Extensions/src/AzureClientFactory.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/AzureClientFactory.cs index 22b9c1c38666e..63ae6845a34d9 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientFactory.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientFactory.cs @@ -13,7 +13,7 @@ internal class AzureClientFactory: IAzureClientFactory> _clientsOptions; + private readonly IOptionsMonitor> _clientsOptions; private readonly IOptionsMonitor _monitor; @@ -21,7 +21,7 @@ internal class AzureClientFactory: IAzureClientFactory> clientsOptions, + IOptionsMonitor> clientsOptions, IEnumerable> clientRegistrations, IOptionsMonitor monitor, EventSourceLogForwarder logForwarder) { diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientOptions.cs b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientOptions.cs similarity index 81% rename from sdk/core/Azure.Core.Extensions/src/AzureClientOptions.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/AzureClientOptions.cs index 471d25ced1ae2..e844e5a81ac9e 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientOptions.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientOptions.cs @@ -5,7 +5,7 @@ namespace Azure.Core.Extensions { - internal class AzureClientOptions + internal class AzureClientCredentialOptions { public Func CredentialFactory { get; set; } } diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientServiceCollectionExtensions.cs b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientServiceCollectionExtensions.cs similarity index 100% rename from sdk/core/Azure.Core.Extensions/src/AzureClientServiceCollectionExtensions.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/AzureClientServiceCollectionExtensions.cs diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsGlobalOptions.cs b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientsGlobalOptions.cs similarity index 100% rename from sdk/core/Azure.Core.Extensions/src/AzureClientsGlobalOptions.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/AzureClientsGlobalOptions.cs diff --git a/sdk/core/Azure.Core.Extensions/src/ClientInformation.cs b/sdk/core/Azure.Core.Extensions/src/Internal/ClientInformation.cs similarity index 97% rename from sdk/core/Azure.Core.Extensions/src/ClientInformation.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/ClientInformation.cs index 81bc0cf2da0b3..e898c737d6ef7 100644 --- a/sdk/core/Azure.Core.Extensions/src/ClientInformation.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/ClientInformation.cs @@ -8,7 +8,7 @@ namespace Azure.Core.Extensions { internal class ClientRegistration { - public string Name { get; } + public string Name { get; set; } private readonly Func _factory; diff --git a/sdk/core/Azure.Core.Extensions/src/ConfigurationClientFactory.cs b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs similarity index 100% rename from sdk/core/Azure.Core.Extensions/src/ConfigurationClientFactory.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientCredentials.cs b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientCredentials.cs new file mode 100644 index 0000000000000..88293b31b802c --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientCredentials.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Extensions.Options; + +namespace Azure.Core.Extensions +{ + internal class ConfigureClientCredentials : IConfigureNamedOptions> + { + private readonly ClientRegistration _registration; + private readonly Func _credentialFactory; + + public ConfigureClientCredentials( + ClientRegistration registration, + Func credentialFactory) + { + _registration = registration; + _credentialFactory = credentialFactory; + } + + public void Configure(AzureClientCredentialOptions options) + { + } + + public void Configure(string name, AzureClientCredentialOptions options) + { + if (name == _registration.Name) + { + options.CredentialFactory = _credentialFactory; + } + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientOptions.cs b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientOptions.cs new file mode 100644 index 0000000000000..446f1edc52199 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientOptions.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Extensions.Options; + +namespace Azure.Core.Extensions +{ + internal class ConfigureClientOptions : IConfigureNamedOptions where TOptions : class + { + private readonly IServiceProvider _serviceProvider; + private readonly ClientRegistration _registration; + private readonly Action _configureOptions; + + public ConfigureClientOptions( + IServiceProvider serviceProvider, + ClientRegistration registration, Action configureOptions) + { + _serviceProvider = serviceProvider; + _registration = registration; + _configureOptions = configureOptions; + } + + public void Configure(TOptions options) + { + } + + public void Configure(string name, TOptions options) + { + if (name == _registration.Name) + { + _configureOptions(options, _serviceProvider); + } + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/DefaultClientOptionsSetup.cs b/sdk/core/Azure.Core.Extensions/src/Internal/DefaultClientOptionsSetup.cs similarity index 100% rename from sdk/core/Azure.Core.Extensions/src/DefaultClientOptionsSetup.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/DefaultClientOptionsSetup.cs diff --git a/sdk/core/Azure.Core.Extensions/src/DefaultCredentialClientOptionsSetup.cs b/sdk/core/Azure.Core.Extensions/src/Internal/DefaultCredentialClientOptionsSetup.cs similarity index 77% rename from sdk/core/Azure.Core.Extensions/src/DefaultCredentialClientOptionsSetup.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/DefaultCredentialClientOptionsSetup.cs index 9ec5a382e49e5..cd7508e79201d 100644 --- a/sdk/core/Azure.Core.Extensions/src/DefaultCredentialClientOptionsSetup.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/DefaultCredentialClientOptionsSetup.cs @@ -5,7 +5,7 @@ namespace Azure.Core.Extensions { - internal class DefaultCredentialClientOptionsSetup : IConfigureNamedOptions> + internal class DefaultCredentialClientOptionsSetup : IConfigureNamedOptions> { private readonly IOptions _defaultOptions; @@ -14,7 +14,7 @@ public DefaultCredentialClientOptionsSetup(IOptions d _defaultOptions = defaultOptions; } - public void Configure(AzureClientOptions options) + public void Configure(AzureClientCredentialOptions options) { if (options.CredentialFactory == null) { @@ -22,7 +22,7 @@ public void Configure(AzureClientOptions options) } } - public void Configure(string name, AzureClientOptions options) + public void Configure(string name, AzureClientCredentialOptions options) { Configure(options); } diff --git a/sdk/core/Azure.Core.Extensions/src/EventSourceLogForwarder.cs b/sdk/core/Azure.Core.Extensions/src/Internal/EventSourceLogForwarder.cs similarity index 100% rename from sdk/core/Azure.Core.Extensions/src/EventSourceLogForwarder.cs rename to sdk/core/Azure.Core.Extensions/src/Internal/EventSourceLogForwarder.cs diff --git a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs index 6f05c264b9c94..5c6855d7c68dd 100644 --- a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs +++ b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs @@ -16,7 +16,7 @@ public class AzureClientFactoryTests public void AllowsResolvingFactoryAndCreatingClientInstance() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", new Uri("http://localhost/"))); + serviceCollection.AddAzureClients(builder => builder.AddTestClient(new Uri("http://localhost/"))); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -31,7 +31,7 @@ public void AllowsResolvingFactoryAndCreatingClientInstance() public void ReturnsSameInstanceWhenResolvedMultipleTimes() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", new Uri("http://localhost/"))); + serviceCollection.AddAzureClients(builder => builder.AddTestClient(new Uri("http://localhost/"))); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -47,7 +47,7 @@ public void ExecutesConfigurationDelegateOnOptions() { var serviceCollection = new ServiceCollection(); serviceCollection.AddAzureClients(builder => - builder.AddTestClient("Default", new Uri("http://localhost/"), options => options.Property = "Value")); + builder.AddTestClient(new Uri("http://localhost/")).ConfigureOptions(options => options.Property = "Value")); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -62,7 +62,7 @@ public void ExecutesConfigurationDelegateOnOptions() public void ExecutesConfigureDelegateOnOptions() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", new Uri("http://localhost/"))); + serviceCollection.AddAzureClients(builder => builder.AddTestClient(new Uri("http://localhost/"))); serviceCollection.Configure("Default", options => options.Property = "Value"); ServiceProvider provider = serviceCollection.BuildServiceProvider(); @@ -78,8 +78,8 @@ public void ExecutesConfigureDelegateOnOptions() public void SubsequentRegistrationOverrides() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", new Uri("http://localhost/"))); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", new Uri("http://otherhost/"))); + serviceCollection.AddAzureClients(builder => builder.AddTestClient(new Uri("http://localhost/"))); + serviceCollection.AddAzureClients(builder => builder.AddTestClient(new Uri("http://otherhost/"))); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -93,9 +93,10 @@ public void SubsequentRegistrationOverrides() public void CanRegisterMultipleClients() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder - .AddTestClient("Default", new Uri("http://localhost/"), options => options.Property = "Value1") - .AddTestClient("OtherClient", new Uri("http://otherhost/"), options => options.Property = "Value2")); + serviceCollection.AddAzureClients(builder => { + builder.AddTestClient(new Uri("http://localhost/")).ConfigureOptions(options => options.Property = "Value1"); + builder.AddTestClient(new Uri("http://otherhost/")).WithName("OtherClient").ConfigureOptions(options => options.Property = "Value2"); + }); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -117,7 +118,7 @@ public void CanCreateClientFromConfiguration() { var configuration = GetConfiguration(new KeyValuePair("uri", "http://localhost/")); var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", configuration)); + serviceCollection.AddAzureClients(builder => builder.AddTestClient(configuration)); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -139,7 +140,7 @@ public void SetsOptionsPropertiesFromConfiguration() ); var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", configuration)); + serviceCollection.AddAzureClients(builder => builder.AddTestClient(configuration)); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -156,7 +157,7 @@ public void SetsOptionsPropertiesFromConfiguration() public void CreateClientThrowsWhenClientIsNotRegistered() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", new Uri("http://localhost/"))); + serviceCollection.AddAzureClients(builder => builder.AddTestClient(new Uri("http://localhost/"))); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -169,7 +170,7 @@ public void CreateClientThrowsWhenClientIsNotRegistered() public void RetrhowsExceptionFromClientCreation() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", "throw")); + serviceCollection.AddAzureClients(builder => builder.AddTestClient("throw")); ServiceProvider provider = serviceCollection.BuildServiceProvider(); IAzureClientFactory factory = provider.GetService>(); @@ -185,8 +186,8 @@ public void CanSetGlobalOptions() { var serviceCollection = new ServiceCollection(); serviceCollection.AddAzureClients(builder => { - builder.AddTestClient("Default", "TestClient1"); - builder.AddTestClientWithCredentials("Default", new Uri("http://localhost")); + builder.AddTestClient("TestClient1"); + builder.AddTestClientWithCredentials(new Uri("http://localhost")); builder.ConfigureDefaults(options => options.TelemetryPolicy.ApplicationId = "GlobalAppId"); }); ServiceProvider provider = serviceCollection.BuildServiceProvider(); @@ -205,8 +206,8 @@ public void CanSetGlobalOptionsUsingConfiguration() var serviceCollection = new ServiceCollection(); serviceCollection.AddAzureClients(builder => { - builder.AddTestClient("Default", "TestClient1"); - builder.AddTestClientWithCredentials("Default", new Uri("http://localhost")); + builder.AddTestClient("TestClient1"); + builder.AddTestClientWithCredentials(new Uri("http://localhost")); builder.UseDefaultConfiguration(configuration); }); ServiceProvider provider = serviceCollection.BuildServiceProvider(); @@ -222,7 +223,7 @@ public void CanSetGlobalOptionsUsingConfiguration() public void ResolvesDefaultClientByDefault() { var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder.AddTestClient("Default", "Connection string")); + serviceCollection.AddAzureClients(builder => builder.AddTestClient("Connection string")); ServiceProvider provider = serviceCollection.BuildServiceProvider(); var client = provider.GetService(); @@ -234,7 +235,7 @@ public void UsesProvidedCredentialIfOverGlobal() { var serviceCollection = new ServiceCollection(); var defaultAzureCredential = new ManagedIdentityCredential(); - serviceCollection.AddAzureClients(builder => builder.AddTestClientWithCredentials("Default", new Uri("http://localhost"), defaultAzureCredential)); + serviceCollection.AddAzureClients(builder => builder.AddTestClientWithCredentials(new Uri("http://localhost")).WithCredential(defaultAzureCredential)); ServiceProvider provider = serviceCollection.BuildServiceProvider(); TestClientWithCredentials client = provider.GetService(); @@ -247,9 +248,10 @@ public void UsesGlobalCredential() { var serviceCollection = new ServiceCollection(); var defaultAzureCredential = new ManagedIdentityCredential(); - serviceCollection.AddAzureClients(builder => builder - .AddTestClientWithCredentials("Default", new Uri("http://localhost")) - .UseCredential(defaultAzureCredential)); + serviceCollection.AddAzureClients(builder => { + builder.AddTestClientWithCredentials(new Uri("http://localhost")); + builder.UseCredential(defaultAzureCredential); + }); ServiceProvider provider = serviceCollection.BuildServiceProvider(); TestClientWithCredentials client = provider.GetService(); @@ -265,9 +267,10 @@ public void UsesCredentialFromGlobalConfiguration() new KeyValuePair("tenantId", "ConfigurationTenantId")); var serviceCollection = new ServiceCollection(); - serviceCollection.AddAzureClients(builder => builder - .AddTestClientWithCredentials("Default", new Uri("http://localhost")) - .UseDefaultConfiguration(configuration)); + serviceCollection.AddAzureClients(builder => { + builder.AddTestClientWithCredentials(new Uri("http://localhost")); + builder.UseDefaultConfiguration(configuration); + }); ServiceProvider provider = serviceCollection.BuildServiceProvider(); TestClientWithCredentials client = provider.GetService(); @@ -291,7 +294,7 @@ public void UsesCredentialFromConfiguration() var serviceCollection = new ServiceCollection(); serviceCollection.AddAzureClients(builder => builder - .AddTestClientWithCredentials("Default", configuration)); + .AddTestClientWithCredentials(configuration)); ServiceProvider provider = serviceCollection.BuildServiceProvider(); TestClientWithCredentials client = provider.GetService(); diff --git a/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs b/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs index c19cd8c1955ef..6e03c4e7abbae 100644 --- a/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs +++ b/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs @@ -7,39 +7,34 @@ namespace Azure.Core.Extensions.Tests { internal static class TestClientsBuilderExtensions { - public static TBuilder AddTestClient(this TBuilder builder, string name, string connectionString, Action configureOptions = null) + public static IAzureClientBuilder AddTestClient(this TBuilder builder, string connectionString) where TBuilder: IAzureClientsBuilder { - builder.RegisterClient(name, options => new TestClient(connectionString, options), configureOptions); - return builder; + return builder.RegisterClient(options => new TestClient(connectionString, options)); } - public static TBuilder AddTestClient(this TBuilder builder, string name, Uri uri, Action configureOptions = null) + public static IAzureClientBuilder AddTestClient(this TBuilder builder, Uri uri) where TBuilder: IAzureClientsBuilder { - builder.RegisterClient(name, options => new TestClient(uri, options), configureOptions); - return builder; + return builder.RegisterClient(options => new TestClient(uri, options)); } - public static TBuilder AddTestClient(this TBuilder builder, string name, TConfiguration configuration) + public static IAzureClientBuilder AddTestClient(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { - builder.RegisterClient(name, configuration); - return builder; + return builder.RegisterClient(configuration); } - public static TBuilder AddTestClientWithCredentials(this TBuilder builder, string name, TConfiguration configuration) + public static IAzureClientBuilder AddTestClientWithCredentials(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { - builder.RegisterClient(name, configuration); - return builder; + return builder.RegisterClient(configuration); } - public static TBuilder AddTestClientWithCredentials(this TBuilder builder, string name, Uri uri, TokenCredential tokenCredential = null, Action configureOptions = null) + public static IAzureClientBuilder AddTestClientWithCredentials(this TBuilder builder, Uri uri) where TBuilder: IAzureClientsBuilderWithCredential { - builder.RegisterClient(name, (options, cred) => new TestClientWithCredentials(uri, cred, options), configureOptions, tokenCredential); - return builder; + return builder.RegisterClient((options, cred) => new TestClientWithCredentials(uri, cred, options)); } } diff --git a/sdk/core/Azure.Core/src/Extensions/IAzureClientBuilder.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientBuilder.cs new file mode 100644 index 0000000000000..bc20cc1e7076d --- /dev/null +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientBuilder.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Azure.Core.Extensions +{ +#pragma warning disable CA1040 // Avoid empty interfaces + public interface IAzureClientBuilder where TOptions : class +#pragma warning restore CA1040 // Avoid empty interfaces + { + } +} diff --git a/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs similarity index 51% rename from sdk/core/Azure.Core/src/IAzureClientsBuilder.cs rename to sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs index f231209038c63..216aa13141f14 100644 --- a/sdk/core/Azure.Core/src/IAzureClientsBuilder.cs +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs @@ -4,10 +4,10 @@ using System; using Azure.Core.Pipeline; -namespace Azure.Core +namespace Azure.Core.Extensions { public interface IAzureClientsBuilder { - void RegisterClient(string name, Func clientFactory, Action configureOptions) where TOptions : ClientOptions; + IAzureClientBuilder RegisterClient(Func clientFactory) where TOptions : ClientOptions; } } diff --git a/sdk/core/Azure.Core/src/IAzureClientsBuilderWithConfiguration.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs similarity index 58% rename from sdk/core/Azure.Core/src/IAzureClientsBuilderWithConfiguration.cs rename to sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs index 10862071c7010..99c4843b1c53e 100644 --- a/sdk/core/Azure.Core/src/IAzureClientsBuilderWithConfiguration.cs +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs @@ -3,10 +3,11 @@ using Azure.Core.Pipeline; -namespace Azure.Core +namespace Azure.Core.Extensions { + public interface IAzureClientsBuilderWithConfiguration: IAzureClientsBuilder { - void RegisterClient(string name, TConfiguration configuration) where TOptions : ClientOptions; + IAzureClientBuilder RegisterClient(TConfiguration configuration) where TOptions : ClientOptions; } } diff --git a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithCredential.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithCredential.cs new file mode 100644 index 0000000000000..7f5e0bb129d10 --- /dev/null +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithCredential.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Pipeline; + +namespace Azure.Core.Extensions +{ + public interface IAzureClientsBuilderWithCredential + { + IAzureClientBuilder RegisterClient(Func clientFactory) where TOptions : ClientOptions; + } +} diff --git a/sdk/core/Azure.Core/src/IAzureClientsBuilderWithCredential.cs b/sdk/core/Azure.Core/src/IAzureClientsBuilderWithCredential.cs deleted file mode 100644 index 1bdc5b845a6e3..0000000000000 --- a/sdk/core/Azure.Core/src/IAzureClientsBuilderWithCredential.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Azure.Core.Pipeline; - -namespace Azure.Core -{ - public interface IAzureClientsBuilderWithCredential - { - void RegisterClient(string name, Func clientFactory, Action configureOptions, TokenCredential providedCredential) where TOptions : ClientOptions; - } -} diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/KeyVaultAzureClientBuilderExtensions.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/KeyVaultAzureClientBuilderExtensions.cs deleted file mode 100644 index c71163db84a64..0000000000000 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/KeyVaultAzureClientBuilderExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Azure.Core; -using Azure.Security.KeyVault.Secrets; - -namespace Azure.ApplicationModel.Configuration -{ - public static class KeyVaultAzureClientBuilderExtensions - { - public static TBuilder AddKeyVaultSecrets(this TBuilder builder, - string name, - Uri vaultUri, - TokenCredential tokenCredential = null, - Action configureOptions = null) - where TBuilder: IAzureClientsBuilderWithCredential - { - builder.RegisterClient(name, (options, cred) => new SecretClient(vaultUri, tokenCredential, options), configureOptions, tokenCredential); - return builder; - } - - public static TBuilder AddKeyVaultSecrets(this TBuilder builder, string name, TConfiguration configuration) - where TBuilder: IAzureClientsBuilderWithConfiguration - { - builder.RegisterClient(name, configuration); - return builder; - } - } -} diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs new file mode 100644 index 0000000000000..45565dd6f2f4e --- /dev/null +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Extensions; + +namespace Azure.Security.KeyVault.Secrets +{ + public static class SecretClientBuilderExtensions + { + public static IAzureClientBuilder AddKeyVaultSecrets(this TBuilder builder, Uri vaultUri) + where TBuilder: IAzureClientsBuilderWithCredential + { + return builder.RegisterClient((options, cred) => new SecretClient(vaultUri, cred, options)); + } + + public static IAzureClientBuilder AddKeyVaultSecrets(this TBuilder builder, TConfiguration configuration) + where TBuilder: IAzureClientsBuilderWithConfiguration + { + return builder.RegisterClient(configuration); + } + } +} From 54420da538763e112f0a4d25efb0a6e92994e1c2 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 3 Jul 2019 12:49:43 -0700 Subject: [PATCH 05/17] Use core --- eng/Directory.Build.Data.props | 2 +- .../src/Azure.ApplicationModel.Configuration.csproj | 1 - sdk/core/Azure.Core.Extensions/samples/Startup.cs | 1 - sdk/identity/Azure.Identity/src/Azure.Identity.csproj | 1 - .../src/Azure.Security.KeyVault.Secrets.csproj | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/eng/Directory.Build.Data.props b/eng/Directory.Build.Data.props index fba7d98dcaae0..66025139fa182 100644 --- a/eng/Directory.Build.Data.props +++ b/eng/Directory.Build.Data.props @@ -106,7 +106,7 @@ false false false - false + true preview diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj index ee45c821f7125..92019df4b546f 100644 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj @@ -13,7 +13,6 @@ $(RequiredTargetFrameworks) $(NoWarn);3021 true - true diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index 2acc92f784041..6bb8357e0052a 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using Azure.ApplicationModel.Configuration; using Azure.Core.Pipeline; using Azure.Core.Pipeline.Policies; using Azure.Identity; diff --git a/sdk/identity/Azure.Identity/src/Azure.Identity.csproj b/sdk/identity/Azure.Identity/src/Azure.Identity.csproj index 7fc298e144738..2cd4336a37a85 100644 --- a/sdk/identity/Azure.Identity/src/Azure.Identity.csproj +++ b/sdk/identity/Azure.Identity/src/Azure.Identity.csproj @@ -14,7 +14,6 @@ $(NoWarn);3021 true false - true diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj index 26e1bab2d3359..bdab447e61224 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj @@ -12,7 +12,6 @@ $(RequiredTargetFrameworks) $(NoWarn);3021 true - true From 753a6a7bbae5d864fc135b9dcb8d4a504d54d185 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 3 Jul 2019 12:56:13 -0700 Subject: [PATCH 06/17] Public --- .../tests/EnvironmentCredentialProviderTests.cs | 6 +++--- .../tests/TestAccessorExtensions.cs | 15 --------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs b/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs index 5e73dffb725ed..6040fd11782ca 100644 --- a/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs +++ b/sdk/identity/Azure.Identity/tests/EnvironmentCredentialProviderTests.cs @@ -43,11 +43,11 @@ public void CredentialConstruction() Assert.NotNull(cred); - Assert.AreEqual("mockclientid", cred._clientId()); + Assert.AreEqual("mockclientid", cred.ClientId); - Assert.AreEqual("mocktenantid", cred._tenantId()); + Assert.AreEqual("mocktenantid", cred.TenantId); - Assert.AreEqual("mockclientsecret", cred._clientSecret()); + Assert.AreEqual("mockclientsecret", cred.ClientSecret); } finally { diff --git a/sdk/identity/Azure.Identity/tests/TestAccessorExtensions.cs b/sdk/identity/Azure.Identity/tests/TestAccessorExtensions.cs index 79be2c6840e29..a253f88079765 100644 --- a/sdk/identity/Azure.Identity/tests/TestAccessorExtensions.cs +++ b/sdk/identity/Azure.Identity/tests/TestAccessorExtensions.cs @@ -10,21 +10,6 @@ namespace Azure.Identity.Tests { internal static class TestAccessorExtensions { - public static string _clientId(this ClientSecretCredential credential) - { - return typeof(ClientSecretCredential).GetField("_clientId", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(credential) as string; - } - - public static string _tenantId(this ClientSecretCredential credential) - { - return typeof(ClientSecretCredential).GetField("_tenantId", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(credential) as string; - } - - public static string _clientSecret(this ClientSecretCredential credential) - { - return typeof(ClientSecretCredential).GetField("_clientSecret", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(credential) as string; - } - public static string _client(this ClientSecretCredential credential) { return typeof(ClientSecretCredential).GetField("_client", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(credential) as string; From 7764830e0d12415f714f790ec210deb3bf99db1a Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 3 Jul 2019 13:31:16 -0700 Subject: [PATCH 07/17] Properties --- sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs | 2 +- .../Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 sdk/core/Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs index 9cae314fd69d4..118ff1a7375c2 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs @@ -49,7 +49,7 @@ public AzureClientsBuilder ConfigureDefaults(Action configuration.Bind(options)); diff --git a/sdk/core/Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs b/sdk/core/Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000000..4e2d3782bc920 --- /dev/null +++ b/sdk/core/Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using Azure.Core; + +[assembly: AzureSdkClientLibrary("base-test")] From cd3d5b0d905418dce144bf30e6e56c0a17fe6d0a Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 3 Jul 2019 13:37:39 -0700 Subject: [PATCH 08/17] CTRL+S --- sdk/core/Azure.Core.Extensions/samples/Startup.cs | 2 +- .../Azure.Core.Extensions/tests/AzureClientFactoryTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index 6bb8357e0052a..e9a8b774688b7 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -41,7 +41,7 @@ public void ConfigureServices(IServiceCollection services) builder.UseCredential(new DefaultAzureCredential()); // This would use configuration for auth and client settings - builder.UseDefaultConfiguration(Configuration.GetSection("Default")); + builder.ConfigureDefaults(Configuration.GetSection("Default")); // Configure global defaults builder.ConfigureDefaults(options => options.RetryPolicy.Mode = RetryMode.Exponential); diff --git a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs index 5c6855d7c68dd..177feb53e0579 100644 --- a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs +++ b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs @@ -208,7 +208,7 @@ public void CanSetGlobalOptionsUsingConfiguration() serviceCollection.AddAzureClients(builder => { builder.AddTestClient("TestClient1"); builder.AddTestClientWithCredentials(new Uri("http://localhost")); - builder.UseDefaultConfiguration(configuration); + builder.ConfigureDefaults(configuration); }); ServiceProvider provider = serviceCollection.BuildServiceProvider(); @@ -269,7 +269,7 @@ public void UsesCredentialFromGlobalConfiguration() var serviceCollection = new ServiceCollection(); serviceCollection.AddAzureClients(builder => { builder.AddTestClientWithCredentials(new Uri("http://localhost")); - builder.UseDefaultConfiguration(configuration); + builder.ConfigureDefaults(configuration); }); ServiceProvider provider = serviceCollection.BuildServiceProvider(); From 6f511b705ae145187d3a9cc51844e8aee31da27e Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 3 Jul 2019 14:38:51 -0700 Subject: [PATCH 09/17] *nix cert fixes --- .../Internal/ConfigurationClientFactory.cs | 19 ++++++++++++++----- .../tests/ConfigurationClientFactoryTests.cs | 13 +++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs index b2b246849382c..9bebb44ccd4a1 100644 --- a/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs @@ -68,7 +68,8 @@ internal static TokenCredential CreateCredentials(IConfiguration configuration, var tenantId = configuration["tenantId"]; var clientSecret = configuration["clientSecret"]; var certificate = configuration["clientCertificate"]; - var certificateStore = configuration["clientCertificateStore"]; + var certificateStoreName = configuration["clientCertificateStoreName"]; + var certificateStoreLocation = configuration["clientCertificateStoreLocation"]; if (!string.IsNullOrWhiteSpace(tenantId) && !string.IsNullOrWhiteSpace(clientId) && @@ -81,11 +82,19 @@ internal static TokenCredential CreateCredentials(IConfiguration configuration, !string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(certificate)) { - var storeLocation = string.Equals(certificateStore, "machine", StringComparison.OrdinalIgnoreCase) - ? StoreLocation.LocalMachine - : StoreLocation.CurrentUser;; + StoreLocation storeLocation = StoreLocation.CurrentUser; - using var store = new X509Store(storeLocation); + if (!string.IsNullOrWhiteSpace(certificateStoreLocation)) + { + storeLocation = (StoreLocation)Enum.Parse(typeof(StoreLocation), certificateStoreLocation, true); + } + + if (string.IsNullOrWhiteSpace(certificateStoreName)) + { + certificateStoreName = "MY"; // MY is the default used in X509Store + } + + using var store = new X509Store(certificateStoreName, storeLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, certificate, false); diff --git a/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs b/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs index e997d2dae63a0..48690d90dbce3 100644 --- a/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs +++ b/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs @@ -52,12 +52,12 @@ public void ThrowsExceptionWithInformationAboutArguments() } [Theory] - [TestCase("user", StoreLocation.CurrentUser)] - [TestCase("machine", StoreLocation.LocalMachine)] - [TestCase(null, StoreLocation.CurrentUser)] - public void CreatesCertificateCredentials(string storeName, StoreLocation expectedStore) + [TestCase("currentUser", StoreLocation.CurrentUser, "my", StoreName.My)] + [TestCase("localMachine", StoreLocation.LocalMachine, "root", StoreName.Root)] + [TestCase(null, StoreLocation.CurrentUser, null, StoreName.My)] + public void CreatesCertificateCredentials(string storeLocation, StoreLocation expectedStore, string storeName, StoreName expectedName) { - var localCert = new X509Store(expectedStore); + var localCert = new X509Store(expectedName, expectedStore); localCert.Open(OpenFlags.ReadOnly); var someLocalCert = localCert.Certificates[0].Thumbprint; localCert.Close(); @@ -65,7 +65,8 @@ public void CreatesCertificateCredentials(string storeName, StoreLocation expect IConfiguration configuration = GetConfiguration( new KeyValuePair("clientId", "ConfigurationClientId"), new KeyValuePair("clientCertificate", someLocalCert), - new KeyValuePair("clientCertificateStore", storeName), + new KeyValuePair("clientCertificateStoreLocation", storeLocation), + new KeyValuePair("clientCertificateStoreName", storeName), new KeyValuePair("tenantId", "ConfigurationTenantId") ); From 4129fd1d590c6a8075857053a9c1bba36af91f04 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 3 Jul 2019 14:42:03 -0700 Subject: [PATCH 10/17] Adjust names --- .../src/ConfigurationClientBuilderExtensions.cs | 4 ++-- sdk/core/Azure.Core.Extensions/samples/Startup.cs | 4 ++-- .../src/SecretClientBuilderExtensions.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs index f0ec4e41aec73..db4cf5fc3215e 100644 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs @@ -7,13 +7,13 @@ namespace Azure.ApplicationModel.Configuration { public static class ConfigurationClientBuilderExtensions { - public static IAzureClientBuilder AddAppConfiguration(this TBuilder builder, string connectionString) + public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, string connectionString) where TBuilder: IAzureClientsBuilder { return builder.RegisterClient(options => new ConfigurationClient(connectionString, options)); } - public static IAzureClientBuilder AddAppConfiguration(this TBuilder builder, TConfiguration configuration) + public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { return builder.RegisterClient(configuration); diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index e9a8b774688b7..38ba497afa7d6 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -31,12 +31,12 @@ public void ConfigureServices(IServiceCollection services) services.AddAzureClients(builder => { - builder.AddKeyVaultSecrets(Configuration.GetSection("KeyVault")) + builder.AddSecretClient(Configuration.GetSection("KeyVault")) .WithName("Default") .WithCredential(new DefaultAzureCredential()) .ConfigureOptions(options => options.RetryPolicy.MaxRetries = 10); - builder.AddKeyVaultSecrets(new Uri("http://my.keyvault.com")); + builder.AddSecretClient(new Uri("http://my.keyvault.com")); builder.UseCredential(new DefaultAzureCredential()); diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs index 45565dd6f2f4e..f84d77b3206e0 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs @@ -8,13 +8,13 @@ namespace Azure.Security.KeyVault.Secrets { public static class SecretClientBuilderExtensions { - public static IAzureClientBuilder AddKeyVaultSecrets(this TBuilder builder, Uri vaultUri) + public static IAzureClientBuilder AddSecretClient(this TBuilder builder, Uri vaultUri) where TBuilder: IAzureClientsBuilderWithCredential { return builder.RegisterClient((options, cred) => new SecretClient(vaultUri, cred, options)); } - public static IAzureClientBuilder AddKeyVaultSecrets(this TBuilder builder, TConfiguration configuration) + public static IAzureClientBuilder AddSecretClient(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { return builder.RegisterClient(configuration); From 58d2d7814ab75831fd53acd730b948d3f06a9262 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 5 Jul 2019 09:54:07 -0700 Subject: [PATCH 11/17] WarnOnPackingNonPackableProject --- .../samples/Azure.Core.Extensions.Samples.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj b/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj index 52e8ccc4d4f75..3162a3231261c 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj +++ b/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj @@ -2,6 +2,7 @@ netcoreapp2.1 $(RequiredTargetFrameworks) + false From 97dde2526141fe8850af147e42ab94427d32c9d0 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 5 Jul 2019 10:26:28 -0700 Subject: [PATCH 12/17] IsImplicitlyDefined --- eng/Packages.Data.props | 1 - .../samples/Azure.Core.Extensions.Samples.csproj | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/eng/Packages.Data.props b/eng/Packages.Data.props index 83e47a9c05bf6..cd0221d011188 100755 --- a/eng/Packages.Data.props +++ b/eng/Packages.Data.props @@ -13,7 +13,6 @@ - diff --git a/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj b/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj index 3162a3231261c..9cc1af65dbc5c 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj +++ b/sdk/core/Azure.Core.Extensions/samples/Azure.Core.Extensions.Samples.csproj @@ -5,7 +5,7 @@ false - + From e2fc779dba2afb95b8055bfa6d4f395deed1b076 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 5 Jul 2019 11:10:46 -0700 Subject: [PATCH 13/17] merge --- sdk/core/Azure.Core.Extensions/samples/Startup.cs | 4 ++-- .../tests/AzureClientFactoryTests.cs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index 38ba497afa7d6..79cec454b536f 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -34,7 +34,7 @@ public void ConfigureServices(IServiceCollection services) builder.AddSecretClient(Configuration.GetSection("KeyVault")) .WithName("Default") .WithCredential(new DefaultAzureCredential()) - .ConfigureOptions(options => options.RetryPolicy.MaxRetries = 10); + .ConfigureOptions(options => options.Retry.MaxRetries = 10); builder.AddSecretClient(new Uri("http://my.keyvault.com")); @@ -44,7 +44,7 @@ public void ConfigureServices(IServiceCollection services) builder.ConfigureDefaults(Configuration.GetSection("Default")); // Configure global defaults - builder.ConfigureDefaults(options => options.RetryPolicy.Mode = RetryMode.Exponential); + builder.ConfigureDefaults(options => options.Retry.Mode = RetryMode.Exponential); // Advanced configure global defaults builder.ConfigureDefaults((options, provider) => options.AddPolicy(HttpPipelinePosition.PerCall, provider.GetService())); diff --git a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs index 177feb53e0579..10d06d725afa0 100644 --- a/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs +++ b/sdk/core/Azure.Core.Extensions/tests/AzureClientFactoryTests.cs @@ -188,21 +188,21 @@ public void CanSetGlobalOptions() serviceCollection.AddAzureClients(builder => { builder.AddTestClient("TestClient1"); builder.AddTestClientWithCredentials(new Uri("http://localhost")); - builder.ConfigureDefaults(options => options.TelemetryPolicy.ApplicationId = "GlobalAppId"); + builder.ConfigureDefaults(options => options.Diagnostics.ApplicationId = "GlobalAppId"); }); ServiceProvider provider = serviceCollection.BuildServiceProvider(); TestClient testClient = provider.GetService>().CreateClient("Default"); TestClientWithCredentials testClientWithCredentials = provider.GetService>().CreateClient("Default"); - Assert.AreEqual("GlobalAppId", testClient.Options.TelemetryPolicy.ApplicationId); - Assert.AreEqual("GlobalAppId", testClientWithCredentials.Options.TelemetryPolicy.ApplicationId); + Assert.AreEqual("GlobalAppId", testClient.Options.Diagnostics.ApplicationId); + Assert.AreEqual("GlobalAppId", testClientWithCredentials.Options.Diagnostics.ApplicationId); } [Test] public void CanSetGlobalOptionsUsingConfiguration() { - var configuration = GetConfiguration(new KeyValuePair("TelemetryPolicy:ApplicationId", "GlobalAppId")); + var configuration = GetConfiguration(new KeyValuePair("Diagnostics:ApplicationId", "GlobalAppId")); var serviceCollection = new ServiceCollection(); serviceCollection.AddAzureClients(builder => { @@ -215,8 +215,8 @@ public void CanSetGlobalOptionsUsingConfiguration() TestClient testClient = provider.GetService>().CreateClient("Default"); TestClientWithCredentials testClientWithCredentials = provider.GetService>().CreateClient("Default"); - Assert.AreEqual("GlobalAppId", testClient.Options.TelemetryPolicy.ApplicationId); - Assert.AreEqual("GlobalAppId", testClientWithCredentials.Options.TelemetryPolicy.ApplicationId); + Assert.AreEqual("GlobalAppId", testClient.Options.Diagnostics.ApplicationId); + Assert.AreEqual("GlobalAppId", testClientWithCredentials.Options.Diagnostics.ApplicationId); } [Test] From 2e340f3255bf406f6c160e97aa160a7d2718d003 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 16 Jul 2019 11:30:14 -0700 Subject: [PATCH 14/17] Feedback and merge fix --- eng/Directory.Build.Data.props | 2 +- eng/Packages.Data.props | 8 ++--- ...nfigurationAzureClientBuilderExtensions.cs | 31 ------------------- ...zure.ApplicationModel.Configuration.csproj | 3 -- .../ConfigurationClientBuilderExtensions.cs | 9 ++++++ .../src/ConfigurationClientOptions.cs | 5 ++- .../samples/CustomPolicy.cs | 4 +-- .../Azure.Core.Extensions/samples/Startup.cs | 4 +-- .../src/AzureClientsBuilder.cs | 4 +-- .../Internal/ConfigurationClientFactory.cs | 2 +- .../tests/ConfigurationClientFactoryTests.cs | 4 +-- .../tests/Properties/AssemblyInfo.cs | 3 -- .../src/ClientCertificateCredential.cs | 11 +++++++ .../src/ClientSecretCredential.cs | 9 ++++++ .../src/SecretClientBuilderExtensions.cs | 9 ++++++ 15 files changed, 56 insertions(+), 52 deletions(-) delete mode 100644 sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AppConfigurationAzureClientBuilderExtensions.cs delete mode 100644 sdk/core/Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs diff --git a/eng/Directory.Build.Data.props b/eng/Directory.Build.Data.props index a9c16933513b1..884e5c2d57820 100644 --- a/eng/Directory.Build.Data.props +++ b/eng/Directory.Build.Data.props @@ -111,7 +111,7 @@ $(IntermediateOutputPath)$(TargetFramework)\$(MSBuildProjectName).xml - + false false diff --git a/eng/Packages.Data.props b/eng/Packages.Data.props index 59d7a42a5986e..fa01a8018a3e5 100755 --- a/eng/Packages.Data.props +++ b/eng/Packages.Data.props @@ -41,10 +41,6 @@ - - - - @@ -104,6 +100,10 @@ + + + + diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AppConfigurationAzureClientBuilderExtensions.cs b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AppConfigurationAzureClientBuilderExtensions.cs deleted file mode 100644 index e9574825b4a78..0000000000000 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AppConfigurationAzureClientBuilderExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Azure.Core; - -namespace Azure.ApplicationModel.Configuration -{ - /// - /// App Configuration client builder - /// - public static class AppConfigurationAzureClientBuilderExtensions - { - public static TBuilder AddAppConfiguration(this TBuilder builder, - string name, - string connectionString, - Action configureOptions = null) - where TBuilder: IAzureClientsBuilder - { - builder.RegisterClient(name, options => new ConfigurationClient(connectionString, options), configureOptions); - return builder; - } - - public static TBuilder AddAppConfiguration(this TBuilder builder, string name, TConfiguration configuration) - where TBuilder: IAzureClientsBuilderWithConfiguration - { - builder.RegisterClient(name, configuration); - return builder; - } - } -} diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj index fd2276c6a487c..92019df4b546f 100644 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/Azure.ApplicationModel.Configuration.csproj @@ -13,9 +13,6 @@ $(RequiredTargetFrameworks) $(NoWarn);3021 true - - - $(NoWarn);1591 diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs index db4cf5fc3215e..2693ed5c842fb 100644 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs @@ -5,14 +5,23 @@ namespace Azure.ApplicationModel.Configuration { + /// + /// Extension methods to add client to clients builder + /// public static class ConfigurationClientBuilderExtensions { + /// + /// Registers a instance with the provided + /// public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, string connectionString) where TBuilder: IAzureClientsBuilder { return builder.RegisterClient(options => new ConfigurationClient(connectionString, options)); } + /// + /// Registers a instance with connection options loaded from the provided instance. + /// public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientOptions.cs b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientOptions.cs index 8b9b4bb75c7f1..6f8f6de9849f0 100644 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientOptions.cs +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientOptions.cs @@ -20,6 +20,9 @@ public class ConfigurationClientOptions: ClientOptions /// public enum ServiceVersion { + /// + /// Uses the latest service version + /// Default = 0 } @@ -35,7 +38,7 @@ public enum ServiceVersion /// /// /// The of the service API used when - /// making requests. + /// making requests. /// public ConfigurationClientOptions(ServiceVersion version = ServiceVersion.Default) { diff --git a/sdk/core/Azure.Core.Extensions/samples/CustomPolicy.cs b/sdk/core/Azure.Core.Extensions/samples/CustomPolicy.cs index 47578e0a11eb5..68bfaa8617a46 100644 --- a/sdk/core/Azure.Core.Extensions/samples/CustomPolicy.cs +++ b/sdk/core/Azure.Core.Extensions/samples/CustomPolicy.cs @@ -6,11 +6,11 @@ namespace Azure.Core.Extensions.Samples { - internal class DIEnabledPolicy : SynchronousHttpPipelinePolicy + internal class DependencyInjectionEnabledPolicy : SynchronousHttpPipelinePolicy { private readonly IHostingEnvironment _environment; - public DIEnabledPolicy(IHostingEnvironment environment) + public DependencyInjectionEnabledPolicy(IHostingEnvironment environment) { this._environment = environment; } diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index 79cec454b536f..e5cc6a06b404b 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -27,7 +27,7 @@ public Startup(IConfiguration configuration) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { - services.AddSingleton(); + services.AddSingleton(); services.AddAzureClients(builder => { @@ -47,7 +47,7 @@ public void ConfigureServices(IServiceCollection services) builder.ConfigureDefaults(options => options.Retry.Mode = RetryMode.Exponential); // Advanced configure global defaults - builder.ConfigureDefaults((options, provider) => options.AddPolicy(HttpPipelinePosition.PerCall, provider.GetService())); + builder.ConfigureDefaults((options, provider) => options.AddPolicy(HttpPipelinePosition.PerCall, provider.GetService())); // Configure default credential // builder.UseDefaultCredential(new ClientSecretCredential("tenantId","clientId","clientSecret")); diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs index 118ff1a7375c2..068e04bf86d44 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs @@ -33,7 +33,7 @@ IAzureClientBuilder IAzureClientsBuilderWithConfiguration( (options, credentials) => (TClient)ClientFactory.CreateClient(typeof(TClient), typeof(TOptions), options, configuration, credentials)) .ConfigureOptions(configuration) - .WithCredential(ClientFactory.CreateCredentials(configuration)); + .WithCredential(ClientFactory.CreateCredential(configuration)); } public AzureClientsBuilder ConfigureDefaults(Action configureOptions) @@ -53,7 +53,7 @@ public AzureClientsBuilder ConfigureDefaults(IConfiguration configuration) { ConfigureDefaults(options => configuration.Bind(options)); - var credentialsFromConfig = ClientFactory.CreateCredentials(configuration); + var credentialsFromConfig = ClientFactory.CreateCredential(configuration); if (credentialsFromConfig != null) { diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs index 9bebb44ccd4a1..0c25bdf673b93 100644 --- a/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigurationClientFactory.cs @@ -62,7 +62,7 @@ public static object CreateClient(Type clientType, Type optionsType, object opti throw new InvalidOperationException(BuildErrorMessage(clientType, optionsType)); } - internal static TokenCredential CreateCredentials(IConfiguration configuration, IdentityClientOptions identityClientOptions = null) + internal static TokenCredential CreateCredential(IConfiguration configuration, IdentityClientOptions identityClientOptions = null) { var clientId = configuration["clientId"]; var tenantId = configuration["tenantId"]; diff --git a/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs b/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs index 48690d90dbce3..a6a537bd2ad6c 100644 --- a/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs +++ b/sdk/core/Azure.Core.Extensions/tests/ConfigurationClientFactoryTests.cs @@ -70,7 +70,7 @@ public void CreatesCertificateCredentials(string storeLocation, StoreLocation ex new KeyValuePair("tenantId", "ConfigurationTenantId") ); - var credential = ClientFactory.CreateCredentials(configuration); + var credential = ClientFactory.CreateCredential(configuration); Assert.IsInstanceOf(credential); var clientCertificateCredential = (ClientCertificateCredential)credential; @@ -89,7 +89,7 @@ public void CreatesClientSecretCredentials() new KeyValuePair("tenantId", "ConfigurationTenantId") ); - var credential = ClientFactory.CreateCredentials(configuration); + var credential = ClientFactory.CreateCredential(configuration); Assert.IsInstanceOf(credential); var clientSecretCredential = (ClientSecretCredential)credential; diff --git a/sdk/core/Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs b/sdk/core/Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 4e2d3782bc920..0000000000000 --- a/sdk/core/Azure.Core.Extensions/tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using Azure.Core; - -[assembly: AzureSdkClientLibrary("base-test")] diff --git a/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs b/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs index 4601290827aea..77dca35d86bcc 100644 --- a/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs +++ b/sdk/identity/Azure.Identity/src/ClientCertificateCredential.cs @@ -17,8 +17,19 @@ namespace Azure.Identity /// public class ClientCertificateCredential : TokenCredential { + /// + /// Gets the Azure Active Directory tenant (directory) Id of the service principal + /// public string TenantId { get; } + + /// + /// Gets the client (application) ID of the service principal + /// public string ClientId { get; } + + /// + /// Gets the authentication X509 Certificate of the service principal + /// public X509Certificate2 ClientCertificate { get; } private readonly AadIdentityClient _client; diff --git a/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs b/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs index 86041c4da2287..2e7f138af9356 100644 --- a/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs +++ b/sdk/identity/Azure.Identity/src/ClientSecretCredential.cs @@ -17,10 +17,19 @@ public class ClientSecretCredential : TokenCredential { private readonly AadIdentityClient _client; + /// + /// Gets the Azure Active Directory tenant (directory) Id of the service principal + /// public string TenantId { get; } + /// + /// Gets the client (application) ID of the service principal + /// public string ClientId { get; } + /// + /// Gets the client secret that was generated for the App Registration used to authenticate the client. + /// public string ClientSecret { get; } /// diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs index f84d77b3206e0..4013e272fbf40 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs @@ -6,14 +6,23 @@ namespace Azure.Security.KeyVault.Secrets { + /// + /// Extension methods to add secret client to clients builder + /// public static class SecretClientBuilderExtensions { + /// + /// Registers a instance with the provided + /// public static IAzureClientBuilder AddSecretClient(this TBuilder builder, Uri vaultUri) where TBuilder: IAzureClientsBuilderWithCredential { return builder.RegisterClient((options, cred) => new SecretClient(vaultUri, cred, options)); } + /// + /// Registers a instance with connection options loaded from the provided instance. + /// public static IAzureClientBuilder AddSecretClient(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { From 8c127eb1a587bd9d2ac43f7d3f41c46fbf3fea3d Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 17 Jul 2019 09:32:25 -0700 Subject: [PATCH 15/17] PR feedback --- ...tensions.cs => AzureClientBuilderExtensions.cs} | 6 +++--- sdk/core/Azure.Core.Extensions/samples/Startup.cs | 4 +--- .../Azure.Core.Extensions/samples/appsettings.json | 8 ++++---- .../src/AzureClientBuilderExtensions.cs | 8 ++++---- .../src/AzureClientsBuilder.cs | 14 +++++++------- .../src/Internal/AzureClientsGlobalOptions.cs | 4 ++-- .../src/Internal/ConfigureClientOptions.cs | 4 +--- .../src/Internal/DefaultClientOptionsSetup.cs | 2 +- .../DefaultCredentialClientOptionsSetup.cs | 2 +- .../tests/TestClientsBuilderExtensions.cs | 10 +++++----- .../src/Extensions/IAzureClientsBuilder.cs | 2 +- .../IAzureClientsBuilderWithConfiguration.cs | 2 +- .../IAzureClientsBuilderWithCredential.cs | 2 +- .../src/SecretClientBuilderExtensions.cs | 6 +++--- 14 files changed, 35 insertions(+), 39 deletions(-) rename sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/{ConfigurationClientBuilderExtensions.cs => AzureClientBuilderExtensions.cs} (78%) diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AzureClientBuilderExtensions.cs similarity index 78% rename from sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs rename to sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AzureClientBuilderExtensions.cs index 2693ed5c842fb..b7d00c96b1199 100644 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/ConfigurationClientBuilderExtensions.cs +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AzureClientBuilderExtensions.cs @@ -8,7 +8,7 @@ namespace Azure.ApplicationModel.Configuration /// /// Extension methods to add client to clients builder /// - public static class ConfigurationClientBuilderExtensions + public static class AzureClientBuilderExtensions { /// /// Registers a instance with the provided @@ -16,7 +16,7 @@ public static class ConfigurationClientBuilderExtensions public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, string connectionString) where TBuilder: IAzureClientsBuilder { - return builder.RegisterClient(options => new ConfigurationClient(connectionString, options)); + return builder.RegisterClientFactory(options => new ConfigurationClient(connectionString, options)); } /// @@ -25,7 +25,7 @@ public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { - return builder.RegisterClient(configuration); + return builder.RegisterClientFactory(configuration); } } } diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index e5cc6a06b404b..3091850da3861 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -27,6 +27,7 @@ public Startup(IConfiguration configuration) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + // Registering policy to use in ConfigureDefaults later services.AddSingleton(); services.AddAzureClients(builder => { @@ -48,9 +49,6 @@ public void ConfigureServices(IServiceCollection services) // Advanced configure global defaults builder.ConfigureDefaults((options, provider) => options.AddPolicy(HttpPipelinePosition.PerCall, provider.GetService())); - - // Configure default credential - // builder.UseDefaultCredential(new ClientSecretCredential("tenantId","clientId","clientSecret")); }); } diff --git a/sdk/core/Azure.Core.Extensions/samples/appsettings.json b/sdk/core/Azure.Core.Extensions/samples/appsettings.json index f1860fdd610b0..10d2bfca313c7 100644 --- a/sdk/core/Azure.Core.Extensions/samples/appsettings.json +++ b/sdk/core/Azure.Core.Extensions/samples/appsettings.json @@ -6,15 +6,15 @@ }, "AllowedHosts": "*", "Default": { - "ClientId": "", - "ClientSecret": "", - "TenantId": "", + "ClientId": "", + "ClientSecret": "", + "TenantId": "", "TelemetryPolicy": { "ApplicationId": "AppId" } }, "KeyVault": { - "VaultUri": "https://pakrym-keyvault.vault.azure.net/" + "VaultUri": "" } } diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientBuilderExtensions.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientBuilderExtensions.cs index 20d91846b6029..f50e870d0aa8b 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientBuilderExtensions.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientBuilderExtensions.cs @@ -12,7 +12,7 @@ public static class AzureClientBuilderExtensions { public static IAzureClientBuilder WithName(this IAzureClientBuilder builder, string name) where TOptions : class { - builder.ToBuilderImpl().Registration.Name = name; + builder.ToBuilder().Registration.Name = name; return builder; } @@ -23,7 +23,7 @@ public static IAzureClientBuilder WithCredential WithCredential(this IAzureClientBuilder builder, Func credentialFactory) where TOptions : class { - var impl = builder.ToBuilderImpl(); + var impl = builder.ToBuilder(); impl.ServiceCollection.AddSingleton>>(new ConfigureClientCredentials(impl.Registration, credentialFactory)); return builder; } @@ -40,12 +40,12 @@ public static IAzureClientBuilder ConfigureOptions ConfigureOptions(this IAzureClientBuilder builder, Action configureOptions) where TOptions : class { - var impl = builder.ToBuilderImpl(); + var impl = builder.ToBuilder(); impl.ServiceCollection.AddSingleton>(provider => new ConfigureClientOptions(provider, impl.Registration, configureOptions));; return builder; } - private static AzureClientBuilder ToBuilderImpl(this IAzureClientBuilder builder) where TOptions : class + private static AzureClientBuilder ToBuilder(this IAzureClientBuilder builder) where TOptions : class { return (AzureClientBuilder)builder; } diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs index 068e04bf86d44..eb850c5a56f4a 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs @@ -23,14 +23,14 @@ internal AzureClientsBuilder(IServiceCollection serviceCollection) _serviceCollection.TryAddSingleton(); } - IAzureClientBuilder IAzureClientsBuilder.RegisterClient(Func clientFactory) + IAzureClientBuilder IAzureClientsBuilder.RegisterClientFactory(Func clientFactory) { - return ((IAzureClientsBuilderWithCredential)this).RegisterClient((options, _) => clientFactory(options)); + return ((IAzureClientsBuilderWithCredential)this).RegisterClientFactory((options, _) => clientFactory(options)); } - IAzureClientBuilder IAzureClientsBuilderWithConfiguration.RegisterClient(IConfiguration configuration) + IAzureClientBuilder IAzureClientsBuilderWithConfiguration.RegisterClientFactory(IConfiguration configuration) { - return ((IAzureClientsBuilderWithCredential)this).RegisterClient( + return ((IAzureClientsBuilderWithCredential)this).RegisterClientFactory( (options, credentials) => (TClient)ClientFactory.CreateClient(typeof(TClient), typeof(TOptions), options, configuration, credentials)) .ConfigureOptions(configuration) .WithCredential(ClientFactory.CreateCredential(configuration)); @@ -44,7 +44,7 @@ public AzureClientsBuilder ConfigureDefaults(Action configureOpti public AzureClientsBuilder ConfigureDefaults(Action configureOptions) { - _serviceCollection.Configure(options => options.ConfigureOptions.Add(configureOptions)); + _serviceCollection.Configure(options => options.ConfigureOptionDelegates.Add(configureOptions)); return this; } @@ -63,7 +63,7 @@ public AzureClientsBuilder ConfigureDefaults(IConfiguration configuration) return this; } - IAzureClientBuilder IAzureClientsBuilderWithCredential.RegisterClient(Func clientFactory) + IAzureClientBuilder IAzureClientsBuilderWithCredential.RegisterClientFactory(Func clientFactory) { var clientRegistration = new ClientRegistration(DefaultClientName, clientFactory); _serviceCollection.AddSingleton(clientRegistration); @@ -86,7 +86,7 @@ public AzureClientsBuilder UseCredential(TokenCredential tokenCredential) public AzureClientsBuilder UseCredential(Func tokenCredentialFactory) { - _serviceCollection.Configure(options => options.Credential = tokenCredentialFactory); + _serviceCollection.Configure(options => options.CredentialFactory = tokenCredentialFactory); return this; } } diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientsGlobalOptions.cs b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientsGlobalOptions.cs index da6212949573f..cf21a19ee8144 100644 --- a/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientsGlobalOptions.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientsGlobalOptions.cs @@ -10,7 +10,7 @@ namespace Azure.Core.Extensions { internal class AzureClientsGlobalOptions { - public Func Credential { get; set; } = _ => new DefaultAzureCredential(); - public List> ConfigureOptions { get; } = new List>(); + public Func CredentialFactory { get; set; } = _ => new DefaultAzureCredential(); + public List> ConfigureOptionDelegates { get; } = new List>(); } } \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientOptions.cs b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientOptions.cs index 446f1edc52199..b3f97312b5f8d 100644 --- a/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientOptions.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/ConfigureClientOptions.cs @@ -12,9 +12,7 @@ internal class ConfigureClientOptions : IConfigureNamedOption private readonly ClientRegistration _registration; private readonly Action _configureOptions; - public ConfigureClientOptions( - IServiceProvider serviceProvider, - ClientRegistration registration, Action configureOptions) + public ConfigureClientOptions(IServiceProvider serviceProvider, ClientRegistration registration, Action configureOptions) { _serviceProvider = serviceProvider; _registration = registration; diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/DefaultClientOptionsSetup.cs b/sdk/core/Azure.Core.Extensions/src/Internal/DefaultClientOptionsSetup.cs index 69bf0ccf828fc..fa993bd919526 100644 --- a/sdk/core/Azure.Core.Extensions/src/Internal/DefaultClientOptionsSetup.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/DefaultClientOptionsSetup.cs @@ -20,7 +20,7 @@ public DefaultClientOptionsSetup(IOptions defaultOpti public void Configure(T options) { - foreach (var globalConfigureOption in _defaultOptions.Value.ConfigureOptions) + foreach (var globalConfigureOption in _defaultOptions.Value.ConfigureOptionDelegates) { globalConfigureOption(options, _serviceProvider); } diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/DefaultCredentialClientOptionsSetup.cs b/sdk/core/Azure.Core.Extensions/src/Internal/DefaultCredentialClientOptionsSetup.cs index cd7508e79201d..e69027639a12f 100644 --- a/sdk/core/Azure.Core.Extensions/src/Internal/DefaultCredentialClientOptionsSetup.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/DefaultCredentialClientOptionsSetup.cs @@ -18,7 +18,7 @@ public void Configure(AzureClientCredentialOptions options) { if (options.CredentialFactory == null) { - options.CredentialFactory = _defaultOptions.Value.Credential; + options.CredentialFactory = _defaultOptions.Value.CredentialFactory; } } diff --git a/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs b/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs index 6e03c4e7abbae..012f9b87ee877 100644 --- a/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs +++ b/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs @@ -10,31 +10,31 @@ internal static class TestClientsBuilderExtensions public static IAzureClientBuilder AddTestClient(this TBuilder builder, string connectionString) where TBuilder: IAzureClientsBuilder { - return builder.RegisterClient(options => new TestClient(connectionString, options)); + return builder.RegisterClientFactory(options => new TestClient(connectionString, options)); } public static IAzureClientBuilder AddTestClient(this TBuilder builder, Uri uri) where TBuilder: IAzureClientsBuilder { - return builder.RegisterClient(options => new TestClient(uri, options)); + return builder.RegisterClientFactory(options => new TestClient(uri, options)); } public static IAzureClientBuilder AddTestClient(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { - return builder.RegisterClient(configuration); + return builder.RegisterClientFactory(configuration); } public static IAzureClientBuilder AddTestClientWithCredentials(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { - return builder.RegisterClient(configuration); + return builder.RegisterClientFactory(configuration); } public static IAzureClientBuilder AddTestClientWithCredentials(this TBuilder builder, Uri uri) where TBuilder: IAzureClientsBuilderWithCredential { - return builder.RegisterClient((options, cred) => new TestClientWithCredentials(uri, cred, options)); + return builder.RegisterClientFactory((options, cred) => new TestClientWithCredentials(uri, cred, options)); } } diff --git a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs index 216aa13141f14..4a4365c5a2ec0 100644 --- a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs @@ -8,6 +8,6 @@ namespace Azure.Core.Extensions { public interface IAzureClientsBuilder { - IAzureClientBuilder RegisterClient(Func clientFactory) where TOptions : ClientOptions; + IAzureClientBuilder RegisterClientFactory(Func clientFactory) where TOptions : ClientOptions; } } diff --git a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs index 99c4843b1c53e..2f3dc0ad4404d 100644 --- a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs @@ -8,6 +8,6 @@ namespace Azure.Core.Extensions public interface IAzureClientsBuilderWithConfiguration: IAzureClientsBuilder { - IAzureClientBuilder RegisterClient(TConfiguration configuration) where TOptions : ClientOptions; + IAzureClientBuilder RegisterClientFactory(TConfiguration configuration) where TOptions : ClientOptions; } } diff --git a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithCredential.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithCredential.cs index 7f5e0bb129d10..328bee5e68f3d 100644 --- a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithCredential.cs +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithCredential.cs @@ -8,6 +8,6 @@ namespace Azure.Core.Extensions { public interface IAzureClientsBuilderWithCredential { - IAzureClientBuilder RegisterClient(Func clientFactory) where TOptions : ClientOptions; + IAzureClientBuilder RegisterClientFactory(Func clientFactory) where TOptions : ClientOptions; } } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs index 4013e272fbf40..96b76e6c49572 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs @@ -9,7 +9,7 @@ namespace Azure.Security.KeyVault.Secrets /// /// Extension methods to add secret client to clients builder /// - public static class SecretClientBuilderExtensions + public static class AzureClientBuilderExtensions { /// /// Registers a instance with the provided @@ -17,7 +17,7 @@ public static class SecretClientBuilderExtensions public static IAzureClientBuilder AddSecretClient(this TBuilder builder, Uri vaultUri) where TBuilder: IAzureClientsBuilderWithCredential { - return builder.RegisterClient((options, cred) => new SecretClient(vaultUri, cred, options)); + return builder.RegisterClientFactory((options, cred) => new SecretClient(vaultUri, cred, options)); } /// @@ -26,7 +26,7 @@ public static IAzureClientBuilder AddSecretCl public static IAzureClientBuilder AddSecretClient(this TBuilder builder, TConfiguration configuration) where TBuilder: IAzureClientsBuilderWithConfiguration { - return builder.RegisterClient(configuration); + return builder.RegisterClientFactory(configuration); } } } From 1baa8bbe3bbe2b1ab831cb9b7637bce981982e57 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 17 Jul 2019 10:06:19 -0700 Subject: [PATCH 16/17] More renames --- .../src/AzureClientBuilderExtensions.cs | 4 ++-- ...Builder.cs => AzureClientFactoryBuilder.cs} | 18 +++++++++--------- .../AzureClientServiceCollectionExtensions.cs | 4 ++-- .../tests/TestClientsBuilderExtensions.cs | 8 ++++---- ...uilder.cs => IAzureClientFactoryBuilder.cs} | 2 +- ...reClientFactoryBuilderWithConfiguration.cs} | 2 +- .../src/SecretClientBuilderExtensions.cs | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) rename sdk/core/Azure.Core.Extensions/src/{AzureClientsBuilder.cs => AzureClientFactoryBuilder.cs} (75%) rename sdk/core/Azure.Core/src/Extensions/{IAzureClientsBuilder.cs => IAzureClientFactoryBuilder.cs} (87%) rename sdk/core/Azure.Core/src/Extensions/{IAzureClientsBuilderWithConfiguration.cs => IAzureClientFactoryBuilderWithConfiguration.cs} (74%) diff --git a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AzureClientBuilderExtensions.cs b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AzureClientBuilderExtensions.cs index b7d00c96b1199..f4e147a6d9630 100644 --- a/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AzureClientBuilderExtensions.cs +++ b/sdk/appconfiguration/Azure.ApplicationModel.Configuration/src/AzureClientBuilderExtensions.cs @@ -14,7 +14,7 @@ public static class AzureClientBuilderExtensions /// Registers a instance with the provided /// public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, string connectionString) - where TBuilder: IAzureClientsBuilder + where TBuilder: IAzureClientFactoryBuilder { return builder.RegisterClientFactory(options => new ConfigurationClient(connectionString, options)); } @@ -23,7 +23,7 @@ public static IAzureClientBuilder instance with connection options loaded from the provided instance. /// public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, TConfiguration configuration) - where TBuilder: IAzureClientsBuilderWithConfiguration + where TBuilder: IAzureClientFactoryBuilderWithConfiguration { return builder.RegisterClientFactory(configuration); } diff --git a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs b/sdk/core/Azure.Core.Extensions/src/AzureClientFactoryBuilder.cs similarity index 75% rename from sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs rename to sdk/core/Azure.Core.Extensions/src/AzureClientFactoryBuilder.cs index eb850c5a56f4a..e9c98a17c5a8b 100644 --- a/sdk/core/Azure.Core.Extensions/src/AzureClientsBuilder.cs +++ b/sdk/core/Azure.Core.Extensions/src/AzureClientFactoryBuilder.cs @@ -10,25 +10,25 @@ namespace Azure.Core.Extensions { - public sealed class AzureClientsBuilder : IAzureClientsBuilderWithConfiguration, IAzureClientsBuilderWithCredential + public sealed class AzureClientFactoryBuilder : IAzureClientFactoryBuilderWithConfiguration, IAzureClientsBuilderWithCredential { private readonly IServiceCollection _serviceCollection; internal const string DefaultClientName = "Default"; - internal AzureClientsBuilder(IServiceCollection serviceCollection) + internal AzureClientFactoryBuilder(IServiceCollection serviceCollection) { _serviceCollection = serviceCollection; _serviceCollection.AddOptions(); _serviceCollection.TryAddSingleton(); } - IAzureClientBuilder IAzureClientsBuilder.RegisterClientFactory(Func clientFactory) + IAzureClientBuilder IAzureClientFactoryBuilder.RegisterClientFactory(Func clientFactory) { return ((IAzureClientsBuilderWithCredential)this).RegisterClientFactory((options, _) => clientFactory(options)); } - IAzureClientBuilder IAzureClientsBuilderWithConfiguration.RegisterClientFactory(IConfiguration configuration) + IAzureClientBuilder IAzureClientFactoryBuilderWithConfiguration.RegisterClientFactory(IConfiguration configuration) { return ((IAzureClientsBuilderWithCredential)this).RegisterClientFactory( (options, credentials) => (TClient)ClientFactory.CreateClient(typeof(TClient), typeof(TOptions), options, configuration, credentials)) @@ -36,20 +36,20 @@ IAzureClientBuilder IAzureClientsBuilderWithConfiguration configureOptions) + public AzureClientFactoryBuilder ConfigureDefaults(Action configureOptions) { ConfigureDefaults((options, provider) => configureOptions(options)); return this; } - public AzureClientsBuilder ConfigureDefaults(Action configureOptions) + public AzureClientFactoryBuilder ConfigureDefaults(Action configureOptions) { _serviceCollection.Configure(options => options.ConfigureOptionDelegates.Add(configureOptions)); return this; } - public AzureClientsBuilder ConfigureDefaults(IConfiguration configuration) + public AzureClientFactoryBuilder ConfigureDefaults(IConfiguration configuration) { ConfigureDefaults(options => configuration.Bind(options)); @@ -79,12 +79,12 @@ IAzureClientBuilder IAzureClientsBuilderWithCredential.Regist } - public AzureClientsBuilder UseCredential(TokenCredential tokenCredential) + public AzureClientFactoryBuilder UseCredential(TokenCredential tokenCredential) { return UseCredential(_ => tokenCredential); } - public AzureClientsBuilder UseCredential(Func tokenCredentialFactory) + public AzureClientFactoryBuilder UseCredential(Func tokenCredentialFactory) { _serviceCollection.Configure(options => options.CredentialFactory = tokenCredentialFactory); return this; diff --git a/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientServiceCollectionExtensions.cs b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientServiceCollectionExtensions.cs index afb7ea165a2aa..26c9ccef16e0c 100644 --- a/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientServiceCollectionExtensions.cs +++ b/sdk/core/Azure.Core.Extensions/src/Internal/AzureClientServiceCollectionExtensions.cs @@ -8,9 +8,9 @@ namespace Azure.Core.Extensions { public static class AzureClientServiceCollectionExtensions { - public static void AddAzureClients(this IServiceCollection collection, Action configureClients) + public static void AddAzureClients(this IServiceCollection collection, Action configureClients) { - configureClients(new AzureClientsBuilder(collection)); + configureClients(new AzureClientFactoryBuilder(collection)); } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs b/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs index 012f9b87ee877..aec5710d92999 100644 --- a/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs +++ b/sdk/core/Azure.Core.Extensions/tests/TestClientsBuilderExtensions.cs @@ -8,25 +8,25 @@ namespace Azure.Core.Extensions.Tests internal static class TestClientsBuilderExtensions { public static IAzureClientBuilder AddTestClient(this TBuilder builder, string connectionString) - where TBuilder: IAzureClientsBuilder + where TBuilder: IAzureClientFactoryBuilder { return builder.RegisterClientFactory(options => new TestClient(connectionString, options)); } public static IAzureClientBuilder AddTestClient(this TBuilder builder, Uri uri) - where TBuilder: IAzureClientsBuilder + where TBuilder: IAzureClientFactoryBuilder { return builder.RegisterClientFactory(options => new TestClient(uri, options)); } public static IAzureClientBuilder AddTestClient(this TBuilder builder, TConfiguration configuration) - where TBuilder: IAzureClientsBuilderWithConfiguration + where TBuilder: IAzureClientFactoryBuilderWithConfiguration { return builder.RegisterClientFactory(configuration); } public static IAzureClientBuilder AddTestClientWithCredentials(this TBuilder builder, TConfiguration configuration) - where TBuilder: IAzureClientsBuilderWithConfiguration + where TBuilder: IAzureClientFactoryBuilderWithConfiguration { return builder.RegisterClientFactory(configuration); } diff --git a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilder.cs similarity index 87% rename from sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs rename to sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilder.cs index 4a4365c5a2ec0..2d1b2a5b3e4b1 100644 --- a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilder.cs +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilder.cs @@ -6,7 +6,7 @@ namespace Azure.Core.Extensions { - public interface IAzureClientsBuilder + public interface IAzureClientFactoryBuilder { IAzureClientBuilder RegisterClientFactory(Func clientFactory) where TOptions : ClientOptions; } diff --git a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs b/sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilderWithConfiguration.cs similarity index 74% rename from sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs rename to sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilderWithConfiguration.cs index 2f3dc0ad4404d..1d50768977a34 100644 --- a/sdk/core/Azure.Core/src/Extensions/IAzureClientsBuilderWithConfiguration.cs +++ b/sdk/core/Azure.Core/src/Extensions/IAzureClientFactoryBuilderWithConfiguration.cs @@ -6,7 +6,7 @@ namespace Azure.Core.Extensions { - public interface IAzureClientsBuilderWithConfiguration: IAzureClientsBuilder + public interface IAzureClientFactoryBuilderWithConfiguration: IAzureClientFactoryBuilder { IAzureClientBuilder RegisterClientFactory(TConfiguration configuration) where TOptions : ClientOptions; } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs index 96b76e6c49572..7de41f4b11208 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientBuilderExtensions.cs @@ -24,7 +24,7 @@ public static IAzureClientBuilder AddSecretCl /// Registers a instance with connection options loaded from the provided instance. /// public static IAzureClientBuilder AddSecretClient(this TBuilder builder, TConfiguration configuration) - where TBuilder: IAzureClientsBuilderWithConfiguration + where TBuilder: IAzureClientFactoryBuilderWithConfiguration { return builder.RegisterClientFactory(configuration); } From e85c0e836609b65e0e0badc1d85abd8f0c316ce0 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 17 Jul 2019 10:26:19 -0700 Subject: [PATCH 17/17] Fix the build --- sdk/core/Azure.Core.Extensions/samples/Startup.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/core/Azure.Core.Extensions/samples/Startup.cs b/sdk/core/Azure.Core.Extensions/samples/Startup.cs index 3091850da3861..48089fdb38dc6 100644 --- a/sdk/core/Azure.Core.Extensions/samples/Startup.cs +++ b/sdk/core/Azure.Core.Extensions/samples/Startup.cs @@ -3,7 +3,6 @@ using System; using Azure.Core.Pipeline; -using Azure.Core.Pipeline.Policies; using Azure.Identity; using Azure.Security.KeyVault.Secrets; using Microsoft.AspNetCore.Builder;