Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

durable task scheduler auth extension support #362

Merged
merged 58 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
fc053ec
durable task scheduler auth extension
YunchuWang Jan 7, 2025
6f1d2bc
support local conn with no auth and via http
YunchuWang Jan 9, 2025
51e39bd
be consistent with azuremanaged targetversion
YunchuWang Jan 9, 2025
6987f1b
clean
YunchuWang Jan 9, 2025
e162815
namespace
YunchuWang Jan 9, 2025
e19de44
fix
YunchuWang Jan 9, 2025
3a6dc52
fix
YunchuWang Jan 9, 2025
65dfb85
doc
YunchuWang Jan 9, 2025
29445a0
ppl
YunchuWang Jan 9, 2025
e63f12a
remove
YunchuWang Jan 9, 2025
5c72ee7
test proj to sln
YunchuWang Jan 9, 2025
c6e42c5
fix warning
YunchuWang Jan 9, 2025
6a66aaa
remove dup
YunchuWang Jan 9, 2025
131c575
fix
YunchuWang Jan 9, 2025
65fa607
Revert "fix"
YunchuWang Jan 9, 2025
4f45ec5
save
YunchuWang Jan 10, 2025
d4607e4
fix
YunchuWang Jan 10, 2025
552a9c8
save
YunchuWang Jan 10, 2025
54dba76
save
YunchuWang Jan 10, 2025
5e97555
some fb
YunchuWang Jan 10, 2025
9c890c5
fix
YunchuWang Jan 10, 2025
49c6282
update
YunchuWang Jan 10, 2025
1adf7cc
update tests
YunchuWang Jan 10, 2025
14b94eb
sample
YunchuWang Jan 10, 2025
5696b2f
save
YunchuWang Jan 11, 2025
62e2b30
save
YunchuWang Jan 11, 2025
02b02c7
update
YunchuWang Jan 11, 2025
ee517d2
save
YunchuWang Jan 11, 2025
34a47ad
save
YunchuWang Jan 11, 2025
2decb79
save
YunchuWang Jan 11, 2025
ee295d0
save
YunchuWang Jan 11, 2025
522d4b0
fix
YunchuWang Jan 11, 2025
d289c10
fix
YunchuWang Jan 11, 2025
0d2a20c
Revert "sample"
YunchuWang Jan 11, 2025
f4f03fc
fix tests
YunchuWang Jan 11, 2025
59c5e9c
test accesstokencache
YunchuWang Jan 11, 2025
3dfbb72
split
YunchuWang Jan 12, 2025
5083703
fix shared
YunchuWang Jan 12, 2025
a505004
save
YunchuWang Jan 12, 2025
443613e
fix client managed
YunchuWang Jan 12, 2025
8744f8a
fix worker
YunchuWang Jan 12, 2025
37d3d5e
fix shared tests
YunchuWang Jan 12, 2025
c7f499a
fix client tests
YunchuWang Jan 12, 2025
f077e98
fix worker tests
YunchuWang Jan 12, 2025
89b7071
fix tests path
YunchuWang Jan 12, 2025
77cd2d9
update sln
YunchuWang Jan 12, 2025
3af8b62
add sample
YunchuWang Jan 10, 2025
549e105
Update src/Shared/AzureManaged/Shared.AzureManaged.csproj
YunchuWang Jan 13, 2025
3a40d09
fix compile
YunchuWang Jan 13, 2025
c697fbc
refactor
YunchuWang Jan 14, 2025
55eea54
fix
YunchuWang Jan 14, 2025
1ede0d4
fb
YunchuWang Jan 15, 2025
02d5992
fb
YunchuWang Jan 15, 2025
e0bd4e2
fb
YunchuWang Jan 15, 2025
5b4f648
fb
YunchuWang Jan 15, 2025
6f28efc
remove validateonstart
YunchuWang Jan 16, 2025
3334130
change ver
YunchuWang Jan 16, 2025
d87eed6
Update CHANGELOG and mark packages as preview
cgillum Jan 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Remove the line below if you want to inherit .editorconfig settings from higher directories
'# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true

# XML project files
Expand Down Expand Up @@ -232,3 +232,9 @@ dotnet_diagnostic.SA1400.severity = none # Access modifier must be declared
dotnet_diagnostic.SA1402.severity = none # File may only contain a single type
dotnet_diagnostic.SA1633.severity = warning # File must have header -- TODO: replace with IDE0073 eventually
dotnet_diagnostic.SA1649.severity = none # File name must match type name

# Enforce explicit types instead of `var`
dotnet_style_prefer_var_for_built_in_types = false:error
dotnet_style_prefer_var_for_simple_types = false:error
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
dotnet_style_prefer_var_when_type_is_apparent = false:error
dotnet_style_prefer_var_when_type_is_not_apparent = false:error
7 changes: 6 additions & 1 deletion .github/workflows/validate-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ jobs:
with:
submodules: true

- name: Setup .NET
- name: Setup .NET 6.0
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved

- name: Setup .NET from global.json
uses: actions/setup-dotnet@v3
with:
global-json-file: global.json
Expand Down
43 changes: 43 additions & 0 deletions Microsoft.DurableTask.sln
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Analyzers.Tests", "test\Ana
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzureFunctionsApp.Tests", "samples\AzureFunctionsUnitTests\AzureFunctionsApp.Tests.csproj", "{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker.AzureManaged", "src\Worker\AzureManaged\Worker.AzureManaged.csproj", "{6106872F-A730-4A75-9267-1B2E2C2DC18C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.AzureManaged", "src\Client\AzureManaged\Client.AzureManaged.csproj", "{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared.AzureManaged.Tests", "test\Shared\AzureManaged.Tests\Shared.AzureManaged.Tests.csproj", "{11357B31-9A63-4A5A-9BC5-091952B25BC0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.AzureManaged.Tests", "test\Client\AzureManaged.Tests\Client.AzureManaged.Tests.csproj", "{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker.AzureManaged.Tests", "test\Worker\AzureManaged.Tests\Worker.AzureManaged.Tests.csproj", "{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -185,6 +195,34 @@ Global
{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9}.Release|Any CPU.Build.0 = Release|Any CPU
{6106872F-A730-4A75-9267-1B2E2C2DC18C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6106872F-A730-4A75-9267-1B2E2C2DC18C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6106872F-A730-4A75-9267-1B2E2C2DC18C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6106872F-A730-4A75-9267-1B2E2C2DC18C}.Release|Any CPU.Build.0 = Release|Any CPU
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}.Release|Any CPU.Build.0 = Release|Any CPU
{11357B31-9A63-4A5A-9BC5-091952B25BC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11357B31-9A63-4A5A-9BC5-091952B25BC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11357B31-9A63-4A5A-9BC5-091952B25BC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11357B31-9A63-4A5A-9BC5-091952B25BC0}.Release|Any CPU.Build.0 = Release|Any CPU
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}.Release|Any CPU.Build.0 = Release|Any CPU
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}.Release|Any CPU.Build.0 = Release|Any CPU
{869D2D51-9372-4764-B059-C43B6C1180A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{869D2D51-9372-4764-B059-C43B6C1180A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{869D2D51-9372-4764-B059-C43B6C1180A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{869D2D51-9372-4764-B059-C43B6C1180A3}.Release|Any CPU.Build.0 = Release|Any CPU
{D4C87C0F-66CD-459D-B271-340C6D180448}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4C87C0F-66CD-459D-B271-340C6D180448}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4C87C0F-66CD-459D-B271-340C6D180448}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4C87C0F-66CD-459D-B271-340C6D180448}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -220,6 +258,11 @@ Global
{998E9D97-BD36-4A9D-81FC-5DAC1CE40083} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{541FCCCE-1059-4691-B027-F761CD80DE92} = {E5637F81-2FB9-4CD7-900D-455363B142A7}
{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9} = {EFF7632B-821E-4CFC-B4A0-ED4B24296B17}
{6106872F-A730-4A75-9267-1B2E2C2DC18C} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{11357B31-9A63-4A5A-9BC5-091952B25BC0} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AB41CB55-35EA-4986-A522-387AB3402E71}
Expand Down
24 changes: 24 additions & 0 deletions src/Client/AzureManaged/Client.AzureManaged.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<PackageDescription>Azure Managed extensions for the Durable Task Framework client.</PackageDescription>
<EnableStyleCop>true</EnableStyleCop>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../../Client/Grpc/Client.Grpc.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="8.0.0" />
Copy link
Member

@jviau jviau Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are targeting net6 but using a v8.x package. While this is technically 'valid', it may be confusing to users. Are we able to use a 6.x package here?

Side note: targeting net8 and using v8.x packages would be another discussion / work item. Don't want to get that tangled into this PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{791DA31B-A16A-4053-8E00-379D46984313} v6 of this package does not target dotnet 6, and v7 does not have
{16E38BDC-D45C-4567-ADB7-9851B06452D0} validateonstart. v8 is min version targeting dotnet 6 and has validateonstart api

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need ValidateOnStart? This will effectively be validated on start, as validation will occur on first import of it, which will be done at start due to this being eventually imported by a IHostedService (the DurableTaskWorker)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, updated ver and removed validateonstart

<PackageReference Include="Grpc.Net.Client" Version="2.67.0" />
</ItemGroup>

<ItemGroup>
<SharedSection Include="AzureManaged" />
<SharedSection Include="Core" />
</ItemGroup>

</Project>
119 changes: 119 additions & 0 deletions src/Client/AzureManaged/DurableTaskSchedulerClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Azure.Core;
using Microsoft.DurableTask.Client.Grpc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;

namespace Microsoft.DurableTask.Client.AzureManaged;

/// <summary>
/// Extension methods for configuring Durable Task clients to use the Azure Durable Task Scheduler service.
/// </summary>
public static class DurableTaskSchedulerClientExtensions
{
/// <summary>
/// Configures Durable Task client to use the Azure Durable Task Scheduler service.
/// </summary>
/// <param name="builder">The Durable Task client builder to configure.</param>
/// <param name="endpointAddress">The endpoint address of the Durable Task Scheduler resource. Expected to be in the format "https://{scheduler-name}.{region}.durabletask.io".</param>
/// <param name="taskHubName">The name of the task hub resource associated with the Durable Task Scheduler resource.</param>
/// <param name="credential">The credential used to authenticate with the Durable Task Scheduler task hub resource.</param>
/// <param name="configure">Optional callback to dynamically configure DurableTaskSchedulerClientOptions.</param>
public static void UseDurableTaskScheduler(
this IDurableTaskClientBuilder builder,
string endpointAddress,
string taskHubName,
TokenCredential credential,
Action<DurableTaskSchedulerClientOptions>? configure = null)
{
ConfigureSchedulerOptions(
builder,
options =>
{
options.EndpointAddress = endpointAddress;
options.TaskHubName = taskHubName;
options.Credential = credential;
},
configure);
}

/// <summary>
/// Configures Durable Task client to use the Azure Durable Task Scheduler service using a connection string.
/// </summary>
/// <param name="builder">The Durable Task client builder to configure.</param>
/// <param name="connectionString">The connection string used to connect to the Durable Task Scheduler service.</param>
/// <param name="configure">Optional callback to dynamically configure DurableTaskSchedulerClientOptions.</param>
public static void UseDurableTaskScheduler(
this IDurableTaskClientBuilder builder,
string connectionString,
Action<DurableTaskSchedulerClientOptions>? configure = null)
{
var connectionOptions = DurableTaskSchedulerClientOptions.FromConnectionString(connectionString);
ConfigureSchedulerOptions(
builder,
options =>
{
options.EndpointAddress = connectionOptions.EndpointAddress;
options.TaskHubName = connectionOptions.TaskHubName;
options.Credential = connectionOptions.Credential;
},
configure);
}

/// <summary>
/// Configures Durable Task client to use the Azure Durable Task Scheduler service using configuration options.
/// </summary>
/// <param name="builder">The Durable Task client builder to configure.</param>
/// <param name="configure">Callback to configure DurableTaskSchedulerClientOptions.</param>
public static void UseDurableTaskScheduler(
this IDurableTaskClientBuilder builder,
Action<DurableTaskSchedulerClientOptions>? configure = null)
{
ConfigureSchedulerOptions(builder, _ => { }, configure);
}

static void ConfigureSchedulerOptions(
IDurableTaskClientBuilder builder,
Action<DurableTaskSchedulerClientOptions> initialConfig,
Action<DurableTaskSchedulerClientOptions>? additionalConfig)
{
builder.Services.AddOptions<DurableTaskSchedulerClientOptions>(builder.Name)
.Configure(initialConfig)
.Configure(additionalConfig ?? (_ => { }))
.ValidateDataAnnotations()
.ValidateOnStart();

builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IConfigureOptions<GrpcDurableTaskClientOptions>, ConfigureGrpcChannel>());
builder.UseGrpc(_ => { });
}

/// <summary>
/// Configuration class that sets up gRPC channels for client options
/// using the provided Durable Task Scheduler options.
/// </summary>
/// <param name="schedulerOptions">Monitor for accessing the current scheduler options configuration.</param>
class ConfigureGrpcChannel(IOptionsMonitor<DurableTaskSchedulerClientOptions> schedulerOptions) :
IConfigureNamedOptions<GrpcDurableTaskClientOptions>
{
/// <summary>
/// Configures the default named options instance.
/// </summary>
/// <param name="options">The options instance to configure.</param>
public void Configure(GrpcDurableTaskClientOptions options) => this.Configure(Options.DefaultName, options);

/// <summary>
/// Configures a named options instance.
/// </summary>
/// <param name="name">The name of the options instance to configure.</param>
/// <param name="options">The options instance to configure.</param>
public void Configure(string? name, GrpcDurableTaskClientOptions options)
{
DurableTaskSchedulerClientOptions source = schedulerOptions.Get(name ?? Options.DefaultName);
options.Channel = source.CreateChannel();
}
}
}
158 changes: 158 additions & 0 deletions src/Client/AzureManaged/DurableTaskSchedulerClientOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.ComponentModel.DataAnnotations;
using Azure.Core;
using Azure.Identity;
using Grpc.Core;
using Grpc.Net.Client;

namespace Microsoft.DurableTask;

/// <summary>
/// Options for configuring the Durable Task Scheduler.
/// </summary>
public class DurableTaskSchedulerClientOptions
{
/// <summary>
/// Gets or sets the endpoint address of the Durable Task Scheduler resource.
/// Expected to be in the format "https://{scheduler-name}.{region}.durabletask.io".
/// </summary>
[Required(ErrorMessage = "Endpoint address is required")]
public string EndpointAddress { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the name of the task hub resource associated with the Durable Task Scheduler resource.
/// </summary>
[Required(ErrorMessage = "Task hub name is required")]
public string TaskHubName { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the credential used to authenticate with the Durable Task Scheduler task hub resource.
/// </summary>
public TokenCredential? Credential { get; set; }

/// <summary>
/// Gets or sets the resource ID of the Durable Task Scheduler resource.
/// The default value is https://durabletask.io.
/// </summary>
public string ResourceId { get; set; } = "https://durabletask.io";

/// <summary>
/// Gets or sets a value indicating whether to allow insecure channel credentials.
/// This should only be set to true in local development/testing scenarios.
/// </summary>
public bool AllowInsecureCredentials { get; set; }

/// <summary>
/// Creates a new instance of <see cref="DurableTaskSchedulerClientOptions"/> from a connection string.
/// </summary>
/// <param name="connectionString">The connection string to parse.</param>
/// <returns>A new instance of <see cref="DurableTaskSchedulerClientOptions"/>.</returns>
public static DurableTaskSchedulerClientOptions FromConnectionString(string connectionString)
{
return FromConnectionString(new DurableTaskSchedulerConnectionString(connectionString));
}

/// <summary>
/// Creates a gRPC channel for communicating with the Durable Task Scheduler service.
/// </summary>
/// <returns>A configured <see cref="GrpcChannel"/> instance that can be used to make gRPC calls.</returns>
public GrpcChannel CreateChannel()
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
{
Verify.NotNull(this.EndpointAddress, nameof(this.EndpointAddress));
Verify.NotNull(this.TaskHubName, nameof(this.TaskHubName));
string taskHubName = this.TaskHubName;
string endpoint = !this.EndpointAddress.Contains("://")
? $"https://{this.EndpointAddress}"
: this.EndpointAddress;
AccessTokenCache? cache =
this.Credential is not null
? new AccessTokenCache(
this.Credential,
new TokenRequestContext(new[] { $"{this.ResourceId}/.default" }),
TimeSpan.FromMinutes(5))
: null;
CallCredentials managedBackendCreds = CallCredentials.FromInterceptor(
async (context, metadata) =>
{
metadata.Add("taskhub", taskHubName);
if (cache == null)
{
return;
}

AccessToken token = await cache.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token.Token}");
});

// Production will use HTTPS, but local testing will use HTTP
ChannelCredentials channelCreds = endpoint.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ?
ChannelCredentials.SecureSsl :
ChannelCredentials.Insecure;
return GrpcChannel.ForAddress(endpoint, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(channelCreds, managedBackendCreds),
UnsafeUseInsecureChannelCallCredentials = this.AllowInsecureCredentials,
});
}

/// <summary>
/// Creates a new instance of <see cref="DurableTaskSchedulerClientOptions"/> from a parsed connection string.
/// </summary>
/// <param name="connectionString">The connection string to parse.</param>
/// <returns>A new instance of <see cref="DurableTaskSchedulerClientOptions"/>.</returns>
internal static DurableTaskSchedulerClientOptions FromConnectionString(
DurableTaskSchedulerConnectionString connectionString) => new()
{
EndpointAddress = connectionString.Endpoint,
TaskHubName = connectionString.TaskHubName,
Credential = GetCredentialFromConnectionString(connectionString),
};

static TokenCredential? GetCredentialFromConnectionString(DurableTaskSchedulerConnectionString connectionString)
{
string authType = connectionString.Authentication;

// Parse the supported auth types, in a case-insensitive way and without spaces
switch (authType.ToLowerInvariant())
{
case "defaultazure":
return new DefaultAzureCredential();
case "managedidentity":
return new ManagedIdentityCredential(connectionString.ClientId);
case "workloadidentity":
var opts = new WorkloadIdentityCredentialOptions();
if (!string.IsNullOrEmpty(connectionString.ClientId))
{
opts.ClientId = connectionString.ClientId;
}

if (!string.IsNullOrEmpty(connectionString.TenantId))
{
opts.TenantId = connectionString.TenantId;
}

if (connectionString.AdditionallyAllowedTenants is not null)
{
foreach (string tenant in connectionString.AdditionallyAllowedTenants)
{
opts.AdditionallyAllowedTenants.Add(tenant);
}
}

return new WorkloadIdentityCredential(opts);
case "environment":
return new EnvironmentCredential();
case "azurecli":
return new AzureCliCredential();
case "azurepowershell":
return new AzurePowerShellCredential();
case "none":
return null;
default:
throw new ArgumentException(
$"The connection string contains an unsupported authentication type '{authType}'.",
nameof(connectionString));
}
}
}
Loading
Loading