Skip to content

[feature/10.0] Use validation source generator #8165

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

Open
wants to merge 8 commits into
base: feature/10.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
<PackageVersion Include="Azure.Storage.Blobs" Version="$(AzureStorageBlobsVersion)" />
<PackageVersion Include="Azure.Storage.Queues" Version="$(AzureStorageQueuesVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(MicrosoftAspNetCoreAuthenticationJwtBearerVersion)" />
<PackageVersion Include="Microsoft.AspnetCore.OpenApi" Version="$(MicrosoftAspNetCoreOpenApiVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="$(MicrosoftAspNetCoreAuthenticationNegotiateVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(MicrosoftAspNetCoreApp100Version)" />
<PackageVersion Include="Microsoft.AspnetCore.OpenApi" Version="$(MicrosoftAspNetCoreOpenApiVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="$(MicrosoftCodeAnalysisNetAnalyzersVersion)" />
<PackageVersion Include="Microsoft.Diagnostics.Monitoring" Version="$(MicrosoftDiagnosticsMonitoringLibraryVersion)" />
<PackageVersion Include="Microsoft.Diagnostics.Monitoring.EventPipe" Version="$(MicrosoftDiagnosticsMonitoringEventPipeLibraryVersion)" />
Expand Down
9 changes: 9 additions & 0 deletions src/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,13 @@
</ItemGroup>
</Target>

<!-- Disable validation source generator to allow working around issues with generated code. -->
<Target Name="DisableValidationSourceGenerator"
BeforeTargets="CoreCompile"
Condition="'$(DisableValidationSourceGenerator)' == 'true'">
<ItemGroup>
<Analyzer Remove="@(Analyzer)" Condition="'%(Analyzer.FileName)' == 'Microsoft.AspNetCore.Http.ValidationsGenerator'" />
</ItemGroup>
</Target>

</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<OutputType>Library</OutputType>
Expand All @@ -11,6 +11,7 @@

<ItemGroup>
<Compile Include="..\Tools\dotnet-monitor\DataAnnotationValidateOptions.cs" Link="DataAnnotationValidateOptions.cs" />
<Compile Include="..\Tools\dotnet-monitor\CollectionRules\Options\ValidationHelper.cs" Link="ValidationHelper.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext vali
results.Add(
new ValidationResult(
string.Format(
OptionsDisplayStrings.ErrorMessage_MultipleAuthenticationModesSpecified)));
OptionsDisplayStrings.ErrorMessage_MultipleAuthenticationModesSpecified), [nameof(MonitorApiKey), nameof(AzureAd)]));
}

return results;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public IEnumerable<ValidationResult> Validate(ValidationContext validationContex
{
// We prefix the validation error with the provider.
results.AddRange(providerResults.Select(r => new ValidationResult(
string.Format(CultureInfo.CurrentCulture, OptionsDisplayStrings.ErrorMessage_NestedProviderValidationError, provider, r.ErrorMessage))));
string.Format(CultureInfo.CurrentCulture, OptionsDisplayStrings.ErrorMessage_NestedProviderValidationError, provider, r.ErrorMessage),
[nameof(Providers)])));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Microsoft.Diagnostics.Monitoring.Options\Microsoft.Diagnostics.Monitoring.Options.csproj" />
<ProjectReference Include="..\..\Tools\dotnet-monitor\dotnet-monitor.csproj" />
<ProjectReference Include="..\Microsoft.Diagnostics.Monitoring.TestCommon\Microsoft.Diagnostics.Monitoring.TestCommon.csproj" />
<ProjectReference Include="..\Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon\Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon.csproj" />
<ProjectReference Include="..\Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample\Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample.csproj" />
</ItemGroup>

</Project>
19 changes: 15 additions & 4 deletions src/Tests/CollectionRuleActions.UnitTests/ExecuteActionTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.Http.Validation;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Diagnostics.Monitoring.TestCommon;
using Microsoft.Diagnostics.Tools.Monitor;
using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions;
using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Exceptions;
using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Globalization;
using System.IO;
Expand All @@ -18,17 +22,23 @@

namespace CollectionRuleActions.UnitTests
{
public class ExecuteActionFixture : WebApplicationFactory<Program>
{
}

[TargetFrameworkMonikerTrait(TargetFrameworkMonikerExtensions.CurrentTargetFrameworkMoniker)]
[Collection(TestCollections.CollectionRuleActions)]
public sealed class ExecuteActionTests
public sealed class ExecuteActionTests : IClassFixture<ExecuteActionFixture>
{
private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30);

private readonly ITestOutputHelper _outputHelper;
private readonly ExecuteActionFixture _fixture;

public ExecuteActionTests(ITestOutputHelper outputHelper)
public ExecuteActionTests(ITestOutputHelper outputHelper, ExecuteActionFixture fixture)
{
_outputHelper = outputHelper;
_fixture = fixture;
}

[Fact]
Expand Down Expand Up @@ -173,9 +183,10 @@ private static void ValidateActionResult(CollectionRuleActionResult result, stri
Assert.Equal(expectedExitCode, actualExitCode);
}

private static async Task ValidateAction(Action<ExecuteOptions> optionsCallback, Func<ICollectionRuleAction, CancellationToken, Task> actionCallback)
private async Task ValidateAction(Action<ExecuteOptions> optionsCallback, Func<ICollectionRuleAction, CancellationToken, Task> actionCallback)
{
ExecuteActionFactory factory = new();
var validationOptions = _fixture.Services.GetService<IOptions<ValidationOptions>>();
ExecuteActionFactory factory = new(_fixture.Services, validationOptions);

ExecuteOptions options = new();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,6 @@ public async Task AllowsConfiguredIssuer()
[Theory]
// Guids that don't match should get rejected
[InlineData("980d2b17-71e1-4313-a084-c077e962680c", "10253b7a-454d-41bb-a3f5-5f2e6b26ed93", HttpStatusCode.Forbidden)]
// Empty string isn't valid even when signed and configured correctly
[InlineData("", "", HttpStatusCode.Unauthorized)]
[InlineData("10253b7a-454d-41bb-a3f5-5f2e6b26ed93", "", HttpStatusCode.Unauthorized)]
[InlineData("", "10253b7a-454d-41bb-a3f5-5f2e6b26ed93", HttpStatusCode.Forbidden)]
public async Task RejectsBadSubject(string jwtSubject, string configSubject, HttpStatusCode expectedError)
{
Expand All @@ -501,6 +498,25 @@ public async Task RejectsBadSubject(string jwtSubject, string configSubject, Htt
Assert.Equal(expectedError, statusCodeException.StatusCode);
}

/// <summary>
/// This tests that an empty configured subject fails on startup.
/// </summary>
[Fact]
public async Task DoesNotStart_With_EmptySubject()
{
var configSubject = "";
await using MonitorCollectRunner toolRunner = new(_outputHelper);
toolRunner.DisableMetricsViaCommandLine = true;

_outputHelper.WriteLine("Generating API key.");

JwtPayload newPayload = GetJwtPayload(AuthConstants.ApiKeyJwtAudience, configSubject, AuthConstants.ApiKeyJwtInternalIssuer, AuthConstants.ApiKeyJwtDefaultExpiration);

toolRunner.ConfigurationFromEnvironment.UseApiKey(SecurityAlgorithms.EcdsaSha384, configSubject, newPayload, out string token);

await Assert.ThrowsAsync<InvalidOperationException>(toolRunner.StartAsync);
}

[Fact]
public async Task RejectsMissingExpiration()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFrameworks>$(ToolTargetFrameworks)</TargetFrameworks>
<DisableCompileTimeOpenApiXmlGenerator>true</DisableCompileTimeOpenApiXmlGenerator>
<DisableValidationSourceGenerator>true</DisableValidationSourceGenerator>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ public static IHost CreateHost(
services.AddSingleton<IMetricsOperationFactory, MetricsOperationFactory>();
services.AddSingleton<ITraceOperationFactory, TraceOperationFactory>();
services.AddSingleton<IGCDumpOperationFactory, GCDumpOperationFactory>();
ValidatableTypes.AddValidation(services);
TestValidatableTypes.AddValidation(services);
servicesCallback?.Invoke(services);
})
.Build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.Http.Validation;
using Microsoft.AspNetCore.Http.Validation.Generated;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.Diagnostics.Monitoring.TestCommon
{
[ValidatableType]
internal sealed class TestValidatableTypes
{
public required PassThroughOptions PassThroughOptions { get; init; }

public static void AddValidation(IServiceCollection services)
{
TestGeneratedServiceCollectionExtensions.AddValidation(services);
}
}
}
Loading
Loading