Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .spelling
Original file line number Diff line number Diff line change
Expand Up @@ -1239,5 +1239,7 @@ v6.0.

#region test/tools/WebListener/README.md Overrides
- test/tools/WebListener/README.md
Auth
NTLM
ResponseHeaders
#endregion
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,12 @@ internal virtual void ValidateParameters()
"WebCmdletAllowUnencryptedAuthenticationRequiredException");
ThrowTerminatingError(error);
}
if (!AllowUnencryptedAuthentication && (null != Credential || UseDefaultCredentials) && (Uri.Scheme != "https"))
{
ErrorRecord error = GetValidationError(WebCmdletStrings.AllowUnencryptedAuthenticationRequired,
"WebCmdletAllowUnencryptedAuthenticationRequiredException");
ThrowTerminatingError(error);
}

// credentials
if (UseDefaultCredentials && (null != Credential))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,8 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {
$credential = [pscredential]::new("testuser",$token)
$httpUri = Get-WebListenerUrl -Test 'Get'
$httpsUri = Get-WebListenerUrl -Test 'Get' -Https
$httpBasicUri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic'
$httpsBasicUri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic' -Https
$testCases = @(
@{Authentication = "bearer"}
@{Authentication = "OAuth"}
Expand Down Expand Up @@ -1412,6 +1414,83 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {

$result.Headers.Authorization | Should BeExactly "Bearer testpassword"
}

It "Verifies Invoke-WebRequest Negotiated -Credential over HTTPS" {
$params = @{
Uri = $httpsBasicUri
Credential = $credential
SkipCertificateCheck = $true
}
$Response = Invoke-WebRequest @params
$result = $response.Content | ConvertFrom-Json

$result.Headers.Authorization | Should BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
}

It "Verifies Invoke-WebRequest Negotiated -Credential Requires HTTPS" {
$params = @{
Uri = $httpBasicUri
Credential = $credential
ErrorAction = 'Stop'
}
{ Invoke-WebRequest @params } | ShouldBeErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}

It "Verifies Invoke-WebRequest Negotiated -Credential Can use HTTP with -AllowUnencryptedAuthentication" {
$params = @{
Uri = $httpBasicUri
Credential = $credential
AllowUnencryptedAuthentication = $true
}
$Response = Invoke-WebRequest @params
$result = $response.Content | ConvertFrom-Json

$result.Headers.Authorization | Should BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
}

# UseDefaultCredentials is only reliably testable on Windows
It "Verifies Invoke-WebRequest Negotiated -UseDefaultCredentials with '<AuthType>' over HTTPS" -Skip:$(!$IsWindows) -TestCases @(
@{AuthType = 'NTLM'}
@{AuthType = 'Negotiate'}
) {
param($AuthType)
$params = @{
Uri = Get-WebListenerUrl -Test 'Auth' -TestValue $AuthType -Https
UseDefaultCredentials = $true
SkipCertificateCheck = $true
}
$Response = Invoke-WebRequest @params
$result = $response.Content | ConvertFrom-Json

$result.Headers.Authorization | Should Match "^$AuthType "
}

# The error condition can at least be tested on all platforms.
It "Verifies Invoke-WebRequest Negotiated -UseDefaultCredentials Requires HTTPS" {
$params = @{
Uri = $httpUri
UseDefaultCredentials = $true
ErrorAction = 'Stop'
}
{ Invoke-WebRequest @params } | ShouldBeErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}

# UseDefaultCredentials is only reliably testable on Windows
It "Verifies Invoke-WebRequest Negotiated -UseDefaultCredentials with '<AuthType>' Can use HTTP with -AllowUnencryptedAuthentication" -Skip:$(!$IsWindows) -TestCases @(
@{AuthType = 'NTLM'}
@{AuthType = 'Negotiate'}
) {
param($AuthType)
$params = @{
Uri = Get-WebListenerUrl -Test 'Auth' -TestValue $AuthType
UseDefaultCredentials = $true
AllowUnencryptedAuthentication = $true
}
$Response = Invoke-WebRequest @params
$result = $response.Content | ConvertFrom-Json

$result.Headers.Authorization | Should Match "^$AuthType "
}
}

BeforeEach {
Expand Down Expand Up @@ -2233,6 +2312,8 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" {
$credential = [pscredential]::new("testuser",$token)
$httpUri = Get-WebListenerUrl -Test 'Get'
$httpsUri = Get-WebListenerUrl -Test 'Get' -Https
$httpBasicUri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic'
$httpsBasicUri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic' -Https
$testCases = @(
@{Authentication = "bearer"}
@{Authentication = "OAuth"}
Expand Down Expand Up @@ -2330,6 +2411,79 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" {

$result.Headers.Authorization | Should BeExactly "Bearer testpassword"
}

It "Verifies Invoke-RestMethod Negotiated -Credential over HTTPS" {
$params = @{
Uri = $httpsBasicUri
Credential = $credential
SkipCertificateCheck = $true
}
$result = Invoke-RestMethod @params

$result.Headers.Authorization | Should BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
}

It "Verifies Invoke-RestMethod Negotiated -Credential Requires HTTPS" {
$params = @{
Uri = $httpBasicUri
Credential = $credential
ErrorAction = 'Stop'
}
{ Invoke-RestMethod @params } | ShouldBeErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}

It "Verifies Invoke-RestMethod Negotiated -Credential Can use HTTP with -AllowUnencryptedAuthentication" {
$params = @{
Uri = $httpBasicUri
Credential = $credential
AllowUnencryptedAuthentication = $true
}
$result = Invoke-RestMethod @params

$result.Headers.Authorization | Should BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
}

# UseDefaultCredentials is only reliably testable on Windows
It "Verifies Invoke-RestMethod Negotiated -UseDefaultCredentials with '<AuthType>' over HTTPS" -Skip:$(!$IsWindows) -TestCases @(
@{AuthType = 'NTLM'}
@{AuthType = 'Negotiate'}
) {
param($AuthType)
$params = @{
Uri = Get-WebListenerUrl -Test 'Auth' -TestValue $AuthType -Https
UseDefaultCredentials = $true
SkipCertificateCheck = $true
}
$result = Invoke-RestMethod @params

$result.Headers.Authorization | Should Match "^$AuthType "
}

# The error condition can at least be tested on all platforms.
It "Verifies Invoke-RestMethod Negotiated -UseDefaultCredentials Requires HTTPS" {
$params = @{
Uri = $httpUri
UseDefaultCredentials = $true
ErrorAction = 'Stop'
}
{ Invoke-RestMethod @params } | ShouldBeErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}

# UseDefaultCredentials is only reliably testable on Windows
It "Verifies Invoke-RestMethod Negotiated -UseDefaultCredentials with '<AuthType>' Can use HTTP with -AllowUnencryptedAuthentication" -Skip:$(!$IsWindows) -TestCases @(
@{AuthType = 'NTLM'}
@{AuthType = 'Negotiate'}
) {
param($AuthType)
$params = @{
Uri = Get-WebListenerUrl -Test 'Auth' -TestValue $AuthType
UseDefaultCredentials = $true
AllowUnencryptedAuthentication = $true
}
$result = Invoke-RestMethod @params

$result.Headers.Authorization | Should Match "^$AuthType "
}
}

BeforeEach {
Expand Down
1 change: 1 addition & 0 deletions test/tools/Modules/WebListener/WebListener.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ function Get-WebListenerUrl {
param (
[switch]$Https,
[ValidateSet(
'Auth',
'Cert',
'Compression',
'Delay',
Expand Down
73 changes: 73 additions & 0 deletions test/tools/WebListener/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Primitives;
using mvc.Models;

namespace mvc.Controllers
{
public class AuthController : Controller
{
public JsonResult Basic()
{
StringValues authorization;
if (Request.Headers.TryGetValue("Authorization", out authorization))
{
var getController = new GetController();
getController.ControllerContext = this.ControllerContext;
return getController.Index();
}
else
{
Response.Headers.Add("WWW-Authenticate","Basic realm=\"WebListener\"");
Response.StatusCode = 401;
return Json("401 Unauthorized");
}
}

public JsonResult Negotiate()
{
StringValues authorization;
if (Request.Headers.TryGetValue("Authorization", out authorization))
{
var getController = new GetController();
getController.ControllerContext = this.ControllerContext;
return getController.Index();
}
else
{
Response.Headers.Add("WWW-Authenticate","Negotiate");
Response.StatusCode = 401;
return Json("401 Unauthorized");
}
}

public JsonResult Ntlm()
{
StringValues authorization;
if (Request.Headers.TryGetValue("Authorization", out authorization))
{
var getController = new GetController();
getController.ControllerContext = this.ControllerContext;
return getController.Index();
}
else
{
Response.Headers.Add("WWW-Authenticate","NTLM");
Response.StatusCode = 401;
return Json("401 Unauthorized");
}
}

public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
70 changes: 70 additions & 0 deletions test/tools/WebListener/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,76 @@ $Listener = Start-WebListener -HttpPort 8083 -HttpsPort 8084

Returns a static HTML page containing links and descriptions of the available tests in WebListener. This can be used as a default or general test where no specific test functionality or return data is required.

## /Auth/Basic/

Provides a mock Basic authentication challenge. If a basic authorization header is sent, then the same results as /Get/ are returned.

```powershell
$credential = Get-Credential
$uri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic' -Https
Invoke-RestMethod -Uri $uri -Credential $credential -SkipCertificateCheck
```

```json
{
"headers":{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0",
"Connection": "Keep-Alive",
"Authorization": "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk",
"Host": "localhost:8084"
},
"origin": "127.0.0.1",
"args": {},
"url": "https://localhost:8084/Auth/Basic"
}
```

## /Auth/Negotiate/

Provides a mock Negotiate authentication challenge. If a basic authorization header is sent, then the same results as /Get/ are returned.

```powershell
$uri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Negotiate' -Https
Invoke-RestMethod -Uri $uri -UseDefaultCredential -SkipCertificateCheck
```

```json
{
"headers":{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0",
"Connection": "Keep-Alive",
"Authorization": "Negotiate jjaguasgtisi7tiqkagasjjajvs",
"Host": "localhost:8084"
},
"origin": "127.0.0.1",
"args": {},
"url": "https://localhost:8084/Auth/Negotiate"
}
```

## /Auth/NTLM/

Provides a mock NTLM authentication challenge. If a basic authorization header is sent, then the same results as /Get/ are returned.

```powershell
$uri = Get-WebListenerUrl -Test 'Auth' -TestValue 'NTLM' -Https
Invoke-RestMethod -Uri $uri -UseDefaultCredential -SkipCertificateCheck
```

```json
{
"headers":{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0",
"Connection": "Keep-Alive",
"Authorization": "NTLM jjaguasgtisi7tiqkagasjjajvs",
"Host": "localhost:8084"
},
"origin": "127.0.0.1",
"args": {},
"url": "https://localhost:8084/Auth/NTLM"
}
```

## /Cert/

Returns a JSON object containing the details of the Client Certificate if one is provided in the request.
Expand Down
3 changes: 3 additions & 0 deletions test/tools/WebListener/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<h1>Available Tests</h1>
<ul>
<li><a href="/">/</a> - This page</li>
<li><a href="/Auth/Basic/">/Auth/Basic/</a> - Basic Authentication</li>
<li><a href="/Auth/Negotiate/">/Auth/Negotiate/</a> - Negotiate Authentication</li>
<li><a href="/Auth/NTLM/">/Auth/NTLM/</a> - NTLM Authentication</li>
<li><a href="/Cert/">/Cert/</a> - Client Certificate Details</li>
<li><a href="/Compression/Deflate/">/Compression/Deflate/</a> - Returns deflate compressed response</li>
<li><a href="/Compression/GZip/">/Compression/Gzip/</a> - Returns gzip compressed response</li>
Expand Down