Skip to content

Commit aad3998

Browse files
committed
Add RBAC support for Service Bus authentication
Introduce `UseRBACForServiceBus` flag in `AppConfig.cs` to toggle between RBAC and SAS for Service Bus authentication. Default is false. Update logic to parse this setting and conditionally initialize `ServiceBusClient` in `CallQueueProcessor.cs` using AAD credentials if RBAC is enabled. Remove old RBAC setup in `GraphImportTests.cs`. Add logging for RBAC initialization. Maintain backward compatibility with SAS.
1 parent 97a30c5 commit aad3998

File tree

4 files changed

+53
-21
lines changed

4 files changed

+53
-21
lines changed

src/AnalyticsEngine/Common/Entities/Config/AppConfig.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ public AppConfig()
7575
this.MetadataRefreshMinutes = metadataRefreshMinutesInt;
7676
}
7777
}
78+
79+
// New optional flag: UseRBACForServiceBus (default false)
80+
var useRbacForSb = ConfigurationManager.AppSettings.Get("UseRBACForServiceBus");
81+
if (!string.IsNullOrEmpty(useRbacForSb))
82+
{
83+
bool parsed = false;
84+
if (bool.TryParse(useRbacForSb, out parsed))
85+
{
86+
this.UseRBACForServiceBus = parsed;
87+
}
88+
}
7889
}
7990

8091
public string BuildLabel { get; set; }
@@ -141,5 +152,11 @@ public List<string> ContentTypesToRead
141152
/// Optional filter for user groups
142153
/// </summary>
143154
public string UserGroupsFilter { get; set; }
155+
156+
/// <summary>
157+
/// When true, use RBAC (AAD) auth to connect to Service Bus instead of SAS connection string.
158+
/// Default false.
159+
/// </summary>
160+
public bool UseRBACForServiceBus { get; set; } = false;
144161
}
145162
}

src/AnalyticsEngine/Tests.UnitTests/App.Release.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<add key="ClientSecret" value="__ClientSecret__" />
2020
<add key="TenantGUID" value="__TenantGUID__" />
2121
<add key="TenantDomain" value="__TenantDomain__" />
22+
<add key="UseRBACForServiceBus" value="true" />
2223

2324
<!--Cognitive endpoint-->
2425
<add key="CognitiveEndpoint" value="__CognitiveEndpoint__" />

src/AnalyticsEngine/Tests.UnitTests/GraphImportTests.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -277,15 +277,6 @@ public async Task CallQueueProcessorTest()
277277
var fqNamespace = sbConnectionProps.Endpoint.Host; // e.g. namespace.servicebus.windows.net
278278
var queueName = sbConnectionProps.EntityPath; // queue name
279279

280-
// Build credential from app registration (client ID / secret or certificate)
281-
// NOTE: Service Bus RBAC requires Standard or Premium tier and the app registration must have role
282-
// 'Azure Service Bus Data Sender' at namespace or queue scope. Basic tier does NOT support AAD RBAC.
283-
// Using direct ClientSecretCredential avoids any graph-specific token logic.
284-
telemetry.LogInformation($"Creating Service Bus client with client ID {config.ClientID}");
285-
var sbCredential = new Azure.Identity.ClientSecretCredential(config.TenantGUID.ToString(), config.ClientID, config.ClientSecret);
286-
var sbClient = new ServiceBusClient(fqNamespace, sbCredential);
287-
var sbSender = sbClient.CreateSender(queueName);
288-
289280
using (var db = new AnalyticsEntitiesContext())
290281
{
291282
var callCountInitial = await db.CallRecords.CountAsync();
@@ -300,6 +291,8 @@ public async Task CallQueueProcessorTest()
300291
_ = callProcessor.BeginProcessCallsQueue();
301292

302293
// START TEST: Send fake msgs through SB - remember IDs
294+
var sbSender = callProcessor.ServiceBusClient.CreateSender(queueName);
295+
303296
var testIds = new List<string>();
304297
for (int i = 0; i < CALLS_TO_ADD; i++)
305298
{

src/AnalyticsEngine/WebJob.Office365ActivityImporter.Engine/Graph/Calls/CallQueueProcessor.cs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Collections.Generic;
1212
using System.Threading.Tasks;
1313
using WebJob.Office365ActivityImporter.Engine.Entities.Serialisation;
14+
using Azure.Identity; // Added for ClientSecretCredential
1415

1516
namespace WebJob.Office365ActivityImporter.Engine.Graph.Calls
1617
{
@@ -32,7 +33,7 @@ public class CallQueueProcessor : IDisposable
3233
private ManualGraphCallClient _graphCallClient;
3334
private bool _isInitialised = false;
3435

35-
36+
public ServiceBusClient ServiceBusClient => _sbClient;
3637
public static CallQueueProcessor _singleton = null;
3738
public static async Task<CallQueueProcessor> GetCallQueueProcessor(AppConfig config, string thisTenantId, ManualGraphCallClient graphCallClient)
3839
{
@@ -53,18 +54,38 @@ private CallQueueProcessor(AppConfig config, string thisTenantId)
5354
_auth = new GraphAppIndentityOAuthContext(_telemetry, config.ClientID, config.TenantGUID.ToString(), config.ClientSecret, config.KeyVaultUrl, config.UseClientCertificate);
5455
this._thisTenantId = thisTenantId;
5556

56-
var sbCredential = new Azure.Identity.ClientSecretCredential(config.TenantGUID.ToString(), config.ClientID, config.ClientSecret);
57-
58-
_sbClient = new ServiceBusClient(config.ConnectionStrings.ServiceBusConnectionString, sbCredential);
59-
var sbConnectionInfo = ServiceBusConnectionStringProperties.Parse(config.ConnectionStrings.ServiceBusConnectionString);
60-
_processor = _sbClient.CreateProcessor(sbConnectionInfo.EntityPath, new ServiceBusProcessorOptions
57+
// If RBAC is enabled, build ServiceBusClient using AAD credential
58+
if (config.UseRBACForServiceBus)
59+
{
60+
_telemetry.LogInformation("Initializing ServiceBusClient using RBAC (ClientSecretCredential).");
61+
var credential = new ClientSecretCredential(config.TenantGUID.ToString(), config.ClientID, config.ClientSecret);
62+
// Extract fully qualified namespace from connection string (Endpoint=sb://namespace.servicebus.windows.net/;...)
63+
var sbProps = ServiceBusConnectionStringProperties.Parse(config.ConnectionStrings.ServiceBusConnectionString);
64+
var fullyQualifiedNamespace = sbProps.FullyQualifiedNamespace; // e.g. namespace.servicebus.windows.net
65+
_sbClient = new ServiceBusClient(fullyQualifiedNamespace, credential);
66+
_processor = _sbClient.CreateProcessor(sbProps.EntityPath, new ServiceBusProcessorOptions
67+
{
68+
MaxConcurrentCalls = 10,
69+
PrefetchCount = 0,
70+
ReceiveMode = ServiceBusReceiveMode.PeekLock,
71+
MaxAutoLockRenewalDuration = TimeSpan.FromHours(24), // Queue should be configured for 5 minute lock timeout
72+
AutoCompleteMessages = false // Messages are completed only when the migrator has succeeded to migrate the file
73+
});
74+
}
75+
else
6176
{
62-
MaxConcurrentCalls = 10,
63-
PrefetchCount = 0,
64-
ReceiveMode = ServiceBusReceiveMode.PeekLock,
65-
MaxAutoLockRenewalDuration = TimeSpan.FromHours(24), // Queue should be configured for 5 minute lock timeout
66-
AutoCompleteMessages = false // Messages are completed only when the migrator has succeeded to migrate the file
67-
});
77+
// Legacy SAS connection string approach
78+
_sbClient = new ServiceBusClient(config.ConnectionStrings.ServiceBusConnectionString);
79+
var sbConnectionInfo = ServiceBusConnectionStringProperties.Parse(config.ConnectionStrings.ServiceBusConnectionString);
80+
_processor = _sbClient.CreateProcessor(sbConnectionInfo.EntityPath, new ServiceBusProcessorOptions
81+
{
82+
MaxConcurrentCalls = 10,
83+
PrefetchCount = 0,
84+
ReceiveMode = ServiceBusReceiveMode.PeekLock,
85+
MaxAutoLockRenewalDuration = TimeSpan.FromHours(24), // Queue should be configured for 5 minute lock timeout
86+
AutoCompleteMessages = false // Messages are completed only when the migrator has succeeded to migrate the file
87+
});
88+
}
6889
}
6990

7091
#endregion

0 commit comments

Comments
 (0)