Просмотр исходного кода

Add a test confirming that X509Certificate is trimmed (#48295)

* Add a test confirming that X509Certificate is trimmed

...when using `CreateSlimBuilder`.

* Disable IsReflectionEnabledByDefault to eliminate warning

* Switch to trimming tests

...since we're testing trimming behavior and add a test in the other direction (i.e. `UseHttps` does cause `X509Certificate` to be preserved).

* Hack around the need for a certificate

* Mitigate missing dev cert in a way that doesn't invalidate the test

* Delay-build trimming test projects

* Add copyright headers

* Use negative exit codes in error scenarios

* Simplify type lookup

* Allow X509Certificate to be preserved if it has no members
Andrew Casey 2 лет назад
Родитель
Сommit
50268170ee

+ 1 - 0
eng/RequiresDelayedBuildProjects.props

@@ -10,6 +10,7 @@
   <ItemGroup>
     <RequiresDelayedBuild Include="$(RepoRoot)src\DataProtection\DataProtection\test\Microsoft.AspNetCore.DataProtection.TrimmingTests\Microsoft.AspNetCore.DataProtection.TrimmingTests.proj" />
     <RequiresDelayedBuild Include="$(RepoRoot)src\DefaultBuilder\test\Microsoft.AspNetCore.NativeAotTests\Microsoft.AspNetCore.NativeAotTests.proj" />
+    <RequiresDelayedBuild Include="$(RepoRoot)src\DefaultBuilder\test\Microsoft.AspNetCore.TrimmingTests\Microsoft.AspNetCore.TrimmingTests.proj" />
     <RequiresDelayedBuild Include="$(RepoRoot)src\Grpc\JsonTranscoding\perf\Microsoft.AspNetCore.Grpc.Microbenchmarks\Microsoft.AspNetCore.Grpc.Microbenchmarks.csproj" />
     <RequiresDelayedBuild Include="$(RepoRoot)src\Grpc\JsonTranscoding\src\Microsoft.AspNetCore.Grpc.JsonTranscoding\Microsoft.AspNetCore.Grpc.JsonTranscoding.csproj" />
     <RequiresDelayedBuild Include="$(RepoRoot)src\Grpc\JsonTranscoding\src\Microsoft.AspNetCore.Grpc.Swagger\Microsoft.AspNetCore.Grpc.Swagger.csproj" />

+ 14 - 0
src/DefaultBuilder/test/Microsoft.AspNetCore.TrimmingTests/Microsoft.AspNetCore.TrimmingTests.proj

@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <ItemGroup>
+    <TestConsoleAppSourceFiles Include="SlimBuilderDoesNotDependOnX509Test.cs">
+      <DisabledFeatureSwitches>System.Text.Json.JsonSerializer.IsReflectionEnabledByDefault</DisabledFeatureSwitches>
+      <AdditionalSourceFiles>X509Utilities.cs</AdditionalSourceFiles>
+    </TestConsoleAppSourceFiles>
+    <TestConsoleAppSourceFiles Include="UseHttpsDoesDependOnX509Test.cs">
+      <DisabledFeatureSwitches>System.Text.Json.JsonSerializer.IsReflectionEnabledByDefault</DisabledFeatureSwitches>
+      <AdditionalSourceFiles>X509Utilities.cs</AdditionalSourceFiles>
+    </TestConsoleAppSourceFiles>
+  </ItemGroup>
+
+</Project>

+ 14 - 0
src/DefaultBuilder/test/Microsoft.AspNetCore.TrimmingTests/SlimBuilderDoesNotDependOnX509Test.cs

@@ -0,0 +1,14 @@
+// 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.Builder;
+
+var builder = WebApplication.CreateSlimBuilder(args);
+var app = builder.Build();
+
+if (X509Utilities.HasCertificateType)
+{
+    return -1;
+}
+
+return 100; // Success

+ 33 - 0
src/DefaultBuilder/test/Microsoft.AspNetCore.TrimmingTests/UseHttpsDoesDependOnX509Test.cs

@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Security.Cryptography.X509Certificates;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+
+var builder = WebApplication.CreateSlimBuilder(args);
+
+builder.WebHost.UseKestrel(serverOptions =>
+{
+    serverOptions.ListenLocalhost(5000, listenOptions =>
+    {
+        listenOptions.UseHttps();
+    });
+});
+
+try
+{
+    _ = builder.Build();
+}
+catch (InvalidOperationException)
+{
+    // Expected if there's no dev cert installed
+}
+
+if (!X509Utilities.HasCertificateType)
+{
+    return -1;
+}
+
+return 100; // Success

+ 40 - 0
src/DefaultBuilder/test/Microsoft.AspNetCore.TrimmingTests/X509Utilities.cs

@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Reflection;
+using Microsoft.AspNetCore.Builder;
+
+#nullable enable
+
+public static class X509Utilities
+{
+    public static bool HasCertificateType
+    {
+        get
+        {
+            var certificateType = GetType("System.Security.Cryptography", "System.Security.Cryptography.X509Certificates.X509Certificate");
+
+            // We're checking for members, rather than just the presence of the type,
+            // because Debugger Display types may reference it without actually
+            // causing a meaningful binary size increase.
+            return certificateType is not null && GetMembers(certificateType).Any();
+        }
+    }
+
+    [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2057:UnrecognizedReflectionPattern",
+        Justification = "Returning null when the type is unreferenced is desirable")]
+    private static Type? GetType(string assemblyName, string typeName)
+    {
+        return Type.GetType($"{typeName}, {assemblyName}");
+    }
+
+    [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
+        Justification = "Returning null when the type is unreferenced is desirable")]
+    private static MemberInfo[] GetMembers(Type type)
+    {
+        return type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
+    }
+}