Skip to content

Commit 762a7b2

Browse files
Support AAD auth (Azure#19892)
* Support AAD auth * Fix test * Add back provider * Fix processor binding * API and change log * Fix test * Undo test change * stop the hosts * try increasing timeout * volatile * unused code * debug * fix * Add debug statements * debug * semaphore * Fix for real * add back debug info * Add missing StopAsync call * remove logging
1 parent 4825853 commit 762a7b2

33 files changed

+769
-723
lines changed

sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
# Release History
22

3-
## 5.0.0-beta.2 (Unreleased)
3+
## 5.0.0-beta.2 (2021-04-07)
44

5+
### Added
6+
- Add AAD support
7+
8+
### Breaking Changes
9+
- Changed the API signatures for the methods in `MessagingProvider`.
10+
- Added `receiver` parameter to `MessageProcessor` constructor.
11+
- Added `client` parameter to `SessionMessageProcessor` constructor.
512

613
## 5.0.0-beta.1 (2021-03-23)
714

sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,25 @@ For local development, use the `local.settings.json` file to store the connectio
4141

4242
When deployed, use the [application settings](https://docs.microsoft.com/azure/azure-functions/functions-how-to-use-azure-function-app-settings) to set the connection string.
4343

44+
#### Managed identity authentication
45+
46+
If your environment has [managed identity](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=dotnet) enabled you can use it to authenticate the Service Bus extension.
47+
To use managed identity provide the `<connection_name>__fullyQualifiedNamespace` configuration setting.
48+
49+
```json
50+
{
51+
"Values": {
52+
"<connection_name>__fullyQualifiedNamespace": "<service_bus_namespace>.servicebus.windows.net"
53+
}
54+
}
55+
```
56+
57+
Or in the case of deployed app set the same setting in [application settings](https://docs.microsoft.com/azure/azure-functions/functions-how-to-use-azure-function-app-settings):
58+
59+
```
60+
<connection_name>__fullyQualifiedNamespace=<service_bus_namespace>.servicebus.windows.net
61+
```
62+
4463

4564
## Key concepts
4665

sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/api/Microsoft.Azure.WebJobs.Extensions.ServiceBus.netstandard2.0.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,24 @@ public enum EntityType
5151
}
5252
public partial class MessageProcessor
5353
{
54-
public MessageProcessor(Azure.Messaging.ServiceBus.ServiceBusProcessor processor) { }
54+
public MessageProcessor(Azure.Messaging.ServiceBus.ServiceBusProcessor processor, Azure.Messaging.ServiceBus.ServiceBusReceiver receiver) { }
55+
protected internal Azure.Messaging.ServiceBus.ServiceBusProcessor Processor { get { throw null; } set { } }
56+
protected internal Azure.Messaging.ServiceBus.ServiceBusReceiver Receiver { get { throw null; } set { } }
5557
public virtual System.Threading.Tasks.Task<bool> BeginProcessingMessageAsync(Microsoft.Azure.WebJobs.ServiceBus.ServiceBusMessageActions messageActions, Azure.Messaging.ServiceBus.ServiceBusReceivedMessage message, System.Threading.CancellationToken cancellationToken) { throw null; }
5658
public virtual System.Threading.Tasks.Task CompleteProcessingMessageAsync(Microsoft.Azure.WebJobs.ServiceBus.ServiceBusMessageActions messageActions, Azure.Messaging.ServiceBus.ServiceBusReceivedMessage message, Microsoft.Azure.WebJobs.Host.Executors.FunctionResult result, System.Threading.CancellationToken cancellationToken) { throw null; }
5759
}
5860
public partial class MessagingProvider
5961
{
60-
public MessagingProvider(Microsoft.Extensions.Options.IOptions<Microsoft.Azure.WebJobs.ServiceBus.ServiceBusOptions> serviceBusOptions) { }
61-
public virtual Azure.Messaging.ServiceBus.ServiceBusReceiver CreateBatchMessageReceiver(string entityPath, string connectionString) { throw null; }
62+
protected MessagingProvider() { }
63+
public MessagingProvider(Microsoft.Extensions.Options.IOptions<Microsoft.Azure.WebJobs.ServiceBus.ServiceBusOptions> options) { }
64+
public virtual Azure.Messaging.ServiceBus.ServiceBusReceiver CreateBatchMessageReceiver(Azure.Messaging.ServiceBus.ServiceBusClient client, string entityPath) { throw null; }
6265
public virtual Azure.Messaging.ServiceBus.ServiceBusClient CreateClient(string connectionString) { throw null; }
63-
public virtual Microsoft.Azure.WebJobs.ServiceBus.MessageProcessor CreateMessageProcessor(string entityPath, string connectionString) { throw null; }
64-
public virtual Azure.Messaging.ServiceBus.ServiceBusSender CreateMessageSender(string entityPath, string connectionString) { throw null; }
65-
public virtual Azure.Messaging.ServiceBus.ServiceBusProcessor CreateProcessor(string entityPath, string connectionString) { throw null; }
66-
public virtual Microsoft.Azure.WebJobs.ServiceBus.SessionMessageProcessor CreateSessionMessageProcessor(string entityPath, string connectionString) { throw null; }
66+
public virtual Azure.Messaging.ServiceBus.ServiceBusClient CreateClient(string fullyQualifiedNamespace, Azure.Core.TokenCredential credential) { throw null; }
67+
public virtual Microsoft.Azure.WebJobs.ServiceBus.MessageProcessor CreateMessageProcessor(Azure.Messaging.ServiceBus.ServiceBusClient client, string entityPath) { throw null; }
68+
public virtual Azure.Messaging.ServiceBus.ServiceBusSender CreateMessageSender(Azure.Messaging.ServiceBus.ServiceBusClient client, string entityPath) { throw null; }
69+
public virtual Azure.Messaging.ServiceBus.ServiceBusProcessor CreateProcessor(Azure.Messaging.ServiceBus.ServiceBusClient client, string entityPath) { throw null; }
70+
public virtual Microsoft.Azure.WebJobs.ServiceBus.SessionMessageProcessor CreateSessionMessageProcessor(Azure.Messaging.ServiceBus.ServiceBusClient client, string entityPath) { throw null; }
71+
public virtual Azure.Messaging.ServiceBus.ServiceBusSessionProcessor CreateSessionProcessor(Azure.Messaging.ServiceBus.ServiceBusClient client, string entityPath) { throw null; }
6772
}
6873
public partial class ServiceBusMessageActions
6974
{
@@ -78,7 +83,6 @@ public partial class ServiceBusOptions : Microsoft.Azure.WebJobs.Hosting.IOption
7883
{
7984
public ServiceBusOptions() { }
8085
public bool AutoCompleteMessages { get { throw null; } set { } }
81-
public string ConnectionString { get { throw null; } set { } }
8286
public System.Func<Azure.Messaging.ServiceBus.ProcessErrorEventArgs, System.Threading.Tasks.Task> ExceptionHandler { get { throw null; } set { } }
8387
public System.TimeSpan MaxAutoLockRenewalDuration { get { throw null; } set { } }
8488
public int MaxConcurrentCalls { get { throw null; } set { } }
@@ -104,7 +108,9 @@ public void Configure(Microsoft.Azure.WebJobs.IWebJobsBuilder builder) { }
104108
}
105109
public partial class SessionMessageProcessor
106110
{
107-
public SessionMessageProcessor(Azure.Messaging.ServiceBus.ServiceBusSessionProcessor processor) { }
111+
public SessionMessageProcessor(Azure.Messaging.ServiceBus.ServiceBusClient client, Azure.Messaging.ServiceBus.ServiceBusSessionProcessor processor) { }
112+
protected internal Azure.Messaging.ServiceBus.ServiceBusClient Client { get { throw null; } set { } }
113+
protected internal Azure.Messaging.ServiceBus.ServiceBusSessionProcessor Processor { get { throw null; } set { } }
108114
public virtual System.Threading.Tasks.Task<bool> BeginProcessingMessageAsync(Microsoft.Azure.WebJobs.ServiceBus.ServiceBusSessionMessageActions sessionActions, Azure.Messaging.ServiceBus.ServiceBusReceivedMessage message, System.Threading.CancellationToken cancellationToken) { throw null; }
109115
public virtual System.Threading.Tasks.Task CompleteProcessingMessageAsync(Microsoft.Azure.WebJobs.ServiceBus.ServiceBusSessionMessageActions sessionActions, Azure.Messaging.ServiceBus.ServiceBusReceivedMessage message, Microsoft.Azure.WebJobs.Host.Executors.FunctionResult result, System.Threading.CancellationToken cancellationToken) { throw null; }
110116
}

sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/src/Bindings/ServiceBusAttributeBindingProvider.cs

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
using System.Globalization;
77
using System.Reflection;
88
using System.Threading.Tasks;
9+
using Microsoft.Azure.WebJobs.Extensions.ServiceBus.Config;
910
using Microsoft.Azure.WebJobs.Host;
1011
using Microsoft.Azure.WebJobs.Host.Bindings;
12+
using Microsoft.Extensions.Azure;
1113
using Microsoft.Extensions.Configuration;
1214

1315
namespace Microsoft.Azure.WebJobs.ServiceBus.Bindings
@@ -25,33 +27,17 @@ internal class ServiceBusAttributeBindingProvider : IBindingProvider
2527
new AsyncCollectorArgumentBindingProvider());
2628

2729
private readonly INameResolver _nameResolver;
28-
private readonly ServiceBusOptions _options;
29-
private readonly IConfiguration _configuration;
3030
private readonly MessagingProvider _messagingProvider;
31+
private readonly ServiceBusClientFactory _clientFactory;
3132

32-
public ServiceBusAttributeBindingProvider(INameResolver nameResolver, ServiceBusOptions options, IConfiguration configuration, MessagingProvider messagingProvider)
33+
public ServiceBusAttributeBindingProvider(
34+
INameResolver nameResolver,
35+
MessagingProvider messagingProvider,
36+
ServiceBusClientFactory clientFactory)
3337
{
34-
if (nameResolver == null)
35-
{
36-
throw new ArgumentNullException(nameof(nameResolver));
37-
}
38-
if (configuration == null)
39-
{
40-
throw new ArgumentNullException(nameof(configuration));
41-
}
42-
if (options == null)
43-
{
44-
throw new ArgumentNullException(nameof(options));
45-
}
46-
if (messagingProvider == null)
47-
{
48-
throw new ArgumentNullException(nameof(messagingProvider));
49-
}
50-
51-
_nameResolver = nameResolver;
52-
_options = options;
53-
_configuration = configuration;
54-
_messagingProvider = messagingProvider;
38+
_nameResolver = nameResolver ?? throw new ArgumentNullException(nameof(nameResolver));
39+
_messagingProvider = messagingProvider ?? throw new ArgumentNullException(nameof(messagingProvider));
40+
_clientFactory = clientFactory ?? throw new ArgumentNullException(nameof(clientFactory));
5541
}
5642

5743
public Task<IBinding> TryCreateAsync(BindingProviderContext context)
@@ -69,7 +55,7 @@ public Task<IBinding> TryCreateAsync(BindingProviderContext context)
6955
return Task.FromResult<IBinding>(null);
7056
}
7157

72-
string queueOrTopicName = Resolve(attribute.QueueOrTopicName);
58+
string queueOrTopicName = _nameResolver.ResolveWholeString(attribute.QueueOrTopicName);
7359
IBindableServiceBusPath path = BindableServiceBusPath.Create(queueOrTopicName);
7460
ValidateContractCompatibility(path, context.BindingDataContract);
7561

@@ -79,10 +65,9 @@ public Task<IBinding> TryCreateAsync(BindingProviderContext context)
7965
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Can't bind ServiceBus to type '{0}'.", parameter.ParameterType));
8066
}
8167

82-
attribute.Connection = Resolve(attribute.Connection);
83-
ServiceBusAccount account = new ServiceBusAccount(_options, _configuration, attribute);
68+
attribute.Connection = _nameResolver.ResolveWholeString(attribute.Connection);
8469

85-
IBinding binding = new ServiceBusBinding(parameter.Name, argumentBinding, account, path, attribute, _messagingProvider);
70+
IBinding binding = new ServiceBusBinding(parameter.Name, argumentBinding, path, attribute, _messagingProvider, _clientFactory);
8671
return Task.FromResult<IBinding>(binding);
8772
}
8873

@@ -105,15 +90,5 @@ private static void ValidateContractCompatibility(IBindableServiceBusPath path,
10590
}
10691
}
10792
}
108-
109-
private string Resolve(string queueName)
110-
{
111-
if (_nameResolver == null)
112-
{
113-
return queueName;
114-
}
115-
116-
return _nameResolver.ResolveWholeString(queueName);
117-
}
11893
}
11994
}

sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/src/Bindings/ServiceBusBinding.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Globalization;
66
using System.Threading.Tasks;
7+
using Microsoft.Azure.WebJobs.Extensions.ServiceBus.Config;
78
using Microsoft.Azure.WebJobs.Host.Bindings;
89
using Microsoft.Azure.WebJobs.Host.Converters;
910
using Microsoft.Azure.WebJobs.Host.Protocols;
@@ -14,21 +15,27 @@ internal class ServiceBusBinding : IBinding
1415
{
1516
private readonly string _parameterName;
1617
private readonly IArgumentBinding<ServiceBusEntity> _argumentBinding;
17-
private readonly ServiceBusAccount _account;
1818
private readonly IBindableServiceBusPath _path;
1919
private readonly IAsyncObjectToTypeConverter<ServiceBusEntity> _converter;
20-
private readonly EntityType _entityType;
2120
private readonly MessagingProvider _messagingProvider;
22-
23-
public ServiceBusBinding(string parameterName, IArgumentBinding<ServiceBusEntity> argumentBinding, ServiceBusAccount account, IBindableServiceBusPath path, ServiceBusAttribute attr, MessagingProvider messagingProvider)
21+
private readonly ServiceBusClientFactory _clientFactory;
22+
private readonly ServiceBusAttribute _attribute;
23+
24+
public ServiceBusBinding(
25+
string parameterName,
26+
IArgumentBinding<ServiceBusEntity> argumentBinding,
27+
IBindableServiceBusPath path,
28+
ServiceBusAttribute attribute,
29+
MessagingProvider messagingProvider,
30+
ServiceBusClientFactory clientFactory)
2431
{
2532
_parameterName = parameterName;
2633
_argumentBinding = argumentBinding;
27-
_account = account;
2834
_path = path;
29-
_entityType = attr.EntityType;
3035
_messagingProvider = messagingProvider;
31-
_converter = new OutputConverter<string>(new StringToServiceBusEntityConverter(account, _path, _entityType, _messagingProvider));
36+
_clientFactory = clientFactory;
37+
_attribute = attribute;
38+
_converter = new OutputConverter<string>(new StringToServiceBusEntityConverter(_attribute, _path, _messagingProvider, _clientFactory));
3239
}
3340

3441
public bool FromAttribute
@@ -41,12 +48,12 @@ public async Task<IValueProvider> BindAsync(BindingContext context)
4148
context.CancellationToken.ThrowIfCancellationRequested();
4249

4350
string boundQueueName = _path.Bind(context.BindingData);
44-
var messageSender = _messagingProvider.CreateMessageSender(boundQueueName, _account.ConnectionString);
51+
var messageSender = _messagingProvider.CreateMessageSender(_clientFactory.CreateClientFromSetting(_attribute.Connection), boundQueueName);
4552

4653
var entity = new ServiceBusEntity
4754
{
4855
MessageSender = messageSender,
49-
EntityType = _entityType
56+
EntityType = _attribute.EntityType
5057
};
5158

5259
return await BindAsync(entity, context.ValueContext).ConfigureAwait(false);

sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/src/Bindings/StringToServiceBusEntityConverter.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,35 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

4-
using System;
4+
using Microsoft.Azure.WebJobs.Extensions.ServiceBus.Config;
55
using System.Threading;
66
using System.Threading.Tasks;
77

88
namespace Microsoft.Azure.WebJobs.ServiceBus.Bindings
99
{
1010
internal class StringToServiceBusEntityConverter : IAsyncConverter<string, ServiceBusEntity>
1111
{
12-
private readonly ServiceBusAccount _account;
12+
private readonly ServiceBusAttribute _attribute;
1313
private readonly IBindableServiceBusPath _defaultPath;
1414
private readonly EntityType _entityType;
1515
private readonly MessagingProvider _messagingProvider;
16+
private readonly ServiceBusClientFactory _clientFactory;
1617

17-
public StringToServiceBusEntityConverter(ServiceBusAccount account, IBindableServiceBusPath defaultPath, EntityType entityType, MessagingProvider messagingProvider)
18+
public StringToServiceBusEntityConverter(ServiceBusAttribute attribute, IBindableServiceBusPath defaultPath, MessagingProvider messagingProvider, ServiceBusClientFactory clientFactory)
1819
{
19-
_account = account;
20+
_attribute = attribute;
2021
_defaultPath = defaultPath;
21-
_entityType = entityType;
22+
_entityType = _attribute.EntityType;
2223
_messagingProvider = messagingProvider;
24+
_clientFactory = clientFactory;
2325
}
2426

2527
public Task<ServiceBusEntity> ConvertAsync(string input, CancellationToken cancellationToken)
2628
{
2729
string queueOrTopicName;
2830

2931
// For convenience, treat an an empty string as a request for the default value.
30-
if (String.IsNullOrEmpty(input) && _defaultPath.IsBound)
32+
if (string.IsNullOrEmpty(input) && _defaultPath.IsBound)
3133
{
3234
queueOrTopicName = _defaultPath.Bind(null);
3335
}
@@ -37,7 +39,7 @@ public Task<ServiceBusEntity> ConvertAsync(string input, CancellationToken cance
3739
}
3840

3941
cancellationToken.ThrowIfCancellationRequested();
40-
var messageSender = _messagingProvider.CreateMessageSender(queueOrTopicName, _account.ConnectionString);
42+
var messageSender = _messagingProvider.CreateMessageSender(_clientFactory.CreateClientFromSetting(_attribute.Connection), queueOrTopicName);
4143

4244
var entity = new ServiceBusEntity
4345
{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.Azure.WebJobs.Extensions.Clients.Shared;
5+
using Microsoft.Extensions.Configuration;
6+
7+
namespace Microsoft.Azure.WebJobs.Extensions.ServiceBus.Config
8+
{
9+
internal static class ConfigurationExtensions
10+
{
11+
// The order of priority is intentionally flipped from what is defined in
12+
// WebJobsConfigurationExtensions.GetWebJobsConnectionStringSection for back compat with the Track 1
13+
// Service Bus extensions.
14+
public static IConfigurationSection GetWebJobsConnectionStringSectionServiceBus(this IConfiguration configuration, string connectionStringName)
15+
{
16+
// first try a direct unprefixed lookup
17+
IConfigurationSection section = WebJobsConfigurationExtensions.GetConnectionStringOrSetting(configuration, connectionStringName);
18+
19+
if (!section.Exists())
20+
{
21+
// next try prefixing
22+
string prefixedConnectionStringName = WebJobsConfigurationExtensions.GetPrefixedConnectionStringName(connectionStringName);
23+
section = WebJobsConfigurationExtensions.GetConnectionStringOrSetting(configuration, prefixedConnectionStringName);
24+
}
25+
26+
return section;
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)