Skip to content

Commit 14c9612

Browse files
authored
Azure AD Authentication for Service Bus and Queue API (#865)
1 parent 36fe66a commit 14c9612

File tree

16 files changed

+310
-120
lines changed

16 files changed

+310
-120
lines changed

dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSMessageQueueProvider.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ public SimpleMessageQueue Connect(string queueURL, out GXBaseCollection<SdtMessa
2121

2222
{
2323
MessageQueueProvider messageQueueProvider = new MessageQueueProvider();
24-
GXProperties properties = new GXProperties();
25-
properties.Add("QUEUE_AWSSQS_QUEUE_URL", queueURL);
24+
GXProperties properties = new GXProperties
25+
{
26+
{ "QUEUE_AWSSQS_QUEUE_URL", queueURL }
27+
};
2628
SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(AWS_SQS, properties, out GXBaseCollection<SdtMessages_Message> errorMessagesConnect, out bool successConnect);
2729
errorMessages = errorMessagesConnect;
2830
success = successConnect;
@@ -31,10 +33,12 @@ public SimpleMessageQueue Connect(string queueURL, out GXBaseCollection<SdtMessa
3133

3234
public GXProperties TransformAWSCredentials(GxUserType awsCredentials)
3335
{
34-
GXProperties properties = new GXProperties();
35-
properties.Add("QUEUE_AWSSQS_ACCESS_KEY", awsCredentials.GetPropertyValue<string>("Accesskey"));
36-
properties.Add("QUEUE_AWSSQS_SECRET_KEY", awsCredentials.GetPropertyValue<string>("Secretkey"));
37-
properties.Add("QUEUE_AWSSQS_REGION", awsCredentials.GetPropertyValue<string>("Region"));
36+
GXProperties properties = new GXProperties
37+
{
38+
{ "QUEUE_AWSSQS_ACCESS_KEY", awsCredentials.GetPropertyValue<string>("Accesskey") },
39+
{ "QUEUE_AWSSQS_SECRET_KEY", awsCredentials.GetPropertyValue<string>("Secretkey") },
40+
{ "QUEUE_AWSSQS_REGION", awsCredentials.GetPropertyValue<string>("Region") }
41+
};
3842
return properties;
3943
}
4044
}

dotnet/src/dotnetcore/Providers/Messaging/GXAmazonSQS/AWSQueue.cs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace GeneXus.Messaging.Queue
1616
public class AWSQueue : QueueBase, IQueue
1717
{
1818

19-
public static String Name = "AWSSQS";
19+
public static string Name = "AWSSQS";
2020
const string ACCESS_KEY = "ACCESS_KEY";
2121
const string SECRET_ACCESS_KEY = "SECRET_KEY";
2222
const string REGION = "REGION";
@@ -313,13 +313,14 @@ private MessageQueueResult SetupMessageQueueResult(SendMessageResponse response)
313313
messageQueueResult.MessageId = response.MessageId;
314314
messageQueueResult.MessageStatus = MessageQueueResultStatus.Sent;
315315

316-
messageQueueResult.MessageAttributes = new GXProperties();
317-
318-
messageQueueResult.MessageAttributes.Add("MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes);
319-
messageQueueResult.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes);
320-
messageQueueResult.MessageAttributes.Add("ContentLength", response.ContentLength.ToString());
321-
messageQueueResult.MessageAttributes.Add("MD5OfMessageBody", response.MD5OfMessageBody);
322-
messageQueueResult.MessageAttributes.Add("SequenceNumber", response.SequenceNumber);
316+
messageQueueResult.MessageAttributes = new GXProperties
317+
{
318+
{ "MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes },
319+
{ "MD5OfMessageAttributes", response.MD5OfMessageAttributes },
320+
{ "ContentLength", response.ContentLength.ToString() },
321+
{ "MD5OfMessageBody", response.MD5OfMessageBody },
322+
{ "SequenceNumber", response.SequenceNumber }
323+
};
323324

324325
Type t = response.ResponseMetadata.GetType();
325326
PropertyInfo[] props = t.GetProperties();
@@ -342,12 +343,13 @@ private MessageQueueResult SetupMessageQueueResult(SendMessageBatchResultEntry r
342343
messageQueueResult.MessageId = response.Id;
343344
messageQueueResult.MessageStatus = MessageQueueResultStatus.Sent;
344345

345-
messageQueueResult.MessageAttributes = new GXProperties();
346-
347-
messageQueueResult.MessageAttributes.Add("MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes);
348-
messageQueueResult.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes);
349-
messageQueueResult.MessageAttributes.Add("MD5OfMessageBody", response.MD5OfMessageBody);
350-
messageQueueResult.MessageAttributes.Add("SequenceNumber", response.SequenceNumber);
346+
messageQueueResult.MessageAttributes = new GXProperties
347+
{
348+
{ "MD5OfMessageSystemAttributes", response.MD5OfMessageSystemAttributes },
349+
{ "MD5OfMessageAttributes", response.MD5OfMessageAttributes },
350+
{ "MD5OfMessageBody", response.MD5OfMessageBody },
351+
{ "SequenceNumber", response.SequenceNumber }
352+
};
351353
return messageQueueResult;
352354
}
353355

@@ -378,11 +380,12 @@ private SimpleQueueMessage SetupSimpleQueueMessage(Message response)
378380
simpleQueueMessage.MessageBody = response.Body;
379381
simpleQueueMessage.MessageHandleId = response.ReceiptHandle;
380382

381-
simpleQueueMessage.MessageAttributes = new GXProperties();
382-
383-
simpleQueueMessage.MessageAttributes.Add("MD5OfMessageAttributes", response.MD5OfMessageAttributes);
384-
simpleQueueMessage.MessageAttributes.Add("MD5OfBody", response.MD5OfBody);
385-
383+
simpleQueueMessage.MessageAttributes = new GXProperties
384+
{
385+
{ "MD5OfMessageAttributes", response.MD5OfMessageAttributes },
386+
{ "MD5OfBody", response.MD5OfBody }
387+
};
388+
386389
foreach (var messageAttribute in response.MessageAttributes)
387390
{
388391
MessageAttributeValue messageAttributeValue = messageAttribute.Value;

dotnet/src/dotnetcore/Providers/Messaging/GXAzureEventGrid/AzureEventGrid.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ private void Initialize(GXService providerService)
4343
else
4444
//Try authenticating using AD
4545
{
46+
ChainedTokenCredential credential = new ChainedTokenCredential(new ManagedIdentityCredential(), new ManagedIdentityCredential(Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")), new EnvironmentCredential(), new AzureCliCredential());
4647
GXLogging.Debug(logger,"Authentication using Oauth 2.0.");
4748
_client = new EventGridPublisherClient(
4849
new Uri(_endpoint),
49-
new DefaultAzureCredential());
50+
credential);
5051
}
5152
}
5253
else

dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureMessageQueueProvider.cs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,35 @@
33

44
namespace GeneXus.Messaging.Queue
55
{
6+
/// <summary>
7+
/// Implementation of AzureQueue.MessageQueueProvider external object.
8+
/// </summary>
9+
///
610
public class AzureMessageQueueProvider
711
{
8-
private const string AZUREQUEUE = "AZUREQUEUE";
9-
public SimpleMessageQueue Connect(string queueName, string queueURL, out GXBaseCollection<SdtMessages_Message> errorMessages, out bool success)
12+
public SimpleMessageQueue Connect(string queueName, string connectionString, out GXBaseCollection<SdtMessages_Message> errorMessages, out bool success)
1013
{
1114
MessageQueueProvider messageQueueProvider = new MessageQueueProvider();
12-
GXProperties properties = new GXProperties();
13-
properties.Add("QUEUE_AZUREQUEUE_QUEUENAME", queueName);
14-
properties.Add("QUEUE_AZUREQUEUE_CONNECTIONSTRING", queueURL);
15-
SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(AZUREQUEUE, properties, out GXBaseCollection<SdtMessages_Message> errorMessagesConnect, out bool successConnect);
15+
GXProperties properties = new GXProperties
16+
{
17+
{ PropertyConstants.QUEUE_AZUREQUEUE_QUEUENAME, queueName },
18+
{ PropertyConstants.QUEUE_AZUREQUEUE_CONNECTIONSTRING, connectionString },
19+
{ PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.Password.ToString()}
20+
};
21+
SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(PropertyConstants.AZURE_QUEUE_PROVIDERTYPENAME, properties, out GXBaseCollection<SdtMessages_Message> errorMessagesConnect, out bool successConnect);
22+
errorMessages = errorMessagesConnect;
23+
success = successConnect;
24+
return simpleMessageQueue;
25+
}
26+
public SimpleMessageQueue Authenticate(string queueURI, out GXBaseCollection<SdtMessages_Message> errorMessages, out bool success)
27+
{
28+
MessageQueueProvider messageQueueProvider = new MessageQueueProvider();
29+
GXProperties properties = new GXProperties
30+
{
31+
{ PropertyConstants.QUEUE_AZUREQUEUE_QUEUEURI, queueURI },
32+
{ PropertyConstants.AUTHENTICATION_METHOD, AuthenticationMethod.ActiveDirectory.ToString()}
33+
};
34+
SimpleMessageQueue simpleMessageQueue = messageQueueProvider.Connect(PropertyConstants.AZURE_QUEUE_PROVIDERTYPENAME, properties, out GXBaseCollection<SdtMessages_Message> errorMessagesConnect, out bool successConnect);
1635
errorMessages = errorMessagesConnect;
1736
success = successConnect;
1837
return simpleMessageQueue;

dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/AzureQueue.cs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Reflection;
4+
using Azure.Identity;
45
using Azure.Storage.Queues;
56
using Azure.Storage.Queues.Models;
67
using GeneXus.Messaging.Common;
78
using GeneXus.Services;
89
using GeneXus.Utils;
10+
using log4net;
911

1012
namespace GeneXus.Messaging.Queue
1113
{
1214
public class AzureQueue : QueueBase, IQueue
1315
{
16+
public static string Name = "AZUREQUEUE";
1417

15-
public static String Name = "AZUREQUEUE";
16-
const string QUEUE_NAME = "QUEUENAME";
17-
const string QUEUE_CONNECTION_STRING = "CONNECTIONSTRING";
18-
18+
static readonly ILog logger = LogManager.GetLogger(typeof(AzureQueue));
1919
QueueClient _queueClient { get; set; }
2020
private string _queueName { get; set; }
2121
private string _connectionString { get; set; }
22+
private string _queueURI { get; set; }
2223

2324
public AzureQueue() : this(null)
24-
{
25-
}
25+
{}
2626

2727
public AzureQueue(GXService providerService) : base(providerService)
2828
{
@@ -31,16 +31,28 @@ public AzureQueue(GXService providerService) : base(providerService)
3131

3232
private void Initialize(GXService providerService)
3333
{
34-
ServiceSettings serviceSettings = new("QUEUE", Name, providerService);
35-
_queueName = serviceSettings.GetEncryptedPropertyValue(QUEUE_NAME);
36-
_connectionString = serviceSettings.GetEncryptedPropertyValue(QUEUE_CONNECTION_STRING);
34+
ServiceSettings serviceSettings = new(PropertyConstants.QUEUE_SERVICE_NAME, Name, providerService);
35+
_queueName = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.QUEUENAME);
36+
_connectionString = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.CONNECTIONSTRING);
37+
_queueURI = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.QUEUEURI);
38+
string authenticationMethod = serviceSettings.GetPropertiesValue(PropertyConstants.AUTHENTICATION_METHOD);
3739

3840
QueueClientOptions queueClientOptions = new QueueClientOptions()
3941
{
4042
MessageEncoding = QueueMessageEncoding.Base64
4143
};
4244

43-
_queueClient = new QueueClient(_connectionString, _queueName, queueClientOptions);
45+
if (authenticationMethod.Equals(AuthenticationMethod.ActiveDirectory.ToString()))
46+
{
47+
ChainedTokenCredential credential = new ChainedTokenCredential(new ManagedIdentityCredential(), new ManagedIdentityCredential(Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")), new EnvironmentCredential(), new AzureCliCredential());
48+
_queueClient = new QueueClient(new Uri(_queueURI), credential,queueClientOptions);
49+
GXLogging.Debug(logger, "Authenticate to Azure Storage Queue using Active Directory authentication.");
50+
}
51+
else
52+
{
53+
_queueClient = new QueueClient(_connectionString, _queueName, queueClientOptions);
54+
GXLogging.Debug(logger, "Authenticate to Azure Storage Queue using Access Keys.");
55+
}
4456
}
4557

4658
QueueClient QueueClient
@@ -59,11 +71,6 @@ public AzureQueue(string connectionString, string queueName)
5971
_connectionString = connectionString;
6072
}
6173

62-
//public AzureQueue(Uri uri, TokenCredential tokenCredential)
63-
//{
64-
//_queueClient = new QueueClient(uri, tokenCredential);
65-
//}
66-
6774
public bool GetMessageFromException(Exception ex, SdtMessages_Message msg)
6875
{
6976
try

dotnet/src/dotnetcore/Providers/Messaging/GXAzureQueue/GXAzureQueue.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10+
<PackageReference Include="Azure.Identity" Version="1.9.0" />
1011
<PackageReference Include="Azure.Storage.Queues" Version="12.15.0" />
1112
</ItemGroup>
1213

dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/AzureServiceBus.cs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,27 @@
44
using System.Reflection;
55
using System.Runtime.Serialization;
66
using System.Threading.Tasks;
7+
using Azure.Identity;
78
using Azure.Messaging.ServiceBus;
89
using GeneXus.Messaging.Common;
910
using GeneXus.Services;
1011
using GeneXus.Utils;
12+
using log4net;
1113

1214
namespace GeneXus.Messaging.GXAzureServiceBus
1315
{
1416
public class AzureServiceBus : MessageBrokerBase, IMessageBroker
1517
{
1618
private const int MAX_MESSAGES_DEFAULT = 10;
1719
private const short LOCK_DURATION = 5;
18-
public static String Name = "AZURESB";
20+
public static string Name = "AZURESB";
21+
static readonly ILog logger = LogManager.GetLogger(typeof(AzureServiceBus));
1922

2023
private ConcurrentDictionary<string, Tuple<DateTime, ServiceBusReceivedMessage>> m_messages = new ConcurrentDictionary<string, Tuple<DateTime, ServiceBusReceivedMessage>>();
2124
ServiceBusClient _serviceBusClient { get; set; }
2225
private string _queueOrTopicName { get; set; }
2326
private string _connectionString { get; set; }
27+
private string _fullyqualifiedNamespace { get; set; }
2428
private string _subscriptionName { get; set; }
2529
private ServiceBusSender _sender { get; set; }
2630
private ServiceBusReceiver _receiver { get; set; }
@@ -41,15 +45,17 @@ private void Initialize(GXService providerService)
4145
_queueOrTopicName = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.QUEUE_NAME);
4246
_connectionString = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.QUEUE_CONNECTION_STRING);
4347
_subscriptionName = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.TOPIC_SUBSCRIPTION);
48+
_fullyqualifiedNamespace = serviceSettings.GetEncryptedPropertyValue(PropertyConstants.FULLYQUALIFIEDNAMESPACE);
49+
string authenticationMethod = serviceSettings.GetPropertiesValue(PropertyConstants.AUTHENTICATION_METHOD);
4450

45-
string sessionEnabled = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.SESSION_ENABLED);
51+
string sessionEnabled = serviceSettings.GetPropertiesValue(PropertyConstants.SESSION_ENABLED);
4652

4753
if (!string.IsNullOrEmpty(sessionEnabled))
4854
_sessionEnabled = Convert.ToBoolean(sessionEnabled);
4955
else
5056
_sessionEnabled = false;
5157

52-
string senderIdentifier = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.SENDER_IDENTIFIER);
58+
string senderIdentifier = serviceSettings.GetPropertiesValue(PropertyConstants.SENDER_IDENTIFIER);
5359

5460
ServiceBusSenderOptions serviceBusSenderOptions = new ServiceBusSenderOptions();
5561
if (!string.IsNullOrEmpty(senderIdentifier))
@@ -58,17 +64,28 @@ private void Initialize(GXService providerService)
5864
//TO DO Consider connection options here
5965
//https://docs.microsoft.com/en-us/javascript/api/@azure/service-bus/servicebusclientoptions?view=azure-node-latest#@azure-service-bus-servicebusclientoptions-websocketoptions
6066

61-
_serviceBusClient = new ServiceBusClient(_connectionString);
67+
if (authenticationMethod.Equals(AuthenticationMethod.ActiveDirectory.ToString()))
68+
{
69+
ChainedTokenCredential credential = new ChainedTokenCredential(new ManagedIdentityCredential(), new ManagedIdentityCredential(Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")), new EnvironmentCredential(), new AzureCliCredential());
70+
_serviceBusClient = new ServiceBusClient(_fullyqualifiedNamespace, credential);
71+
GXLogging.Debug(logger, "Authenticate to Azure Service Bus using Active Directory authentication.");
72+
}
73+
else
74+
{
75+
_serviceBusClient = new ServiceBusClient(_connectionString);
76+
GXLogging.Debug(logger, "Authenticate to Azure Service Bus using SAS authentication.");
77+
}
78+
6279
if (_serviceBusClient != null)
6380
{
6481
_sender = _serviceBusClient.CreateSender(_queueOrTopicName, serviceBusSenderOptions);
6582
if (!_sessionEnabled && _sender != null)
6683
{
6784
_serviceBusReceiverOptions = new ServiceBusReceiverOptions();
6885

69-
string receiveMode = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.RECEIVE_MODE);
70-
string prefetchCount = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.PREFETCH_COUNT);
71-
string receiverIdentifier = serviceSettings.GetEncryptedOptPropertyValue(PropertyConstants.RECEIVER_IDENTIFIER);
86+
string receiveMode = serviceSettings.GetPropertiesValue(PropertyConstants.RECEIVE_MODE);
87+
string prefetchCount = serviceSettings.GetPropertiesValue(PropertyConstants.PREFETCH_COUNT);
88+
string receiverIdentifier = serviceSettings.GetPropertiesValue(PropertyConstants.RECEIVER_IDENTIFIER);
7289

7390
if (!string.IsNullOrEmpty(receiveMode))
7491
_serviceBusReceiverOptions.ReceiveMode = (ServiceBusReceiveMode)Convert.ToInt16(receiveMode);

dotnet/src/dotnetcore/Providers/Messaging/GXAzureServiceBus/GXAzureServiceBus.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10+
<PackageReference Include="Azure.Identity" Version="1.9.0" />
1011
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.15.0" />
1112
</ItemGroup>
1213

0 commit comments

Comments
 (0)