Skip to content

Conversation

@dantraMSFT
Copy link
Contributor

PR Summary

Fix #6779 regression.

The change to disallow Basic Auth over HTTP was not checking the scheme for the -Uri parameter. The result is Basic Auth connections over HTTPS via the -Uri parameter were disallowed.

The change adds the check for the scheme as well as useSSL.

PR Checklist

@dantraMSFT dantraMSFT requested review from SteveL-MSFT, iSazonov and markekraus and removed request for PaulHigin and mirichmo May 17, 2018 19:52
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can get rid of the isHttps variable and just use:

connectionUri.Scheme != Uri.UriSchemeHttps

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT: does connectionUri guarantee that it normalizes the case of the Scheme property?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe @SteveL-MSFT means:

if (connectionInfo.AuthenticationMechanism == AuthenticationMechanism.Basic && !isSSLSpecified && StringComparer.OrdinalIgnoreCase.Compare("https", connectionUri.Scheme) != 0) 

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT is correct. Uri.Scheme is always normalized to lowercase (see the notes on the property value here https://docs.microsoft.com/en-us/dotnet/api/system.uri.scheme?view=netcore-2.1)

Line 1531 is unneeded and on line 1533 && !isHttps can be changed to && connectionUri.Scheme != Uri.UriSchemeHttps

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the HelpersRemoting.psm1 module, I believe you can get real creds to validate it works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't want to establish a connection; I'm verifying that Basic Auth verification doesn't reject the request.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a separate test that validates it works?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT: No, we don't have any automated remoting tests for PSRP at this point.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe @SteveL-MSFT means:

if (connectionInfo.AuthenticationMechanism == AuthenticationMechanism.Basic && !isSSLSpecified && StringComparer.OrdinalIgnoreCase.Compare("https", connectionUri.Scheme) != 0) 

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment in Line 32 says "not with a PSSessionOpenFailed". Seems the comment should be corrected (or the test is wrong?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@dantraMSFT
Copy link
Contributor Author

dantraMSFT commented May 18, 2018

The test failure appears to be a variation of microsoft/omi#502 that is not covered by the fix.

This PR cannot be merged until the libmi issue is fixed since the new test hits this path. It appears to hit sporadically in release builds and consistently in debug builds.

@dantraMSFT dantraMSFT added the Blocked blocked on something external to this repo label May 18, 2018
@vors
Copy link
Collaborator

vors commented Jun 17, 2018

Can we at least merge it without tests, since the "Blocker" status is applicable to the tests flakiness as far as I understand?

As @kai-h pointed out in #7054

As I see it (which may or may not be correct), one of the primary use cases for PowerShell on non-Windows systems is for administering remote Windows systems, including Azure and Office 365.

Inability of connecting to office 365 remoting endpoints out of the box is a pretty concerning regression and impact the number of useful scenarios for pwsh.

@echobb8
Copy link

echobb8 commented Jun 20, 2018

What's the status on this? I need to connect to Office 365 from my Mac, but it fails: "New-PSSession : Basic authentication is not supported over HTTP on Unix."

Is there a workaround?

@vors
Copy link
Collaborator

vors commented Jun 20, 2018

Is there a workaround?

Use PS version before 6.1.0-Preview3, i.e. 6.1.0-Preview2
https://github.com/PowerShell/PowerShell/releases

@dantraMSFT
Copy link
Contributor Author

I will see if I can get the PR through today with the failing test marked as pending.

@adityapatwardhan
Copy link
Member

@dantraMSFT Can you have a look, the PR is pulling 91 commits with 498 files.

@dantraMSFT dantraMSFT removed the Blocked blocked on something external to this repo label Jun 20, 2018
@dantraMSFT
Copy link
Contributor Author

I removed the blocking label and disabled the test that hits the libmi issue (microsoft/omi#502 )

@dantraMSFT
Copy link
Contributor Author

@adityapatwardhan Fixed

$err.Exception.ErrorCode | Should -Be 801
}

# Marked as pending due tohttps://github.com/Microsoft/omi/issues/502
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: space between to and https

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

# use a Uri that specifies HTTPS to test Basic Auth logic.
# NOTE: The connection is expected to fail but not with a ConnectFailed exception
$uri = "https://localhost"
New-PSSession -Uri $uri -Credential $credential -Authentication Basic -ErrorVariable err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use the pattern below?

{ New-PSSession -Uri $uri -Credential $credential -Authentication Basic -ErrorVariable err } | Should -Throw -ErrorId '1,PSSessionOpenFailed' -ExceptionType 'System.Management.Automation.Remoting.PSRemotingTransportException'
$err.Exception.HResult | Should -Be -2146233087

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, when -ErrorVariable is used, pester doesn't have an exception to catch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cannot be done as when err is set no exception is thrown.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a negative test case where you need to do more validation of the exception, you should use the pattern in our test guidance doc with -PassThru: https://github.com/PowerShell/PowerShell/blob/master/docs/testing-guidelines/WritingPesterTests.md#writing-pester-tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT: new-pssession doesn't throw, it writes to the error stream.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT: do you have any additional feedback?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should follow the convention for now to use -ErrorAction Stop and then use Pester's Should -ThrowErrorId -PassThru to do additional validation for consistency until we have capability to validate non-terminating errors

# use a Uri that specifies HTTPS to test Basic Auth logic.
# NOTE: The connection is expected to fail but not with a ConnectFailed exception
$uri = "https://localhost"
New-PSSession -Uri $uri -Credential $credential -Authentication Basic -ErrorVariable err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a negative test case where you need to do more validation of the exception, you should use the pattern in our test guidance doc with -PassThru: https://github.com/PowerShell/PowerShell/blob/master/docs/testing-guidelines/WritingPesterTests.md#writing-pester-tests

@kai-h
Copy link

kai-h commented Jun 25, 2018

Can we please explicitly have a test to connect to Office 365, or even Azure.
We just need to test that the connection attempt succeeds, it doesn't need to be given valid credentials as long as it doesn't throw a ConnectFailed error.
The remote session can be accessed via the following Connection URI for Office 365:

-ConnectionUri https://outlook.office365.com/powershell-liveid/

or, for your code snippet:

$uri = "https://outlook.office365.com/powershell-liveid/"

@iSazonov
Copy link
Collaborator

Can we please explicitly have a test to connect to Office 365

All tests using external resources is unstable. 😕 and daily/night builds frequently failed.

Perhaps for the cases we could have optional test set in separate job.

@kai-h
Copy link

kai-h commented Jun 26, 2018

I suppose that the main thing is that PowerShell actually attempts to connect to a remote session, be it locally or on an actual remote system.
It would be wonderful however if the testing was able to qualify that it will connect successfully to Office 365, Azure or some other Microsoft endpoint that customers will be using PowerShell to manage.

@dantraMSFT
Copy link
Contributor Author

dantraMSFT commented Jun 26, 2018

@kai-h I will be creating tests that verify we can successfully connect to o365 but it won't be in the nightly build. One reason is mentioned above but the primary one, for now, is I don't want to expose o365 account information; even if only for testing purposes.

The tests will be checked in but will likely be conditioned on a custom JSON file that is not present in the public CI builds.

That's my working plan for now. If I come up with a cleaner solution, I'll post to this thread.

@kai-h
Copy link

kai-h commented Jun 26, 2018

@dantraMSFT - Thanks, I understand given the reasons above.
In my testing, I've found that it's not necessary to supply valid credentials in testing if PowerShell can connect to Office 365. Even if you're supplying invalid credentials (e.g. user@example.com with password Password123), if PowerShell can at least initiate the connection attempt to Office 365, even if Office365 says invalid username or password, this shows that PowerShell can connect, however it can't test if any remote commands can be executed.

New-PSSession -Uri $uri -Credential $credential -Authentication Basic -ErrorVariable err
$err.Exception | Should -BeOfType [System.Management.Automation.Remoting.PSRemotingTransportException]
$err.FullyQualifiedErrorId | Should -Be '1,PSSessionOpenFailed'
$err.Exception.HResult | Should -Be -2146233087
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: prefer the hex version particularly with a HResult: 0x80131501

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@adityapatwardhan
Copy link
Member

@dantraMSFT Can you respond to @SteveL-MSFT comment.

@dantraMSFT
Copy link
Contributor Author

@adityapatwardhan Addressed Steve's comment.

# use a Uri that specifies HTTPS to test Basic Auth logic.
# NOTE: The connection is expected to fail but not with a ConnectFailed exception
$uri = "https://localhost"
New-PSSession -Uri $uri -Credential $credential -Authentication Basic -ErrorVariable err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should follow the convention for now to use -ErrorAction Stop and then use Pester's Should -ThrowErrorId -PassThru to do additional validation for consistency until we have capability to validate non-terminating errors

@dantraMSFT
Copy link
Contributor Author

@SteveL-MSFT Hmm, that's not how I interpreted the guidelines.
That said, forcing a throw isn't testing the cmdlet the way it's normally used. Additionally, using the guideline prevents testing non-terminating errors.

@SteveL-MSFT
Copy link
Member

@dantraMSFT let's defer this to the other discussion on validating terminating vs non-terminating. I'll approve this PR as this isn't blocking.

@adityapatwardhan adityapatwardhan merged commit 5e8b23e into PowerShell:master Jun 27, 2018
@dantraMSFT dantraMSFT deleted the dantra/issue6779 branch August 22, 2018 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Explicitly disallow Basic Auth over HTTP with PSRP on Linux

9 participants