using System.Reflection; using Elsa.Diagnostics.OpenTelemetry.Contracts; using Elsa.Diagnostics.OpenTelemetry.Features; using Elsa.Diagnostics.OpenTelemetry.Models; using Elsa.Diagnostics.OpenTelemetry.Permissions; using FastEndpoints; namespace Elsa.Diagnostics.OpenTelemetry.IntegrationTests; public class OpenTelemetryAuthorizationTests { [Theory] [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Resources.Endpoint")] [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Traces.Endpoint")] [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Trace.Endpoint")] [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Metrics.Endpoint")] [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Logs.Endpoint")] [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.Storage.Endpoint")] [InlineData("Elsa.Diagnostics.OpenTelemetry.Endpoints.OpenTelemetry.CollectorConfiguration.Endpoint")] public void RestEndpoints_RequireOpenTelemetryReadPermission(string endpointTypeName) { var permissions = GetConfiguredPermissions(endpointTypeName); Assert.Contains(OpenTelemetryPermissions.Read, permissions); } private static IReadOnlyCollection GetConfiguredPermissions(string endpointTypeName) { var endpointType = typeof(OpenTelemetryFeature).Assembly.GetType(endpointTypeName, throwOnError: true)!; var endpoint = Activator.CreateInstance(endpointType, new TestOpenTelemetryProvider())!; var (requestDtoType, responseDtoType) = GetEndpointDtoTypes(endpointType); var definition = new EndpointDefinition(endpointType, requestDtoType, responseDtoType); endpointType .GetProperty("Definition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)! .SetValue(endpoint, definition); endpointType.GetMethod("Configure")!.Invoke(endpoint, null); var permissions = definition .GetType() .GetProperty("AllowedPermissions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)! .GetValue(definition); return Assert.IsAssignableFrom>(permissions).ToArray(); } private static (Type RequestDtoType, Type ResponseDtoType) GetEndpointDtoTypes(Type endpointType) { var type = endpointType; while (type.BaseType != null) { type = type.BaseType; if (!type.IsGenericType) continue; var genericTypeDefinition = type.GetGenericTypeDefinition(); var genericArguments = type.GetGenericArguments(); if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpoint<,>)) return (genericArguments[0], genericArguments[1]); if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpoint<,,>)) return (genericArguments[0], genericArguments[1]); if (genericTypeDefinition == typeof(Elsa.Abstractions.ElsaEndpointWithoutRequest<>)) return (typeof(EmptyRequest), genericArguments[0]); } throw new InvalidOperationException($"Unsupported endpoint type '{endpointType.FullName}'."); } private class TestOpenTelemetryProvider : IOpenTelemetryProvider { public ValueTask GetResourcesAsync(OpenTelemetryResourceFilter filter, CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryResourceResult([], 0)); public ValueTask GetTracesAsync(OpenTelemetryTraceFilter filter, CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryTraceResult([], 0)); public ValueTask GetTraceAsync(string traceId, CancellationToken cancellationToken = default) => ValueTask.FromResult(null); public ValueTask GetMetricsAsync(OpenTelemetryMetricFilter filter, CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryMetricResult([], [], 0)); public ValueTask GetLogsAsync(OpenTelemetryLogFilter filter, CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryLogResult([], 0)); public ValueTask GetStorageDiagnosticsAsync(CancellationToken cancellationToken = default) => ValueTask.FromResult(new OpenTelemetryStorageDiagnostics(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); public ValueTask GetCollectorConfigurationAsync(CancellationToken cancellationToken = default) { var configuration = new CollectorConfiguration( new CollectorEndpointInfo("http/protobuf", "/elsa/otlp/v1", true, null), new CollectorEndpointInfo("grpc", null, false, "Disabled"), "OTEL_SERVICE_NAME", "OTEL_EXPORTER_OTLP_ENDPOINT", "OTEL_EXPORTER_OTLP_PROTOCOL", new Dictionary()); return ValueTask.FromResult(configuration); } } }