Skip to content

Certsign #10356

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

Closed
wants to merge 14 commits into from
1 change: 1 addition & 0 deletions eng/ProjectReferences.props
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Abstractions\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.csproj" RefProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Abstractions\ref\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Libuv\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" RefProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Libuv\ref\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Sockets\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj" RefProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Sockets\ref\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Certificate" ProjectPath="$(RepoRoot)src\Security\Authentication\Certificate\src\Microsoft.AspNetCore.Authentication.Certificate.csproj" RefProjectPath="$(RepoRoot)src\Security\Authentication\Certificate\ref\Microsoft.AspNetCore.Authentication.Certificate.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Cookies" ProjectPath="$(RepoRoot)src\Security\Authentication\Cookies\src\Microsoft.AspNetCore.Authentication.Cookies.csproj" RefProjectPath="$(RepoRoot)src\Security\Authentication\Cookies\ref\Microsoft.AspNetCore.Authentication.Cookies.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication" ProjectPath="$(RepoRoot)src\Security\Authentication\Core\src\Microsoft.AspNetCore.Authentication.csproj" RefProjectPath="$(RepoRoot)src\Security\Authentication\Core\ref\Microsoft.AspNetCore.Authentication.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Facebook" ProjectPath="$(RepoRoot)src\Security\Authentication\Facebook\src\Microsoft.AspNetCore.Authentication.Facebook.csproj" RefProjectPath="$(RepoRoot)src\Security\Authentication\Facebook\ref\Microsoft.AspNetCore.Authentication.Facebook.csproj" />
Expand Down
1 change: 1 addition & 0 deletions eng/SharedFramework.Local.props
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Server.Kestrel" />
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions" />
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" />
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Authentication.Certificate" />
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Authentication.Cookies" />
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Authentication" />
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Authentication.OAuth" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

namespace Microsoft.AspNetCore.Builder
{
public static partial class CertificateForwarderExtensions
{
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddCertificateHeaderForwarding(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<Microsoft.AspNetCore.HttpOverrides.CertificateForwarderOptions> configure) { throw null; }
public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseCertificateHeaderForwarding(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { throw null; }
}
public static partial class ForwardedHeadersExtensions
{
public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseForwardedHeaders(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) { throw null; }
Expand Down Expand Up @@ -37,6 +42,18 @@ public HttpMethodOverrideOptions() { }
}
namespace Microsoft.AspNetCore.HttpOverrides
{
public partial class CertificateForwarderMiddleware
{
public CertificateForwarderMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.HttpOverrides.CertificateForwarderOptions> options) { }
[System.Diagnostics.DebuggerStepThroughAttribute]
public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext httpContext) { throw null; }
}
public partial class CertificateForwarderOptions
{
public System.Func<string, System.Security.Cryptography.X509Certificates.X509Certificate2> HeaderConverter;
public CertificateForwarderOptions() { }
public string CertificateHeader { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
[System.FlagsAttribute]
public enum ForwardedHeaders
{
Expand Down
53 changes: 53 additions & 0 deletions src/Middleware/HttpOverrides/src/CertificateForwarderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;

using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using System.Security.Cryptography.X509Certificates;

namespace Microsoft.AspNetCore.Builder
{
public static class CertificateForwarderExtensions
{
/// <summary>
/// Adds a middleware to the pipeline that will look for a base64 encoded certificate in a request header
/// and put that certificate on the request client certificate property.
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseCertificateHeaderForwarding(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}

return app.UseMiddleware<CertificateForwarderMiddleware>();
}

/// <summary>
/// Adds certificate forwarding to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="configure">An action delegate to configure the provided <see cref="CertificateForwarderOptions"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection AddCertificateHeaderForwarding(
this IServiceCollection services,
Action<CertificateForwarderOptions> configure)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}

if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}

return services.Configure(configure);
}
}
}
68 changes: 68 additions & 0 deletions src/Middleware/HttpOverrides/src/CertificateForwarderMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Microsoft.AspNetCore.HttpOverrides
{
public class CertificateForwarderMiddleware
{
private readonly RequestDelegate _next;
private readonly CertificateForwarderOptions _options;
private readonly ILogger _logger;

public CertificateForwarderMiddleware(
RequestDelegate next,
ILoggerFactory loggerFactory,
IOptions<CertificateForwarderOptions> options)
{
_next = next ?? throw new ArgumentNullException(nameof(next));

if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}

if (options == null)
{
throw new ArgumentNullException(nameof(options));
}

_options = options.Value;
_logger = loggerFactory.CreateLogger<CertificateForwarderMiddleware>();
}

public async Task Invoke(HttpContext httpContext)
{
if (!string.IsNullOrWhiteSpace(_options.CertificateHeader))
{
var clientCertificate = await httpContext.Connection.GetClientCertificateAsync();

if (clientCertificate == null)
{
// Check for forwarding header
string certificateHeader = httpContext.Request.Headers[_options.CertificateHeader];
if (!string.IsNullOrEmpty(certificateHeader))
{
try
{
httpContext.Connection.ClientCertificate = _options.HeaderConverter(certificateHeader);
}
catch
{
_logger.LogError("Could not read certificate from header.");
}
}
}
}

await _next(httpContext);
}
}
}
27 changes: 27 additions & 0 deletions src/Middleware/HttpOverrides/src/CertificateForwarderOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Security.Cryptography.X509Certificates;

namespace Microsoft.AspNetCore.HttpOverrides
{
public class CertificateForwarderOptions
{
/// <summary>
/// The header name containing the Base64 encoded client certificate.
/// </summary>
/// <remarks>
/// This defaults to X-ARR-ClientCert, which is the header Azure Web Apps uses.
/// </remarks>
public string CertificateHeader { get; set; } = "X-ARR-ClientCert";

/// <summary>
/// The function used to convert the header to an instance of <see cref="X509Certificate2"/>.
/// </summary>
/// <remarks>
/// This defaults to a conversion from a base64 converted string.
/// </remarks>
public Func<string, X509Certificate2> HeaderConverter = (headerValue) => new X509Certificate2(Convert.FromBase64String(headerValue));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
<Compile Include="Microsoft.AspNetCore.Authentication.Certificate.netcoreapp3.0.cs" />
<Reference Include="Microsoft.AspNetCore.Authentication" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.AspNetCore.Authentication.Certificate
{
public static partial class CertificateAuthenticationDefaults
{
public const string AuthenticationScheme = "Certificate";
public const string CertificateItemsKey = "Certificate";
}
public partial class CertificateAuthenticationEvents
{
public CertificateAuthenticationEvents() { }
public System.Func<Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationFailedContext, System.Threading.Tasks.Task> OnAuthenticationFailed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public System.Func<Microsoft.AspNetCore.Authentication.Certificate.ValidateCertificateContext, System.Threading.Tasks.Task> OnValidateCertificate { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public virtual System.Threading.Tasks.Task AuthenticationFailed(Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationFailedContext context) { throw null; }
public virtual System.Threading.Tasks.Task ValidateCertificate(Microsoft.AspNetCore.Authentication.Certificate.ValidateCertificateContext context) { throw null; }
}
public partial class CertificateAuthenticationFailedContext : Microsoft.AspNetCore.Authentication.ResultContext<Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationOptions>
{
public CertificateAuthenticationFailedContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationOptions options) : base (default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationOptions)) { }
public System.Exception Exception { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
public partial class CertificateAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions
{
public CertificateAuthenticationOptions() { }
public Microsoft.AspNetCore.Authentication.Certificate.CertificateTypes AllowedCertificateTypes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public new Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationEvents Events { get { throw null; } set { } }
public System.Security.Cryptography.X509Certificates.X509RevocationFlag RevocationFlag { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public System.Security.Cryptography.X509Certificates.X509RevocationMode RevocationMode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public bool ValidateCertificateUse { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public bool ValidateValidityPeriod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
[System.FlagsAttribute]
public enum CertificateTypes
{
Chained = 1,
SelfSigned = 2,
All = 3,
}
public static partial class CertificateValidator
{
public static bool DisableChannelValidation(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors errors) { throw null; }
}
public partial class ValidateCertificateContext : Microsoft.AspNetCore.Authentication.ResultContext<Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationOptions>
{
public ValidateCertificateContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationOptions options) : base (default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationOptions)) { }
public System.Security.Cryptography.X509Certificates.X509Certificate2 ClientCertificate { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
public static partial class X509Certificate2Extensions
{
public static bool IsSelfSigned(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; }
}
}
namespace Microsoft.Extensions.DependencyInjection
{
public static partial class CertificateAuthenticationAppBuilderExtensions
{
public static Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddCertificate(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder) { throw null; }
public static Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddCertificate(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder, System.Action<Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationOptions> configureOptions) { throw null; }
public static Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddCertificate(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder, string authenticationScheme) { throw null; }
public static Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddCertificate(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder, string authenticationScheme, System.Action<Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationOptions> configureOptions) { throw null; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;

namespace Certificate.Sample.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
Loading