Skip to content

Commit 6d4b603

Browse files
committed
Changes to run the tests with managed identity instead of connection strings
1 parent a09bdaf commit 6d4b603

29 files changed

+453
-92
lines changed

Directory.Packages.props

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
<RuntimePackageVersion>8.0.0</RuntimePackageVersion>
55
</PropertyGroup>
66
<ItemGroup>
7+
<PackageVersion Include="Azure.ResourceManager.ServiceBus" Version="1.1.0" />
8+
<PackageVersion Include="Azure.Security.KeyVault.Certificates" Version="4.8.0" />
9+
<PackageVersion Include="Azure.Security.KeyVault.Secrets" Version="4.8.0" />
10+
<PackageVersion Include="Microsoft.Azure.StackExchangeRedis" Version="3.2.1" />
711
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.0" />
8-
<PackageVersion Include="Azure.Core" Version="1.40.0" />
12+
<PackageVersion Include="Azure.Core" Version="1.44.1" />
913
<PackageVersion Include="Azure.Data.Tables" Version="12.8.0" />
10-
<PackageVersion Include="Azure.Identity" Version="1.12.0" />
14+
<PackageVersion Include="Azure.Identity" Version="1.13.2" />
1115
<PackageVersion Include="Azure.Messaging.EventGrid" Version="4.17.0" />
1216
<PackageVersion Include="Azure.Messaging.EventHubs" Version="5.9.2" />
1317
<PackageVersion Include="Azure.Messaging.EventHubs.Processor" Version="5.9.2" />
14-
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.15.0" />
18+
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.20.1" />
1519
<PackageVersion Include="Azure.Storage.Files.DataLake" Version="12.14.0" />
1620
<PackageVersion Include="Azure.Storage.Files.Shares" Version="12.14.0" />
1721
<PackageVersion Include="Azure.Storage.Queues" Version="12.14.0" />

samples/Quickstart/src/QuickstartSample.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="Azure.Identity" Version="1.12.0" />
12+
<PackageReference Include="Azure.Identity" Version="1.13.2" />
1313
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.21.0" />
1414
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
1515
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
@@ -29,7 +29,7 @@
2929
<ItemGroup Condition="'$(SdkVersion)' == 'local'">
3030
<ProjectReference Include="..\..\..\src\Microsoft.AzureHealth.DataServices.Core\Microsoft.AzureHealth.DataServices.Core.csproj" />
3131
</ItemGroup>
32-
32+
3333
<!-- If neither of the above, read version from SdkVersion -->
3434
<ItemGroup Condition="'$(SdkVersion)' != '' And '$(SdkVersion)' != 'local'">
3535
<PackageReference Include="Microsoft.AzureHealth.DataServices.Core" Version="$(SdkVersion)" />

samples/UseCaseSamples/ModifyCapabilityStatement/src/UseCaseSample.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="Azure.Identity" Version="1.12.0" />
12+
<PackageReference Include="Azure.Identity" Version="1.13.2" />
1313
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.21.0" />
1414
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
1515
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
@@ -28,7 +28,7 @@
2828
<ItemGroup Condition="'$(SdkVersion)' == 'local'">
2929
<ProjectReference Include="..\..\..\..\src\Microsoft.AzureHealth.DataServices.Core\Microsoft.AzureHealth.DataServices.Core.csproj" />
3030
</ItemGroup>
31-
31+
3232
<!-- If neither of the above, read version from SdkVersion -->
3333
<ItemGroup Condition="'$(SdkVersion)' != '' And '$(SdkVersion)' != 'local'">
3434
<PackageReference Include="Microsoft.AzureHealth.DataServices.Core" Version="$(SdkVersion)" />

src/Microsoft.AzureHealth.DataServices.Caching/Microsoft.AzureHealth.DataServices.Caching.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
<ItemGroup>
1313
<PackageReference Include="Azure.Identity" />
14+
<PackageReference Include="Microsoft.Azure.StackExchangeRedis" />
1415
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" />
1516
<PackageReference Include="Microsoft.Extensions.Hosting" />
1617
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />

src/Microsoft.AzureHealth.DataServices.Caching/StorageProviders/AzureBlobStorageCacheOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
public class AzureBlobStorageCacheOptions
77
{
88
/// <summary>
9+
/// Gets or sets the Azure Blob Storage Account URI.
10+
/// </summary>
11+
public Uri AccountUri { get; set; }
12+
13+
/// <summary>
914
/// Gets or sets the Azure Blob Storage connection string.
1015
/// </summary>
1116
public string ConnectionString { get; set; }

src/Microsoft.AzureHealth.DataServices.Caching/StorageProviders/AzureJsonBlobStorageProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public AzureJsonBlobStorageProvider(IOptions<AzureBlobStorageCacheOptions> optio
2727
}
2828
else
2929
{
30-
storage = new(new Uri(options.Value.BlobServiceEndpoint), new DefaultAzureCredential());
30+
storage = new(options.Value.AccountUri, new DefaultAzureCredential());
3131
}
3232

3333
container = options.Value.Container;

src/Microsoft.AzureHealth.DataServices.Caching/StorageProviders/RedisCacheOptions.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace Microsoft.AzureHealth.DataServices.Caching.StorageProviders
1+
using Azure.Identity;
2+
3+
namespace Microsoft.AzureHealth.DataServices.Caching.StorageProviders
24
{
35
/// <summary>
46
/// Options for redis cache backing store.
@@ -14,5 +16,10 @@ public class RedisCacheOptions
1416
/// Optional instance name
1517
/// </summary>
1618
public string InstanceName { get; set; }
19+
20+
/// <summary>
21+
/// Optional DefultAzureCredential
22+
/// </summary>
23+
public DefaultAzureCredential Credential { get; set; }
1724
}
1825
}

src/Microsoft.AzureHealth.DataServices.Caching/StorageProviders/RedisJsonStorageProvider.cs

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.Extensions.Hosting;
44
using Microsoft.Extensions.Options;
55
using Newtonsoft.Json;
6+
using StackExchange.Redis;
67

78
namespace Microsoft.AzureHealth.DataServices.Caching.StorageProviders
89
{
@@ -13,22 +14,46 @@ public class RedisJsonStorageProvider : ICacheBackingStoreProvider
1314
{
1415
private readonly IHost host;
1516
private readonly IDistributedCache redis;
17+
private readonly IDatabase redisDb;
1618

1719
/// <summary>
1820
/// Creates an instance of RedisJsonStorageProvider.
1921
/// </summary>
2022
/// <param name="options">Redis cache options.</param>
2123
public RedisJsonStorageProvider(IOptions<RedisCacheOptions> options)
2224
{
23-
host = Host.CreateDefaultBuilder()
24-
.ConfigureServices(services => services.AddStackExchangeRedisCache(op =>
25-
{
26-
op.Configuration = options.Value.ConnectionString;
27-
op.InstanceName = options.Value.InstanceName ?? string.Empty;
28-
}))
29-
.Build();
25+
if (!string.IsNullOrWhiteSpace(options.Value.ConnectionString))
26+
{
27+
// Case 1: Connection string
28+
host = Host.CreateDefaultBuilder()
29+
.ConfigureServices(services =>
30+
{
31+
services.AddStackExchangeRedisCache(op =>
32+
{
33+
op.Configuration = options.Value.ConnectionString;
34+
op.InstanceName = options.Value.InstanceName ?? string.Empty;
35+
});
36+
})
37+
.Build();
3038

31-
redis = host.Services.GetRequiredService<IDistributedCache>();
39+
redis = host.Services.GetRequiredService<IDistributedCache>();
40+
}
41+
else if (options.Value.Credential != null)
42+
{
43+
var cacheHostName = options.Value.InstanceName;
44+
var configurationOptions = ConfigurationOptions.Parse($"{cacheHostName}:6380");
45+
configurationOptions.Ssl = true;
46+
configurationOptions.AbortOnConnectFail = true;
47+
configurationOptions = configurationOptions.ConfigureForAzureWithTokenCredentialAsync(options.Value.Credential).GetAwaiter().GetResult();
48+
var connectionMultiplexer = ConnectionMultiplexer.ConnectAsync(configurationOptions).GetAwaiter().GetResult();
49+
redisDb = connectionMultiplexer.GetDatabase();
50+
}
51+
else
52+
{
53+
// No valid Redis configuration
54+
throw new InvalidOperationException(
55+
"No Redis connection string or DefaultAzureCredential provided for Redis cache.");
56+
}
3257
}
3358

3459
/// <summary>
@@ -41,7 +66,14 @@ public RedisJsonStorageProvider(IOptions<RedisCacheOptions> options)
4166
public async Task AddAsync<T>(string key, T value)
4267
{
4368
string json = JsonConvert.SerializeObject(value);
44-
await redis.SetStringAsync(key, json);
69+
if (redis != null)
70+
{
71+
await redis.SetStringAsync(key, json);
72+
}
73+
else if (redisDb != null)
74+
{
75+
await redisDb.StringSetAsync(key, json);
76+
}
4577
}
4678

4779
/// <summary>
@@ -53,7 +85,14 @@ public async Task AddAsync<T>(string key, T value)
5385
public async Task AddAsync(string key, object value)
5486
{
5587
string json = JsonConvert.SerializeObject(value);
56-
await redis.SetStringAsync(key, json);
88+
if (redis != null)
89+
{
90+
await redis.SetStringAsync(key, json);
91+
}
92+
else if (redisDb != null)
93+
{
94+
await redisDb.StringSetAsync(key, json);
95+
}
5796
}
5897

5998
/// <summary>
@@ -64,15 +103,18 @@ public async Task AddAsync(string key, object value)
64103
/// <returns>Object from cache.</returns>
65104
public async Task<T> GetAsync<T>(string key)
66105
{
67-
string json = await redis.GetStringAsync(key);
68-
if (json == null)
106+
string json = null;
107+
108+
if (redis != null)
69109
{
70-
return default;
110+
json = await redis.GetStringAsync(key);
71111
}
72-
else
112+
else if (redisDb != null)
73113
{
74-
return JsonConvert.DeserializeObject<T>(json);
114+
json = await redisDb.StringGetAsync(key);
75115
}
116+
117+
return json == null ? default : JsonConvert.DeserializeObject<T>(json);
76118
}
77119

78120
/// <summary>
@@ -82,7 +124,16 @@ public async Task<T> GetAsync<T>(string key)
82124
/// <returns>Item from cache as a JSON string.</returns>
83125
public async Task<string> GetAsync(string key)
84126
{
85-
return await redis.GetStringAsync(key);
127+
if (redis != null)
128+
{
129+
return await redis.GetStringAsync(key);
130+
}
131+
else if (redisDb != null)
132+
{
133+
return await redisDb.StringGetAsync(key);
134+
}
135+
136+
return null;
86137
}
87138

88139
/// <summary>
@@ -92,7 +143,15 @@ public async Task<string> GetAsync(string key)
92143
/// <returns>True if object removed otherwise false.</returns>
93144
public async Task<bool> RemoveAsync(string key)
94145
{
95-
await redis.RemoveAsync(key);
146+
if (redis != null)
147+
{
148+
await redis.RemoveAsync(key);
149+
}
150+
else if (redisDb != null)
151+
{
152+
await redisDb.KeyDeleteAsync(key);
153+
}
154+
96155
return true;
97156
}
98157
}

src/Microsoft.AzureHealth.DataServices.Channels/EventGridChannel.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Text;
33
using System.Threading.Tasks;
44
using Azure;
5+
using Azure.Identity;
56
using Azure.Messaging.EventGrid;
67
using Microsoft.AzureHealth.DataServices.Pipelines;
78
using Microsoft.AzureHealth.DataServices.Storage;
@@ -17,6 +18,7 @@ namespace Microsoft.AzureHealth.DataServices.Channels
1718
public class EventGridChannel : IInputChannel, IOutputChannel
1819
{
1920
private readonly string _fallbackStorageConnectionString;
21+
private readonly string _fallbackStorageAccountName;
2022
private readonly string _container;
2123
private readonly string _topic;
2224
private readonly string _accessKey;
@@ -25,6 +27,7 @@ public class EventGridChannel : IInputChannel, IOutputChannel
2527
private readonly string _dataVersion;
2628
private readonly ILogger _logger;
2729
private readonly StatusType _statusType;
30+
private readonly DefaultAzureCredential _credential;
2831
private EventGridPublisherClient _client;
2932
private StorageBlob _storage;
3033
private bool _disposed;
@@ -38,13 +41,15 @@ public class EventGridChannel : IInputChannel, IOutputChannel
3841
public EventGridChannel(IOptions<EventGridChannelOptions> options, ILogger<EventGridChannel> logger = null)
3942
{
4043
_fallbackStorageConnectionString = options.Value.FallbackStorageConnectionString;
44+
_fallbackStorageAccountName = options.Value.FallbackStorageAccountName;
4145
_container = options.Value.FallbackStorageContainer;
4246
_topic = options.Value.TopicUriString;
4347
_accessKey = options.Value.AccessKey;
4448
_subject = options.Value.Subject;
4549
_eventType = options.Value.EventType;
4650
_dataVersion = options.Value.DataVersion;
4751
_statusType = options.Value.ExecutionStatusType;
52+
_credential = options.Value.Credential;
4853
_logger = logger;
4954
}
5055

@@ -152,11 +157,25 @@ public async Task CloseAsync()
152157
/// <returns>Task</returns>
153158
public async Task OpenAsync()
154159
{
155-
_client = new EventGridPublisherClient(
156-
new Uri(_topic),
157-
new AzureKeyCredential(_accessKey));
160+
// Create Event Grid client
161+
if (!string.IsNullOrWhiteSpace(_accessKey))
162+
{
163+
_client = new EventGridPublisherClient(new Uri(_topic), new AzureKeyCredential(_accessKey));
164+
}
165+
else
166+
{
167+
// Use Managed Identity / Azure AD authentication
168+
_client = new EventGridPublisherClient(new Uri(_topic), _credential);
169+
}
158170

159-
_storage = new StorageBlob(_fallbackStorageConnectionString, null, null, null, _logger);
171+
if (!string.IsNullOrEmpty(_fallbackStorageConnectionString))
172+
{
173+
_storage = new StorageBlob(_fallbackStorageConnectionString, null, null, null, _logger);
174+
}
175+
else
176+
{
177+
_storage = new StorageBlob(new Uri($"https://{_fallbackStorageAccountName}.blob.core.windows.net"), _credential, null, null, null, null, _logger);
178+
}
160179

161180
State = ChannelState.Open;
162181
OnOpen?.Invoke(this, new ChannelOpenEventArgs(Id, Name, null));

src/Microsoft.AzureHealth.DataServices.Channels/EventGridChannelOptions.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.AzureHealth.DataServices.Pipelines;
1+
using Azure.Identity;
2+
using Microsoft.AzureHealth.DataServices.Pipelines;
23

34
namespace Microsoft.AzureHealth.DataServices.Channels
45
{
@@ -46,5 +47,15 @@ public class EventGridChannelOptions
4647
/// Gets or sets an Azure Blob Storage container used to store data when data exceeds the allowable Azure Event Grid size.
4748
/// </summary>
4849
public string FallbackStorageContainer { get; set; }
50+
51+
/// <summary>
52+
/// Gets or sets an Azure Blob Storage account used to store data when data exceeds the allowable Azure Event Grid size.
53+
/// </summary>
54+
public string FallbackStorageAccountName { get; set; }
55+
56+
/// <summary>
57+
/// Gets or sets an Azure Blob Storage account used to store data when data exceeds the allowable Azure Event Grid size.
58+
/// </summary>
59+
public DefaultAzureCredential Credential { get; set; }
4960
}
5061
}

0 commit comments

Comments
 (0)