Merge branch 'release' into dev
This commit is contained in:
commit
31a00f19f8
|
|
@ -10,8 +10,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
NuGet.Config = NuGet.Config
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.IISPlatformHandler", "src\Microsoft.AspNetCore.IISPlatformHandler\Microsoft.AspNetCore.IISPlatformHandler.xproj", "{ABE53415-83CE-4AF0-AF67-E52160C7862B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{EF30B533-D715-421A-92B7-92FEF460AC9C}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestSites", "test\TestSites\TestSites.xproj", "{E27453AD-9CA0-49A2-94FA-96337D77677D}"
|
||||
|
|
@ -20,10 +18,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C74B
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "IISSample", "samples\IISSample\IISSample.xproj", "{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-publish-iis.Tests", "test\dotnet-publish-iis.Tests\dotnet-publish-iis.Tests.xproj", "{CFB3AF72-0AF6-44CB-8815-6E4052C7B5A0}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-publish-iis", "src\dotnet-publish-iis\dotnet-publish-iis.xproj", "{E492AEF2-42C1-4399-B718-A6934EBB36AB}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server.IISIntegration", "src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.xproj", "{8B3446E8-E6A8-4591-AA63-A95837C6E97C}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests", "test\Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests\Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests.xproj", "{7F2F50C7-610F-4B69-B945-CA283511A587}"
|
||||
|
|
@ -40,10 +34,6 @@ Global
|
|||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{ABE53415-83CE-4AF0-AF67-E52160C7862B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ABE53415-83CE-4AF0-AF67-E52160C7862B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ABE53415-83CE-4AF0-AF67-E52160C7862B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ABE53415-83CE-4AF0-AF67-E52160C7862B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E27453AD-9CA0-49A2-94FA-96337D77677D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E27453AD-9CA0-49A2-94FA-96337D77677D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E27453AD-9CA0-49A2-94FA-96337D77677D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -52,14 +42,6 @@ Global
|
|||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CFB3AF72-0AF6-44CB-8815-6E4052C7B5A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CFB3AF72-0AF6-44CB-8815-6E4052C7B5A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CFB3AF72-0AF6-44CB-8815-6E4052C7B5A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CFB3AF72-0AF6-44CB-8815-6E4052C7B5A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E492AEF2-42C1-4399-B718-A6934EBB36AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E492AEF2-42C1-4399-B718-A6934EBB36AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E492AEF2-42C1-4399-B718-A6934EBB36AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E492AEF2-42C1-4399-B718-A6934EBB36AB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -85,11 +67,8 @@ Global
|
|||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{ABE53415-83CE-4AF0-AF67-E52160C7862B} = {04B1EDB6-E967-4D25-89B9-E6F8304038CD}
|
||||
{E27453AD-9CA0-49A2-94FA-96337D77677D} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
|
||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64} = {C74B8F36-FD2F-45C9-9B8A-00E7CF0126A9}
|
||||
{CFB3AF72-0AF6-44CB-8815-6E4052C7B5A0} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
|
||||
{E492AEF2-42C1-4399-B718-A6934EBB36AB} = {04B1EDB6-E967-4D25-89B9-E6F8304038CD}
|
||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C} = {04B1EDB6-E967-4D25-89B9-E6F8304038CD}
|
||||
{7F2F50C7-610F-4B69-B945-CA283511A587} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
|
||||
{4106DB10-E09F-480E-9CE6-B39235512EE6} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
"AdxVerificationCompositeRule"
|
||||
],
|
||||
"packages": {
|
||||
"dotnet-publish-iis": { },
|
||||
"Microsoft.AspNetCore.IISPlatformHandler": { },
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": { },
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,138 +0,0 @@
|
|||
// 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.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.Http.Features.Authentication;
|
||||
|
||||
namespace Microsoft.AspNetCore.IISPlatformHandler
|
||||
{
|
||||
internal class AuthenticationHandler : IAuthenticationHandler
|
||||
{
|
||||
internal AuthenticationHandler(HttpContext httpContext, IISPlatformHandlerOptions options, ClaimsPrincipal user)
|
||||
{
|
||||
HttpContext = httpContext;
|
||||
User = user;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
internal HttpContext HttpContext { get; }
|
||||
|
||||
internal IISPlatformHandlerOptions Options { get; }
|
||||
|
||||
internal ClaimsPrincipal User { get; }
|
||||
|
||||
internal IAuthenticationHandler PriorHandler { get; set; }
|
||||
|
||||
public Task AuthenticateAsync(AuthenticateContext context)
|
||||
{
|
||||
if (ShouldHandleScheme(context.AuthenticationScheme))
|
||||
{
|
||||
if (User != null)
|
||||
{
|
||||
context.Authenticated(User, properties: null,
|
||||
description: Options.AuthenticationDescriptions.FirstOrDefault(descrip =>
|
||||
string.Equals(User.Identity.AuthenticationType, descrip.AuthenticationScheme, StringComparison.Ordinal))?.Items);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.NotAuthenticated();
|
||||
}
|
||||
}
|
||||
|
||||
if (PriorHandler != null)
|
||||
{
|
||||
return PriorHandler.AuthenticateAsync(context);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ChallengeAsync(ChallengeContext context)
|
||||
{
|
||||
bool handled = false;
|
||||
if (ShouldHandleScheme(context.AuthenticationScheme))
|
||||
{
|
||||
switch (context.Behavior)
|
||||
{
|
||||
case ChallengeBehavior.Automatic:
|
||||
// If there is a principal already, invoke the forbidden code path
|
||||
if (User == null)
|
||||
{
|
||||
goto case ChallengeBehavior.Unauthorized;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto case ChallengeBehavior.Forbidden;
|
||||
}
|
||||
case ChallengeBehavior.Unauthorized:
|
||||
HttpContext.Response.StatusCode = 401;
|
||||
// We would normally set the www-authenticate header here, but IIS does that for us.
|
||||
break;
|
||||
case ChallengeBehavior.Forbidden:
|
||||
HttpContext.Response.StatusCode = 403;
|
||||
handled = true; // No other handlers need to consider this challenge.
|
||||
break;
|
||||
}
|
||||
context.Accept();
|
||||
}
|
||||
|
||||
if (!handled && PriorHandler != null)
|
||||
{
|
||||
return PriorHandler.ChallengeAsync(context);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public void GetDescriptions(DescribeSchemesContext context)
|
||||
{
|
||||
foreach (var description in Options.AuthenticationDescriptions)
|
||||
{
|
||||
context.Accept(description.Items);
|
||||
}
|
||||
|
||||
if (PriorHandler != null)
|
||||
{
|
||||
PriorHandler.GetDescriptions(context);
|
||||
}
|
||||
}
|
||||
|
||||
public Task SignInAsync(SignInContext context)
|
||||
{
|
||||
// Not supported, fall through
|
||||
if (PriorHandler != null)
|
||||
{
|
||||
return PriorHandler.SignInAsync(context);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SignOutAsync(SignOutContext context)
|
||||
{
|
||||
// Not supported, fall through
|
||||
if (PriorHandler != null)
|
||||
{
|
||||
return PriorHandler.SignOutAsync(context);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private bool ShouldHandleScheme(string authenticationScheme)
|
||||
{
|
||||
if (Options.AutomaticAuthentication && string.Equals(AuthenticationManager.AutomaticScheme, authenticationScheme, StringComparison.Ordinal))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return Options.AuthenticationDescriptions.Any(description => string.Equals(description.AuthenticationScheme, authenticationScheme, StringComparison.Ordinal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
// 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;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.IISPlatformHandler
|
||||
{
|
||||
internal class ForwardedTlsConnectionFeature : ITlsConnectionFeature
|
||||
{
|
||||
private StringValues _header;
|
||||
private X509Certificate2 _certificate;
|
||||
private ILogger _logger;
|
||||
|
||||
public ForwardedTlsConnectionFeature(ILogger logger, StringValues header)
|
||||
{
|
||||
_logger = logger;
|
||||
_header = header;
|
||||
}
|
||||
|
||||
public X509Certificate2 ClientCertificate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_certificate == null && _header != StringValues.Empty)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bytes = Convert.FromBase64String(_header);
|
||||
_certificate = new X509Certificate2(bytes);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(0, ex, "Failed to read the client certificate.");
|
||||
}
|
||||
}
|
||||
return _certificate;
|
||||
}
|
||||
set
|
||||
{
|
||||
_certificate = value;
|
||||
_header = StringValues.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<X509Certificate2> GetClientCertificateAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(ClientCertificate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
{
|
||||
public static class IISPlatformHandlerAddressExtensions
|
||||
{
|
||||
// This is defined by IIS's HttpPlatformHandler.
|
||||
private static readonly string ServerPort = "HTTP_PLATFORM_PORT";
|
||||
private static readonly string ServerPath = "HTTP_PLATFORM_APPL_PATH";
|
||||
|
||||
/// <summary>
|
||||
/// Configures the port and base path the server should listen on when running behind HttpPlatformHandler.
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
public static IWebHostBuilder UseIISPlatformHandlerUrl(this IWebHostBuilder app)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
var port = Environment.GetEnvironmentVariable(ServerPort);
|
||||
var path = Environment.GetEnvironmentVariable(ServerPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(port))
|
||||
{
|
||||
var address = "http://localhost:" + port + path;
|
||||
app.UseSetting(WebHostDefaults.ServerUrlsKey, address);
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
// 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.IISPlatformHandler
|
||||
{
|
||||
public class IISPlatformHandlerDefaults
|
||||
{
|
||||
public const string Negotiate = "Negotiate";
|
||||
public const string Ntlm = "NTLM";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
// 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.Globalization;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Http.Features.Authentication;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.IISPlatformHandler
|
||||
{
|
||||
public class IISPlatformHandlerMiddleware
|
||||
{
|
||||
private const string XIISWindowsAuthToken = "X-IIS-WindowsAuthToken"; // TODO: Legacy, remove before RTW
|
||||
private const string MSPlatformHandlerWinAuthToken = "MS-PLATFORM-HANDLER-WINAUTHTOKEN";
|
||||
private const string MSPlatformHandlerClientCert = "MS-PLATFORM-HANDLER-CLIENTCERT";
|
||||
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IISPlatformHandlerOptions _options;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public IISPlatformHandlerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions<IISPlatformHandlerOptions> options)
|
||||
{
|
||||
if (next == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(next));
|
||||
}
|
||||
if (loggerFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(loggerFactory));
|
||||
}
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
_next = next;
|
||||
_options = options.Value;
|
||||
_logger = loggerFactory.CreateLogger<IISPlatformHandlerMiddleware>();
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
if (_options.ForwardClientCertificate)
|
||||
{
|
||||
var header = httpContext.Request.Headers[MSPlatformHandlerClientCert];
|
||||
if (!StringValues.IsNullOrEmpty(header))
|
||||
{
|
||||
httpContext.Features.Set<ITlsConnectionFeature>(new ForwardedTlsConnectionFeature(_logger, header));
|
||||
}
|
||||
}
|
||||
|
||||
if (_options.ForwardWindowsAuthentication)
|
||||
{
|
||||
var winPrincipal = UpdateUser(httpContext);
|
||||
var handler = new AuthenticationHandler(httpContext, _options, winPrincipal);
|
||||
AttachAuthenticationHandler(handler);
|
||||
try
|
||||
{
|
||||
await _next(httpContext);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DetachAuthenticationhandler(handler);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await _next(httpContext);
|
||||
}
|
||||
}
|
||||
|
||||
private WindowsPrincipal UpdateUser(HttpContext httpContext)
|
||||
{
|
||||
var tokenHeader = httpContext.Request.Headers[MSPlatformHandlerWinAuthToken];
|
||||
|
||||
if (StringValues.IsNullOrEmpty(tokenHeader))
|
||||
{
|
||||
// TODO: Legacy, remove before RTW
|
||||
tokenHeader = httpContext.Request.Headers[XIISWindowsAuthToken];
|
||||
}
|
||||
|
||||
int hexHandle;
|
||||
WindowsPrincipal winPrincipal = null;
|
||||
if (!StringValues.IsNullOrEmpty(tokenHeader)
|
||||
&& int.TryParse(tokenHeader, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hexHandle))
|
||||
{
|
||||
// Always create the identity if the handle exists, we need to dispose it so it does not leak.
|
||||
var handle = new IntPtr(hexHandle);
|
||||
var winIdentity = new WindowsIdentity(handle);
|
||||
|
||||
// WindowsIdentity just duplicated the handle so we need to close the original.
|
||||
NativeMethods.CloseHandle(handle);
|
||||
|
||||
httpContext.Response.RegisterForDispose(winIdentity);
|
||||
winPrincipal = new WindowsPrincipal(winIdentity);
|
||||
|
||||
if (_options.AutomaticAuthentication)
|
||||
{
|
||||
// Don't get it from httpContext.User, that always returns a non-null anonymous user by default.
|
||||
var existingPrincipal = httpContext.Features.Get<IHttpAuthenticationFeature>()?.User;
|
||||
if (existingPrincipal != null)
|
||||
{
|
||||
httpContext.User = SecurityHelper.MergeUserPrincipal(existingPrincipal, winPrincipal);
|
||||
}
|
||||
else
|
||||
{
|
||||
httpContext.User = winPrincipal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return winPrincipal;
|
||||
}
|
||||
|
||||
private void AttachAuthenticationHandler(AuthenticationHandler handler)
|
||||
{
|
||||
var auth = handler.HttpContext.Features.Get<IHttpAuthenticationFeature>();
|
||||
if (auth == null)
|
||||
{
|
||||
auth = new HttpAuthenticationFeature();
|
||||
handler.HttpContext.Features.Set(auth);
|
||||
}
|
||||
handler.PriorHandler = auth.Handler;
|
||||
auth.Handler = handler;
|
||||
}
|
||||
|
||||
private void DetachAuthenticationhandler(AuthenticationHandler handler)
|
||||
{
|
||||
var auth = handler.HttpContext.Features.Get<IHttpAuthenticationFeature>();
|
||||
if (auth != null)
|
||||
{
|
||||
auth.Handler = handler.PriorHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
// 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.IISPlatformHandler;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
public static class IISPlatformHandlerMiddlewareExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds middleware for interacting with the IIS HttpPlatformHandler reverse proxy module.
|
||||
/// This will handle forwarded Windows Authentication, request scheme, remote IPs, etc..
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseIISPlatformHandler(this IApplicationBuilder app)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
return app.UseMiddleware<IISPlatformHandlerMiddleware>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds middleware for interacting with the IIS HttpPlatformHandler reverse proxy module.
|
||||
/// This will handle forwarded Windows Authentication, request scheme, remote IPs, etc..
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseIISPlatformHandler(this IApplicationBuilder app, IISPlatformHandlerOptions options)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
return app.UseMiddleware<IISPlatformHandlerMiddleware>(Options.Create(options));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.IISPlatformHandler;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
public class IISPlatformHandlerOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// If true the authentication middleware alter the request user coming in and respond to generic challenges.
|
||||
/// If false the authentication middleware will only provide identity and respond to challenges when explicitly indicated
|
||||
/// by the AuthenticationScheme.
|
||||
/// </summary>
|
||||
public bool AutomaticAuthentication { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// If true authentication middleware will try to authenticate using platform handler windows authentication
|
||||
/// If false authentication middleware won't be added
|
||||
/// </summary>
|
||||
public bool ForwardWindowsAuthentication { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Populates the ITLSConnectionFeature if the MS-PLATFORM-HANDLER-CLIENTCERT request header is present.
|
||||
/// </summary>
|
||||
public bool ForwardClientCertificate { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Additional information about the authentication type which is made available to the application.
|
||||
/// </summary>
|
||||
public IList<AuthenticationDescription> AuthenticationDescriptions { get; } = new List<AuthenticationDescription>()
|
||||
{
|
||||
new AuthenticationDescription()
|
||||
{
|
||||
AuthenticationScheme = IISPlatformHandlerDefaults.Negotiate
|
||||
},
|
||||
new AuthenticationDescription()
|
||||
{
|
||||
AuthenticationScheme = IISPlatformHandlerDefaults.Ntlm
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>abe53415-83ce-4af0-af67-e52160c7862b</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// 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.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.AspNetCore.IISPlatformHandler
|
||||
{
|
||||
internal class NativeMethods
|
||||
{
|
||||
#if DOTNET5_4
|
||||
private const string api_ms_win_core_handle_LIB = "api-ms-win-core-handle-l1-1-0.dll";
|
||||
#else
|
||||
private const string KERNEL32 = "kernel32.dll";
|
||||
#endif
|
||||
|
||||
#if DOTNET5_4
|
||||
[DllImport(api_ms_win_core_handle_LIB, ExactSpelling = true, SetLastError = true)]
|
||||
#else
|
||||
[DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)]
|
||||
#endif
|
||||
internal static extern bool CloseHandle(IntPtr handle);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
// 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.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-us")]
|
||||
[assembly: AssemblyCompany("Microsoft Corporation.")]
|
||||
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
|
||||
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"compilationOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk",
|
||||
"nowarn": [ "CS1591" ],
|
||||
"xmlDoc": true
|
||||
},
|
||||
"description": "ASP.NET 5 components for working with the IIS HttpPlatformHandler module.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/IISIntegration"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Hosting.Abstractions": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Http": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Http.Extensions": "1.0.0-*",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Extensions.Options": "1.0.0-*",
|
||||
"Microsoft.Extensions.SecurityHelper.Sources": {
|
||||
"type": "build",
|
||||
"version": "1.0.0-*"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": { },
|
||||
"netstandard1.3": {
|
||||
"dependencies": {
|
||||
"System.Security.Principal.Windows": "4.0.0-*"
|
||||
},
|
||||
"imports": [ "dotnet5.4" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
// 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.Extensions.Cli.Utils;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
namespace Microsoft.AspNetCore.Tools.PublishIIS
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
var app = new CommandLineApplication
|
||||
{
|
||||
Name = "dotnet publish-iis",
|
||||
FullName = "Asp.Net IIS Publisher",
|
||||
Description = "IIS Publisher for the Asp.Net web applications",
|
||||
};
|
||||
app.HelpOption("-h|--help");
|
||||
|
||||
var publishFolderOption = app.Option("--publish-folder|-p", "The path to the publish output folder", CommandOptionType.SingleValue);
|
||||
var webRootOption = app.Option("--webroot|-w", "The name of webroot folder", CommandOptionType.SingleValue);
|
||||
var projectPath = app.Argument("<PROJECT>", "The path to the project (project folder or project.json) being published. If empty the current directory is used.");
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
var publishFolder = publishFolderOption.Value();
|
||||
|
||||
if (publishFolder == null)
|
||||
{
|
||||
app.ShowHelp();
|
||||
return 2;
|
||||
}
|
||||
|
||||
Reporter.Output.WriteLine($"Configuring the following project for use with IIS: '{publishFolder}'");
|
||||
|
||||
var exitCode = new PublishIISCommand(publishFolder, projectPath.Value, webRootOption.Value()).Run();
|
||||
|
||||
Reporter.Output.WriteLine("Configuring project completed successfully");
|
||||
|
||||
return exitCode;
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
return app.Execute(args);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Reporter.Error.WriteLine(e.Message.Red());
|
||||
Reporter.Output.WriteLine(e.ToString().Yellow());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
// 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.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-us")]
|
||||
[assembly: AssemblyCompany("Microsoft Corporation.")]
|
||||
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
|
||||
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
// 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.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.Extensions.Cli.Utils;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Tools.PublishIIS
|
||||
{
|
||||
public class PublishIISCommand
|
||||
{
|
||||
private readonly string _publishFolder;
|
||||
private readonly string _projectPath;
|
||||
private readonly string _webRoot;
|
||||
|
||||
public PublishIISCommand(string publishFolder, string projectPath, string webRoot)
|
||||
{
|
||||
_publishFolder = publishFolder;
|
||||
_projectPath = projectPath;
|
||||
_webRoot = webRoot;
|
||||
}
|
||||
|
||||
public int Run()
|
||||
{
|
||||
var applicationBasePath = GetApplicationBasePath();
|
||||
var webRoot = GetWebRoot(applicationBasePath);
|
||||
|
||||
XDocument webConfigXml = null;
|
||||
var webRootDirectory = Path.Combine(_publishFolder, webRoot);
|
||||
var webConfigPath = Path.Combine(webRootDirectory, "web.config");
|
||||
if (File.Exists(webConfigPath))
|
||||
{
|
||||
Reporter.Output.WriteLine($"Updating web.config at '{webConfigPath}'");
|
||||
|
||||
try
|
||||
{
|
||||
webConfigXml = XDocument.Load(webConfigPath);
|
||||
}
|
||||
catch (XmlException) { }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Directory.Exists(webRootDirectory))
|
||||
{
|
||||
Reporter.Output.WriteLine($"No webroot directory found. Creating '{webRootDirectory}'");
|
||||
Directory.CreateDirectory(webRootDirectory);
|
||||
}
|
||||
|
||||
Reporter.Output.WriteLine($"No web.config found. Creating '{webConfigPath}'");
|
||||
}
|
||||
|
||||
var applicationName = GetApplicationName(applicationBasePath) + ".exe";
|
||||
var transformedConfig = WebConfigTransform.Transform(webConfigXml, applicationName, ConfigureForAzure());
|
||||
|
||||
using (var f = new FileStream(webConfigPath, FileMode.Create))
|
||||
{
|
||||
transformedConfig.Save(f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private string GetApplicationBasePath()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_projectPath))
|
||||
{
|
||||
var fullProjectPath = Path.GetFullPath(_projectPath);
|
||||
|
||||
return Path.GetFileName(fullProjectPath) == "project.json"
|
||||
? Path.GetDirectoryName(fullProjectPath)
|
||||
: fullProjectPath;
|
||||
}
|
||||
|
||||
return Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
private string GetApplicationName(string applicationBasePath)
|
||||
{
|
||||
return ProjectReader.GetProject(Path.Combine(applicationBasePath, "project.json")).Name;
|
||||
}
|
||||
|
||||
private string GetWebRoot(string applicationBasePath)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_webRoot))
|
||||
{
|
||||
return _webRoot;
|
||||
}
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(applicationBasePath)
|
||||
.AddJsonFile("hosting.json", optional: true);
|
||||
|
||||
var webroot = builder.Build()["webroot"];
|
||||
|
||||
if (!string.IsNullOrEmpty(webroot))
|
||||
{
|
||||
return webroot;
|
||||
}
|
||||
|
||||
if (Directory.Exists(Path.Combine(applicationBasePath, "wwwroot")))
|
||||
{
|
||||
return "wwwroot";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static bool ConfigureForAzure()
|
||||
{
|
||||
var configureForAzureValue = Environment.GetEnvironmentVariable("DOTNET_CONFIGURE_AZURE");
|
||||
return string.Equals(configureForAzureValue, "true", StringComparison.Ordinal) ||
|
||||
string.Equals(configureForAzureValue, "1", StringComparison.Ordinal) ||
|
||||
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Tools.PublishIIS
|
||||
{
|
||||
public static class WebConfigTransform
|
||||
{
|
||||
public static XDocument Transform(XDocument webConfig, string appName, bool configureForAzure)
|
||||
{
|
||||
const string HandlersElementName = "handlers";
|
||||
const string httpPlatformElementName = "httpPlatform";
|
||||
|
||||
webConfig = webConfig == null || webConfig.Root.Name.LocalName != "configuration"
|
||||
? XDocument.Parse("<configuration />")
|
||||
: webConfig;
|
||||
|
||||
var webServerSection = GetOrCreateChild(webConfig.Root, "system.webServer");
|
||||
|
||||
TransformHandlers(GetOrCreateChild(webServerSection, HandlersElementName));
|
||||
TransformHttpPlatform(GetOrCreateChild(webServerSection, httpPlatformElementName), appName, configureForAzure);
|
||||
|
||||
// make sure that the httpPlatform element is after handlers element
|
||||
var httpPlatformElement = webServerSection.Element(HandlersElementName)
|
||||
.ElementsBeforeSelf(httpPlatformElementName).SingleOrDefault();
|
||||
if (httpPlatformElement != null)
|
||||
{
|
||||
httpPlatformElement.Remove();
|
||||
webServerSection.Element(HandlersElementName).AddAfterSelf(httpPlatformElement);
|
||||
}
|
||||
|
||||
return webConfig;
|
||||
}
|
||||
|
||||
private static void TransformHandlers(XElement handlersElement)
|
||||
{
|
||||
var platformHandlerElement =
|
||||
handlersElement.Elements("add")
|
||||
.FirstOrDefault(e => string.Equals((string)e.Attribute("name"), "httpplatformhandler", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (platformHandlerElement == null)
|
||||
{
|
||||
platformHandlerElement = new XElement("add");
|
||||
handlersElement.Add(platformHandlerElement);
|
||||
}
|
||||
|
||||
platformHandlerElement.SetAttributeValue("name", "httpPlatformHandler");
|
||||
SetAttributeValueIfEmpty(platformHandlerElement, "path", "*");
|
||||
SetAttributeValueIfEmpty(platformHandlerElement, "verb", "*");
|
||||
SetAttributeValueIfEmpty(platformHandlerElement, "modules", "httpPlatformHandler");
|
||||
SetAttributeValueIfEmpty(platformHandlerElement, "resourceType", "Unspecified");
|
||||
}
|
||||
|
||||
private static void TransformHttpPlatform(XElement httpPlatformElement, string appName, bool configureForAzure)
|
||||
{
|
||||
var appPath = Path.Combine(configureForAzure ? @"%home%\site" : "..", appName).Replace("/", "\\");
|
||||
var logPath = Path.Combine(configureForAzure ? @"\\?\%home%\LogFiles" : @"..\logs", "stdout.log").Replace("/", "\\");
|
||||
|
||||
httpPlatformElement.SetAttributeValue("processPath", appPath);
|
||||
SetAttributeValueIfEmpty(httpPlatformElement, "stdoutLogEnabled", "false");
|
||||
SetAttributeValueIfEmpty(httpPlatformElement, "stdoutLogFile", logPath);
|
||||
SetAttributeValueIfEmpty(httpPlatformElement, "startupTimeLimit", "3600");
|
||||
|
||||
AddApplicationBase(httpPlatformElement);
|
||||
}
|
||||
|
||||
private static void AddApplicationBase(XElement httpPlatformElement)
|
||||
{
|
||||
const string contentRootKeyName = "ASPNETCORE_CONTENTROOT";
|
||||
|
||||
var envVariables = GetOrCreateChild(httpPlatformElement, "environmentVariables");
|
||||
var appBaseElement = envVariables.Elements("environmentVariable").SingleOrDefault(e =>
|
||||
string.Equals((string)e.Attribute("name"), contentRootKeyName, StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
if (appBaseElement == null)
|
||||
{
|
||||
appBaseElement = new XElement("environmentVariable", new XAttribute("name", contentRootKeyName));
|
||||
envVariables.AddFirst(appBaseElement);
|
||||
}
|
||||
|
||||
appBaseElement.SetAttributeValue("value", ".");
|
||||
}
|
||||
|
||||
private static XElement GetOrCreateChild(XElement parent, string childName)
|
||||
{
|
||||
var childElement = parent.Element(childName);
|
||||
if (childElement == null)
|
||||
{
|
||||
childElement = new XElement(childName);
|
||||
parent.Add(childElement);
|
||||
}
|
||||
return childElement;
|
||||
}
|
||||
|
||||
private static void SetAttributeValueIfEmpty(XElement element, string attributeName, string value)
|
||||
{
|
||||
element.SetAttributeValue(attributeName, (string)element.Attribute(attributeName) ?? value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>e492aef2-42c1-4399-b718-a6934ebb36ab</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
{
|
||||
"name": "dotnet-publish-iis",
|
||||
"version": "1.0.0-*",
|
||||
"compilationOptions": {
|
||||
"emitEntryPoint": true,
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk",
|
||||
"nowarn": [ "CS1591" ],
|
||||
"xmlDoc": true
|
||||
},
|
||||
"compile": "../Microsoft.AspNetCore.Server.IISIntegration.Tools/Internal/*.cs",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.CommandLineUtils": "1.0.0-*",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0-*",
|
||||
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||
"System.Diagnostics.Process": "4.1.0-*"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"portable-net451+win8",
|
||||
"dnxcore50"
|
||||
],
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"type": "platform",
|
||||
"version": "1.0.0-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
using Xunit;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Tools.PublishIIS.Tests
|
||||
{
|
||||
public class PublishIISCommandFacts
|
||||
{
|
||||
private class Folders
|
||||
{
|
||||
public string TestRoot;
|
||||
public string PublishOutput;
|
||||
public string ProjectPath;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PublishIIS_uses_default_values_if_options_not_specified()
|
||||
{
|
||||
var webRoot = "wwwroot";
|
||||
var folders = CreateTestDir("{}", webRoot);
|
||||
|
||||
new PublishIISCommand(folders.PublishOutput, folders.ProjectPath, null).Run();
|
||||
|
||||
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
|
||||
.Descendants("httpPlatform").Attributes("processPath").Single();
|
||||
|
||||
Assert.Equal($@"..\projectDir.exe", processPath);
|
||||
|
||||
Directory.Delete(folders.TestRoot, recursive: true);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("awesomeApp")]
|
||||
[InlineData("awesome.App")]
|
||||
public void PublishIIS_reads_application_name_from_project_json_if_exists(string projectName)
|
||||
{
|
||||
var webRoot = "wwwroot";
|
||||
var folders = CreateTestDir($@"{{ ""name"": ""{projectName}"" }}", webRoot);
|
||||
|
||||
new PublishIISCommand(folders.PublishOutput, folders.ProjectPath, null).Run();
|
||||
|
||||
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
|
||||
.Descendants("httpPlatform").Attributes("processPath").Single();
|
||||
|
||||
Assert.Equal($@"..\{projectName}.exe", processPath);
|
||||
|
||||
Directory.Delete(folders.TestRoot, recursive: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PublishIIS_uses_webroot_from_hosting_json()
|
||||
{
|
||||
var webRoot = "mywebroot";
|
||||
var folders = CreateTestDir("{}", webRoot);
|
||||
File.WriteAllText(Path.Combine(folders.ProjectPath, "hosting.json"), $"{{ \"webroot\": \"{webRoot}\"}}");
|
||||
|
||||
new PublishIISCommand(folders.PublishOutput, folders.ProjectPath, null).Run();
|
||||
|
||||
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
|
||||
.Descendants("httpPlatform").Attributes("processPath").Single();
|
||||
|
||||
Assert.Equal(@"..\projectDir.exe", processPath);
|
||||
|
||||
Directory.Delete(folders.TestRoot, recursive: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PublishIIS_webroot_switch_takes_precedence_over_hosting_json()
|
||||
{
|
||||
var webRoot = "mywebroot";
|
||||
var folders = CreateTestDir("{}", webRoot);
|
||||
File.WriteAllText(Path.Combine(folders.ProjectPath, "hosting.json"), $"{{ \"webroot\": \"wwwroot\"}}");
|
||||
|
||||
new PublishIISCommand(folders.PublishOutput, folders.ProjectPath, webRoot).Run();
|
||||
|
||||
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
|
||||
.Descendants("httpPlatform").Attributes("processPath").Single();
|
||||
|
||||
Assert.Equal(@"..\projectDir.exe", processPath);
|
||||
|
||||
Directory.Delete(folders.TestRoot, recursive: true);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("projectDir")]
|
||||
[InlineData("project.Dir")]
|
||||
public void PublishIIS_accepts_path_to_project_json_as_project_path(string projectDir)
|
||||
{
|
||||
var webRoot = "wwwroot";
|
||||
var folders = CreateTestDir("{}", webRoot, projectDir);
|
||||
|
||||
new PublishIISCommand(folders.PublishOutput, Path.Combine(folders.ProjectPath, "project.json"), null).Run();
|
||||
|
||||
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
|
||||
.Descendants("httpPlatform").Attributes("processPath").Single();
|
||||
|
||||
Assert.Equal($@"..\{projectDir}.exe", processPath);
|
||||
|
||||
Directory.Delete(folders.TestRoot, recursive: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PublishIIS_modifies_existing_web_config()
|
||||
{
|
||||
var webRoot = "wwwroot";
|
||||
var folders = CreateTestDir("{}", webRoot);
|
||||
|
||||
File.WriteAllText(Path.Combine(folders.PublishOutput, webRoot, "web.config"),
|
||||
@"<configuration>
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name=""httpPlatformHandler"" path=""*"" verb=""*"" modules=""httpPlatformHandler"" resourceType=""Unspecified""/>
|
||||
</handlers>
|
||||
<httpPlatform processPath=""%________%"" stdoutLogEnabled=""false"" startupTimeLimit=""1234""/>
|
||||
</system.webServer>
|
||||
</configuration>");
|
||||
|
||||
new PublishIISCommand(folders.PublishOutput, Path.Combine(folders.ProjectPath, "project.json"), null).Run();
|
||||
|
||||
var httpPlatformElement = GetPublishedWebConfig(folders.PublishOutput, webRoot)
|
||||
.Descendants("httpPlatform").Single();
|
||||
|
||||
Assert.Equal(@"..\projectDir.exe", (string)httpPlatformElement.Attribute("processPath"));
|
||||
Assert.Equal(@"1234", (string)httpPlatformElement.Attribute("startupTimeLimit"));
|
||||
|
||||
Directory.Delete(folders.TestRoot, recursive: true);
|
||||
}
|
||||
|
||||
private XDocument GetPublishedWebConfig(string publishOut, string webRoot)
|
||||
{
|
||||
return XDocument.Load(Path.Combine(publishOut, webRoot, "web.config"));
|
||||
}
|
||||
|
||||
private Folders CreateTestDir(string projectJson, string webRoot, string projectDir = "projectDir")
|
||||
{
|
||||
var testRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(testRoot);
|
||||
|
||||
var projectPath = Path.Combine(testRoot, projectDir);
|
||||
Directory.CreateDirectory(projectPath);
|
||||
Directory.CreateDirectory(Path.Combine(projectPath, webRoot));
|
||||
File.WriteAllText(Path.Combine(projectPath, "project.json"), projectJson);
|
||||
|
||||
var publishOut = Path.Combine(testRoot, "publishOut");
|
||||
Directory.CreateDirectory(publishOut);
|
||||
Directory.CreateDirectory(Path.Combine(publishOut, webRoot));
|
||||
|
||||
return new Folders { TestRoot = testRoot, ProjectPath = projectPath, PublishOutput = publishOut };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
using Xunit;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Tools.PublishIIS.Tests
|
||||
{
|
||||
public class WebConfigTransformFacts
|
||||
{
|
||||
private XDocument WebConfigTemplate => XDocument.Parse(
|
||||
@"<configuration>
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name=""httpPlatformHandler"" path=""*"" verb=""*"" modules=""httpPlatformHandler"" resourceType=""Unspecified""/>
|
||||
</handlers>
|
||||
<httpPlatform processPath=""..\test.exe"" stdoutLogEnabled=""false"" stdoutLogFile=""..\logs\stdout.log"" startupTimeLimit=""3600"">
|
||||
<environmentVariables>
|
||||
<environmentVariable name=""ASPNETCORE_CONTENTROOT"" value=""."" />
|
||||
</environmentVariables>
|
||||
</httpPlatform>
|
||||
</system.webServer>
|
||||
</configuration>");
|
||||
|
||||
[Fact]
|
||||
public void WebConfigTransform_creates_new_config_if_one_does_not_exist()
|
||||
{
|
||||
Assert.True(XNode.DeepEquals(WebConfigTemplate,
|
||||
WebConfigTransform.Transform(null, "test.exe", configureForAzure: false)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebConfigTransform_creates_new_config_if_one_has_unexpected_format()
|
||||
{
|
||||
Assert.True(XNode.DeepEquals(WebConfigTemplate,
|
||||
WebConfigTransform.Transform(XDocument.Parse("<unexpected />"), "test.exe", configureForAzure: false)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new object[] { new[] { "system.webServer" } })]
|
||||
[InlineData(new object[] { new[] { "add" } })]
|
||||
[InlineData(new object[] { new[] { "handlers" } })]
|
||||
[InlineData(new object[] { new[] { "httpPlatform" } })]
|
||||
[InlineData(new object[] { new[] { "environmentVariables" } })]
|
||||
[InlineData(new object[] { new[] { "environmentVariable" } })]
|
||||
[InlineData(new object[] { new[] { "handlers", "httpPlatform", "environmentVariables" } })]
|
||||
public void WebConfigTransform_adds_missing_elements(string[] elementNames)
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
foreach (var elementName in elementNames)
|
||||
{
|
||||
input.Descendants(elementName).Remove();
|
||||
}
|
||||
|
||||
Assert.True(XNode.DeepEquals(WebConfigTemplate,
|
||||
WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("add", "path", "test")]
|
||||
[InlineData("add", "verb", "test")]
|
||||
[InlineData("add", "modules", "mods")]
|
||||
[InlineData("add", "resourceType", "Either")]
|
||||
[InlineData("httpPlatform", "stdoutLogEnabled", "true")]
|
||||
[InlineData("httpPlatform", "startupTimeLimit", "1200")]
|
||||
[InlineData("httpPlatform", "arguments", "arg1")]
|
||||
[InlineData("httpPlatform", "stdoutLogFile", "logfile.log")]
|
||||
public void WebConfigTransform_wont_override_custom_values(string elementName, string attributeName, string attributeValue)
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
input.Descendants(elementName).Single().SetAttributeValue(attributeName, attributeValue);
|
||||
|
||||
var output = WebConfigTransform.Transform(input, "test.exe", configureForAzure: false);
|
||||
Assert.Equal(attributeValue, (string)output.Descendants(elementName).Single().Attribute(attributeName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebConfigTransform_overwrites_processPath()
|
||||
{
|
||||
var newProcessPath =
|
||||
(string)WebConfigTransform.Transform(WebConfigTemplate, "app.exe", configureForAzure: false)
|
||||
.Descendants("httpPlatform").Single().Attribute("processPath");
|
||||
|
||||
Assert.Equal(@"..\app.exe", newProcessPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebConfigTransform_fixes_httpPlatformHandler_casing()
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
input.Descendants("add").Single().SetAttributeValue("name", "httpplatformhandler");
|
||||
|
||||
Assert.True(XNode.DeepEquals(WebConfigTemplate,
|
||||
WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebConfigTransform_does_not_remove_children_of_httpPlatform_element()
|
||||
{
|
||||
var envVarElement =
|
||||
new XElement("environmentVariable", new XAttribute("name", "ENVVAR"), new XAttribute("value", "123"));
|
||||
|
||||
var input = WebConfigTemplate;
|
||||
input.Descendants("environmentVariable").Single().Add(envVarElement);
|
||||
|
||||
Assert.True(XNode.DeepEquals(envVarElement,
|
||||
WebConfigTransform.Transform(input, "app.exe", configureForAzure: false)
|
||||
.Descendants("environmentVariable").SingleOrDefault(e => (string)e.Attribute("name") == "ENVVAR")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebConfigTransform_adds_stdoutLogEnabled_if_attribute_is_missing()
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
input.Descendants("httpPlatform").Attributes("stdoutLogEnabled").Remove();
|
||||
|
||||
Assert.Equal(
|
||||
"false",
|
||||
(string)WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)
|
||||
.Descendants().Attributes("stdoutLogEnabled").Single());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("false")]
|
||||
[InlineData("true")]
|
||||
public void WebConfigTransform_adds_stdoutLogFile_if_attribute_is_missing(string stdoutLogFile)
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
|
||||
var httpPlatformElement = input.Descendants("httpPlatform").Single();
|
||||
httpPlatformElement.Attribute("stdoutLogEnabled").Remove();
|
||||
if (stdoutLogFile != null)
|
||||
{
|
||||
httpPlatformElement.SetAttributeValue("stdoutLogEnabled", stdoutLogFile);
|
||||
}
|
||||
|
||||
Assert.Equal(
|
||||
@"..\logs\stdout.log",
|
||||
(string)WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)
|
||||
.Descendants().Attributes("stdoutLogFile").Single());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("true")]
|
||||
[InlineData("false")]
|
||||
public void WebConfigTransform_does_not_change_existing_stdoutLogEnabled(string stdoutLogEnabledValue)
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
var httpPlatformElement = input.Descendants("httpPlatform").Single();
|
||||
|
||||
httpPlatformElement.SetAttributeValue("stdoutLogFile", "mylog.txt");
|
||||
httpPlatformElement.Attributes("stdoutLogEnabled").Remove();
|
||||
if (stdoutLogEnabledValue != null)
|
||||
{
|
||||
input.Descendants("httpPlatform").Single().SetAttributeValue("stdoutLogEnabled", stdoutLogEnabledValue);
|
||||
}
|
||||
|
||||
Assert.Equal(
|
||||
"mylog.txt",
|
||||
(string)WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)
|
||||
.Descendants().Attributes("stdoutLogFile").Single());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebConfigTransform_correctly_configures_for_Azure()
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
input.Descendants("httpPlatform").Attributes().Remove();
|
||||
|
||||
var httPlatformElement = WebConfigTransform.Transform(input, "test.exe", configureForAzure: true)
|
||||
.Descendants("httpPlatform").Single();
|
||||
httPlatformElement.Elements().Remove();
|
||||
|
||||
Assert.True(XNode.DeepEquals(
|
||||
XDocument.Parse(@"<httpPlatform processPath=""%home%\site\test.exe"" stdoutLogEnabled=""false""
|
||||
stdoutLogFile=""\\?\%home%\LogFiles\stdout.log"" startupTimeLimit=""3600""/>").Root,
|
||||
httPlatformElement));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebConfigTransform_overrites_value_for_ASPNET_APPLICATIONBASE()
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
input.Descendants("environmentVariable").Single().SetAttributeValue("value", "abc");
|
||||
|
||||
Assert.True(XNode.DeepEquals(WebConfigTemplate,
|
||||
WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)));
|
||||
}
|
||||
|
||||
private bool VerifyMissingElementCreated(params string[] elementNames)
|
||||
{
|
||||
var input = WebConfigTemplate;
|
||||
foreach (var elementName in elementNames)
|
||||
{
|
||||
input.Descendants(elementName).Remove();
|
||||
}
|
||||
|
||||
return XNode.DeepEquals(WebConfigTemplate,
|
||||
WebConfigTransform.Transform(input, "test.exe", configureForAzure: false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>cfb3af72-0af6-44cb-8815-6e4052c7b5a0</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"xunit": "2.1.0",
|
||||
"dotnet-publish-iis": "1.0.0-*",
|
||||
"System.Diagnostics.Process": "4.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"portable-net451+win8",
|
||||
"dnxcore50",
|
||||
"netstandardapp1.5"
|
||||
],
|
||||
"dependencies": {
|
||||
"dotnet-test-xunit": "1.0.0-dev-*",
|
||||
"Microsoft.NETCore.App": {
|
||||
"type": "platform",
|
||||
"version": "1.0.0-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"testRunner": "xunit"
|
||||
}
|
||||
Loading…
Reference in New Issue