Skip to content

Commit b77ce9f

Browse files
authored
Merge pull request #399 from serverlessworkflow/fix-authorization-info
Fix the AuthorizationInfo to resolve referenced authentication policies
2 parents b860edb + dc7eb06 commit b77ce9f

File tree

11 files changed

+70
-26
lines changed

11 files changed

+70
-26
lines changed

src/core/Synapse.Core/SynapseDefaults.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
// See the License for the specific language governing permissions and
1212
// limitations under the License.
1313

14-
using Synapse.Resources;
1514
using Neuroglia.Data.Infrastructure.ResourceOriented;
15+
using Synapse.Resources;
1616
using System.Diagnostics;
1717
using System.Reflection;
1818

@@ -766,7 +766,7 @@ public static class Secrets
766766
/// <summary>
767767
/// Gets the prefix for all secrets related environment variables
768768
/// </summary>
769-
public const string Prefix = EnvironmentVariables.Prefix + "SECRETS";
769+
public const string Prefix = EnvironmentVariables.Prefix + "SECRETS_";
770770
/// <summary>
771771
/// Gets the name of the environment variable used to configure the path to the directory that contains secrets files
772772
/// </summary>

src/runner/Synapse.Runner/AuthorizationInfo.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
// See the License for the specific language governing permissions and
1212
// limitations under the License.
1313

14-
using Docker.DotNet.Models;
1514
using Neuroglia.Data.Infrastructure.ResourceOriented;
1615
using ServerlessWorkflow.Sdk.Models.Authentication;
1716
using System.Text;
@@ -42,16 +41,22 @@ public class AuthorizationInfo(string scheme, string parameter)
4241
/// <summary>
4342
/// Creates a new <see cref="AuthorizationInfo"/> based on the specified <see cref="AuthenticationPolicyDefinition"/>
4443
/// </summary>
44+
/// <param name="workflow">The <see cref="WorkflowDefinition"/> that defines the <see cref="AuthenticationPolicyDefinition"/> to create a new <see cref="AuthorizationInfo"/> for</param>
4545
/// <param name="authentication">The <see cref="AuthenticationPolicyDefinition"/> to create a new <see cref="AuthorizationInfo"/> for</param>
4646
/// <param name="serviceProvider">The current <see cref="IServiceProvider"/></param>
4747
/// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
4848
/// <returns>A new <see cref="AuthorizationInfo"/> based on the specified <see cref="AuthenticationPolicyDefinition"/></returns>
49-
public static async Task<AuthorizationInfo> CreateAsync(AuthenticationPolicyDefinition authentication, IServiceProvider serviceProvider, CancellationToken cancellationToken = default)
49+
public static async Task<AuthorizationInfo> CreateAsync(WorkflowDefinition workflow, AuthenticationPolicyDefinition authentication, IServiceProvider serviceProvider, CancellationToken cancellationToken = default)
5050
{
5151
ArgumentNullException.ThrowIfNull(nameof(authentication));
5252
ArgumentNullException.ThrowIfNull(nameof(serviceProvider));
5353
string scheme, parameter;
5454
var logger = serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger("AuthenticationPolicyHandler");
55+
if (!string.IsNullOrWhiteSpace(authentication.Use))
56+
{
57+
if (workflow.Use?.Authentications?.TryGetValue(authentication.Use, out AuthenticationPolicyDefinition? referencedAuthentication) != true || referencedAuthentication == null) throw new NullReferenceException($"Failed to find the specified authentication policy '{authentication.Use}'");
58+
else authentication = referencedAuthentication;
59+
}
5560
var isSecretBased = authentication.TryGetBaseSecret(out var secretName);
5661
object? authenticationProperties = null;
5762
if (isSecretBased && !string.IsNullOrWhiteSpace(secretName))

src/runner/Synapse.Runner/Extensions/HttpClientExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ public static class HttpClientExtensions
2525
/// Configures the <see cref="HttpClient"/> to use the specified authentication mechanism
2626
/// </summary>
2727
/// <param name="httpClient">The <see cref="HttpClient"/> to configure</param>
28+
/// <param name="workflow">The <see cref="WorkflowDefinition"/> that defines the authentication to configure</param>
2829
/// <param name="authentication">An object that describes the authentication mechanism to use</param>
2930
/// <param name="serviceProvider">The current <see cref="IServiceProvider"/></param>
3031
/// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
3132
/// <returns>A new awaitable <see cref="Task"/></returns>
32-
public static async Task ConfigureAuthenticationAsync(this HttpClient httpClient, AuthenticationPolicyDefinition? authentication, IServiceProvider serviceProvider, CancellationToken cancellationToken = default)
33+
public static async Task ConfigureAuthenticationAsync(this HttpClient httpClient, WorkflowDefinition workflow, AuthenticationPolicyDefinition? authentication, IServiceProvider serviceProvider, CancellationToken cancellationToken = default)
3334
{
35+
ArgumentNullException.ThrowIfNull(workflow);
3436
if (authentication == null) return;
35-
var authorization = await AuthorizationInfo.CreateAsync(authentication, serviceProvider, cancellationToken).ConfigureAwait(false);
37+
var authorization = await AuthorizationInfo.CreateAsync(workflow, authentication, serviceProvider, cancellationToken).ConfigureAwait(false);
3638
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authorization.Scheme, authorization.Parameter);
3739
}
3840

src/runner/Synapse.Runner/Services/Executors/ForTaskExecutor.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ protected virtual async Task OnIterationFaultAsync(ITaskExecutor executor, Cance
105105
ArgumentNullException.ThrowIfNull(executor);
106106
var error = executor.Task.Instance.Error ?? throw new NullReferenceException();
107107
this.Executors.Remove(executor);
108-
await executor.DisposeAsync().ConfigureAwait(false);
109108
await this.SetErrorAsync(error, cancellationToken).ConfigureAwait(false);
110109
}
111110

@@ -123,7 +122,6 @@ protected virtual async Task OnIterationCompletedAsync(ITaskExecutor executor, C
123122
var output = executor.Task.Output!;
124123
this.Executors.Remove(executor);
125124
if (this.Task.ContextData != executor.Task.ContextData) await this.Task.SetContextDataAsync(executor.Task.ContextData, cancellationToken).ConfigureAwait(false);
126-
await executor.DisposeAsync().ConfigureAwait(false);
127125
var index = int.Parse(last.Reference.OriginalString.Split('/', StringSplitOptions.RemoveEmptyEntries)[^2]) + 1;
128126
if (index == this.Collection.Count)
129127
{

src/runner/Synapse.Runner/Services/Executors/ForkTaskExecutor.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,9 @@ protected virtual async Task OnSubTaskFaultAsync(ITaskExecutor executor, Cancell
8080
using var @lock = await this.Lock.LockAsync(cancellationToken).ConfigureAwait(false);
8181
var error = executor.Task.Instance.Error ?? throw new NullReferenceException();
8282
this.Executors.Remove(executor);
83-
await executor.DisposeAsync().ConfigureAwait(false);
8483
foreach (var subExecutor in this.Executors)
8584
{
8685
await subExecutor.CancelAsync(cancellationToken).ConfigureAwait(false);
87-
await subExecutor.DisposeAsync().ConfigureAwait(false);
8886
this.Executors.Remove(executor);
8987
}
9088
await this.SetErrorAsync(error, cancellationToken).ConfigureAwait(false);
@@ -102,11 +100,7 @@ protected virtual async Task OnSubTaskCompletedAsync(ITaskExecutor executor, Can
102100
using var @lock = await this.Lock.LockAsync(cancellationToken).ConfigureAwait(false);
103101
if (this.Task.Instance.Status != TaskInstanceStatus.Running)
104102
{
105-
if (this.Executors.Remove(executor))
106-
{
107-
await executor.CancelAsync(cancellationToken).ConfigureAwait(false);
108-
await executor.DisposeAsync().ConfigureAwait(false);
109-
}
103+
if (this.Executors.Remove(executor)) await executor.CancelAsync(cancellationToken).ConfigureAwait(false);
110104
}
111105
if (this.Task.Definition.Fork.Compete == true)
112106
{
@@ -115,7 +109,6 @@ protected virtual async Task OnSubTaskCompletedAsync(ITaskExecutor executor, Can
115109
{
116110
this.Executors.Remove(concurrentTaskExecutor);
117111
await concurrentTaskExecutor.CancelAsync(cancellationToken).ConfigureAwait(false);
118-
await concurrentTaskExecutor.DisposeAsync().ConfigureAwait(false);
119112
}
120113
await this.SetResultAsync(output, this.Task.Definition.Then, cancellationToken).ConfigureAwait(false);
121114
}

src/runner/Synapse.Runner/Services/Executors/FunctionCallExecutor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ protected virtual async Task OnSubTaskFaultAsync(ITaskExecutor executor, Cancell
115115
ArgumentNullException.ThrowIfNull(executor);
116116
var error = executor.Task.Instance.Error ?? throw new NullReferenceException();
117117
this.Executors.Remove(executor);
118-
await executor.DisposeAsync().ConfigureAwait(false);
119118
await this.SetErrorAsync(error, cancellationToken).ConfigureAwait(false);
120119
}
121120

src/runner/Synapse.Runner/Services/Executors/HttpCallExecutor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ protected override async Task DoInitializeAsync(CancellationToken cancellationTo
5656
{
5757
this.Http = (HttpCallDefinition)this.JsonSerializer.Convert(this.Task.Definition.With, typeof(HttpCallDefinition))!;
5858
var authentication = this.Http.Endpoint.Authentication == null ? null : await this.Task.Workflow.Expressions.EvaluateAsync<AuthenticationPolicyDefinition>(this.Http.Endpoint.Authentication, this.Task.Input, this.Task.Arguments, cancellationToken).ConfigureAwait(false);
59-
await this.HttpClient.ConfigureAuthenticationAsync(authentication, this.ServiceProvider, cancellationToken).ConfigureAwait(false);
59+
await this.HttpClient.ConfigureAuthenticationAsync(this.Task.Workflow.Definition, authentication, this.ServiceProvider, cancellationToken).ConfigureAwait(false);
6060
}
6161
catch(Exception ex)
6262
{

src/runner/Synapse.Runner/Services/Executors/OpenApiCallExecutor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ protected override async Task DoInitializeAsync(CancellationToken cancellationTo
109109
{
110110
this.OpenApi = (OpenApiCallDefinition)this.JsonSerializer.Convert(this.Task.Definition.With, typeof(OpenApiCallDefinition))!;
111111
using var httpClient = this.HttpClientFactory.CreateClient();
112-
await httpClient.ConfigureAuthenticationAsync(this.OpenApi.Document.Endpoint.Authentication, this.ServiceProvider, cancellationToken).ConfigureAwait(false);
112+
await httpClient.ConfigureAuthenticationAsync(this.Task.Workflow.Definition, this.OpenApi.Document.Endpoint.Authentication, this.ServiceProvider, cancellationToken).ConfigureAwait(false);
113113
using var request = new HttpRequestMessage(HttpMethod.Get, this.OpenApi.Document.EndpointUri);
114114
using var response = await httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
115115
if (!response.IsSuccessStatusCode)
@@ -226,7 +226,7 @@ protected override async Task DoExecuteAsync(CancellationToken cancellationToken
226226
}
227227
}
228228
using var httpClient = this.HttpClientFactory.CreateClient();
229-
await httpClient.ConfigureAuthenticationAsync(this.OpenApi.Authentication, this.ServiceProvider, cancellationToken).ConfigureAwait(false);
229+
await httpClient.ConfigureAuthenticationAsync(this.Task.Workflow.Definition, this.OpenApi.Authentication, this.ServiceProvider, cancellationToken).ConfigureAwait(false);
230230
using var response = await httpClient.SendAsync(request, cancellationToken);
231231
if (response.StatusCode == HttpStatusCode.ServiceUnavailable) continue;
232232
var rawContent = await response.Content.ReadAsByteArrayAsync(cancellationToken)!;

src/runner/Synapse.Runner/Services/ExternalResourceProvider.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ public virtual async Task<Stream> ReadAsync(WorkflowDefinition workflow, Externa
5454
/// <returns>The specified <see cref="ExternalResourceDefinition"/>'s content <see cref="Stream"/></returns>
5555
protected virtual async Task<Stream> ReadOverHttpAsync(WorkflowDefinition workflow, ExternalResourceDefinition resource, CancellationToken cancellationToken = default)
5656
{
57+
ArgumentNullException.ThrowIfNull(workflow);
58+
ArgumentNullException.ThrowIfNull(resource);
5759
using var httpClient = this.HttpClientFactory.CreateClient();
58-
await httpClient.ConfigureAuthenticationAsync(resource.Endpoint.Authentication, this.ServiceProvider, cancellationToken).ConfigureAwait(false);
60+
await httpClient.ConfigureAuthenticationAsync(workflow, resource.Endpoint.Authentication, this.ServiceProvider, cancellationToken).ConfigureAwait(false);
5961
return await httpClient.GetStreamAsync(resource.EndpointUri, cancellationToken).ConfigureAwait(false);
6062
}
6163

src/runner/Synapse.Runner/Services/TaskExecutor.cs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,34 @@ public abstract class TaskExecutor<TDefinition>(IServiceProvider serviceProvider
115115
/// <inheritdoc/>
116116
public virtual async Task InitializeAsync(CancellationToken cancellationToken = default)
117117
{
118-
await this.DoInitializeAsync(cancellationToken).ConfigureAwait(false);
119-
await this.Task.InitializeAsync(cancellationToken).ConfigureAwait(false);
120-
this.Subject.OnNext(new TaskLifeCycleEvent(TaskLifeCycleEventType.Initialized));
118+
try
119+
{
120+
await this.DoInitializeAsync(cancellationToken).ConfigureAwait(false);
121+
await this.Task.InitializeAsync(cancellationToken).ConfigureAwait(false);
122+
this.Subject.OnNext(new TaskLifeCycleEvent(TaskLifeCycleEventType.Initialized));
123+
}
124+
catch(HttpRequestException ex)
125+
{
126+
await this.SetErrorAsync(new Error()
127+
{
128+
Type = ErrorType.Communication,
129+
Title = ErrorTitle.Communication,
130+
Status = ex.StatusCode.HasValue ? (ushort)ex.StatusCode : (ushort)ErrorStatus.Communication,
131+
Detail = ex.Message,
132+
Instance = this.Task.Instance.Reference
133+
}, cancellationToken).ConfigureAwait(false);
134+
}
135+
catch(Exception ex)
136+
{
137+
await this.SetErrorAsync(new Error()
138+
{
139+
Type = ErrorType.Runtime,
140+
Title = ErrorTitle.Runtime,
141+
Status = ErrorStatus.Runtime,
142+
Detail = ex.Message,
143+
Instance = this.Task.Instance.Reference
144+
}, cancellationToken).ConfigureAwait(false);
145+
}
121146
}
122147

123148
/// <summary>
@@ -171,6 +196,28 @@ await this.SetErrorAsync(new()
171196
await this.TaskCompletionSource.Task.ConfigureAwait(false);
172197
}
173198
catch (OperationCanceledException) { }
199+
catch (HttpRequestException ex)
200+
{
201+
await this.SetErrorAsync(new Error()
202+
{
203+
Type = ErrorType.Communication,
204+
Title = ErrorTitle.Communication,
205+
Status = ex.StatusCode.HasValue ? (ushort)ex.StatusCode : (ushort)ErrorStatus.Communication,
206+
Detail = ex.Message,
207+
Instance = this.Task.Instance.Reference
208+
}, cancellationToken).ConfigureAwait(false);
209+
}
210+
catch (Exception ex)
211+
{
212+
await this.SetErrorAsync(new Error()
213+
{
214+
Type = ErrorType.Runtime,
215+
Title = ErrorTitle.Runtime,
216+
Status = ErrorStatus.Runtime,
217+
Detail = ex.Message,
218+
Instance = this.Task.Instance.Reference
219+
}, cancellationToken).ConfigureAwait(false);
220+
}
174221
}
175222

176223
/// <summary>
@@ -198,7 +245,6 @@ protected virtual async Task BeforeExecuteAsync(CancellationToken cancellationTo
198245
}
199246
input = executor.Task.Output ?? new();
200247
this.Executors.Remove(executor);
201-
await executor.DisposeAsync().ConfigureAwait(false);
202248
}
203249
}
204250

src/runner/Synapse.Runner/Services/WorkflowExecutor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,6 @@ protected virtual async Task OnTaskCompletedAsync(ITaskExecutor executor, Cancel
272272
};
273273
var completedTask = executor.Task;
274274
this.Executors.Remove(executor);
275-
await executor.DisposeAsync().ConfigureAwait(false);
276275
if (nextDefinition == null)
277276
{
278277
await this.SetResultAsync(completedTask.Output, cancellationToken).ConfigureAwait(false);

0 commit comments

Comments
 (0)