jborean93 / omi

Open Management Infrastructure
Other
108 stars 13 forks source link

Any way to leverage this from PowerShell SDK? #36

Closed jeff-simeon closed 3 years ago

jeff-simeon commented 3 years ago
SUMMARY

PowerShell Core has abandoned support of OMI and PowerShell SDK can't be used for Exchange Online even with the symbolic link created to OpenSSL.

The issue is documented here https://github.com/PowerShell/PowerShell/issues/10600

with a minimally reproducible example here: https://github.com/JeffN825/PowerShellWSManBug

Is it possible to make this work using your fork?

Thanks! Great work on this project.

OS / ENVIRONMENT

Mac OS Big Sur

jborean93 commented 3 years ago

It should be possible, you essentially need to ensure the libmi and libpsrpclient in the pwsh dir are replaced. The Install-WSMan cmdlet distributed in PSWSMan does this for you but there's nothing stopping you from doing it yourself. You could also add an ImportResolver as mentioned in https://github.com/jborean93/omi/issues/24#issuecomment-798995921 to ensure libpsrpclient loads the so/dylib distributed by PSWSMan instead of replacing what PowerShell ships with.

jeff-simeon commented 3 years ago

Thanks. I tried this and didn't make it too far.

I added this to my csproj:

  <ItemGroup>
    <Content Include="PSWSMan/2.2.1/lib/macOS-3/*.*" CopyToOutputDirectory="Always" Link="%(Filename)%(Extension)" />
  </ItemGroup>

which gets the dylib's copied to my bin directory

Added this to my entry point

System.Runtime.InteropServices.NativeLibrary.SetDllImportResolver(typeof(PSObject).Assembly, ImportResolver);

and validated my resolver gets called:

public static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
        {   
            if (libraryName == "libpsrpclient" || libraryName == "libmi") {
                libraryName = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), $"{libraryName}.dylib");
            }      

            return NativeLibrary.Load(libraryName, assembly, searchPath);
        }

Unfortunately, this blows up at

            return NativeLibrary.Load(libraryName, assembly, searchPath);

with the exception

An exception of type 'System.DllNotFoundException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Unable to load shared library '/Users/jeff/dev/PowerShellWSManBug/bin/Debug/net5.0/libpsrpclient.dylib' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: dlopen(/Users/jeff/dev/PowerShellWSManBug/bin/Debug/net5.0/libpsrpclient.dylib, 1): Library not loaded: @loader_path/libssl.3.dylib
  Referenced from: /Users/jeff/dev/PowerShellWSManBug/bin/Debug/net5.0/libmi.dylib
  Reason: image not found'
   at System.Runtime.InteropServices.NativeLibrary.LoadByName(String libraryName, QCallAssembly callingAssembly, Boolean hasDllImportSearchPathFlag, UInt32 dllImportSearchPathFlag, Boolean throwOnError)

the file is, of course, there

jborean93 commented 3 years ago

The number in the distribution refers to the OpenSSL version it is linked against. Because each OpenSSL major version is not ABI (and sometimes API) compatible the version you use must reflect what OpenSSL version you have available. You most likely have OpenSSL 1.1.x installed with brew (3 is still in the release candidate phase) so you should include macOS-1.1.

MacOS also makes things a bit more difficult as it's trying to find libssl and libcrypto relative to libmi.dylib (@loader_path/libssl.1.1.dylib). The Install-WSMan cmdlet will create the 2 symlinks for these files in the same dir as libmi.dylib to point to the actual libssl and libcrypto either provided by brew or port. You will either:

# Must be done for libssl and libcrypto. The target path is dependent on your host in question
# For brew see 'echo "$( brew --prefix openssl )/lib"'
# For port see 'port contents openssl'

install_name_tool -change \
    @loader_path/libssl.1.1.dylib \
    /usr/local/opt/openssl@1.1/lib/libssl.dylib \
    libmi.dylib

# You can verify the paths with 'otool -L libmi.dylib'

It's a mess unfortunately but unfortunately I don't know of a nice way to achieve all this that is universal across macOS distributions. The proper solution is to adjust the code so it uses Apple's native TLS library, Network, but that's a lot more than I can chew at the moment. I don't even think it's possible to use the BIO memory like setup that OpenSSL offers which makes using that even harder for this library.

if (libraryName == "libpsrpclient" || libraryName == "libmi") {

As an FYI you only need to adjust libpsrpclient for the .NET resolver. PowerShell imports libpsrpclient which in turn imports libmi through the dylib loading process completely outside of .NET.

Edit: Changed install_name_tool argument order.

jeff-simeon commented 3 years ago

Thanks!

I must have done something wrong...I install openssl via MacPorts (it's not available on Brew anymore that I can see).

I grabbed the path of my install

Jeffs-MBP ~ % port contents openssl | grep dylib  
  /opt/local/lib/engines-1.1/capi.dylib
  /opt/local/lib/engines-1.1/padlock.dylib
  /opt/local/lib/libcrypto.1.1.dylib
  /opt/local/lib/libcrypto.dylib
  /opt/local/lib/libssl.1.1.dylib
  /opt/local/lib/libssl.dylib

I switched to 1.1

  <ItemGroup>
    <Content Include="PSWSMan/2.2.1/lib/macOS-1.1/*.*" CopyToOutputDirectory="Always" Link="%(Filename)%(Extension)" />
  </ItemGroup>

and I ran this command from my bin/Debug/net5.0 directory

net5.0 % sudo install_name_tool -change \
    libmi.dylib \
    @loader_path/libssl.1.1.dylib \
    /opt/local/lib/libssl.1.1.dylib

But I still get the error

An exception of type 'System.DllNotFoundException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Unable to load shared library '/Users/jeff/dev/PowerShellWSManBug/bin/Debug/net5.0/libpsrpclient.dylib' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: dlopen(/Users/jeff/dev/PowerShellWSManBug/bin/Debug/net5.0/libpsrpclient.dylib, 1): Library not loaded: @loader_path/libssl.1.1.dylib
jborean93 commented 3 years ago

Hmm based on the error it is still trying to find libssl using @loader_path/libssl.1.1.dylib which shouldn't be the case after running install_name_tool. Can you run otool -L libpsrpclient.dylib and otool -L libmi.dylib and share those results? You shouldn't have to run install_name_tool as root as well. It just edits the ELF headers of the dylib specified so as long as you have rights to the file you are good to go.

jborean93 commented 3 years ago

Ah sorry I gave you the wrong order of arguments it should be

install_name_tool -change \
    @loader_path/libssl.1.1.dylib \
    /opt/local/lib/libssl.1.1.dylib \
    libmi.dylib

The first argument is what to change, the 2nd is what to change it to, and the 3rd is the library to change.

jeff-simeon commented 3 years ago

Progress!

An unhandled exception of type 'System.AggregateException' occurred in System.Private.CoreLib.dll: 'One or more errors occurred.'
 Inner exceptions found, see $exception in variables window for more details.
 Innermost exception     System.Management.Automation.ActionPreferenceStopException : The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: [outlook.office365.com] Connecting to remote server outlook.office365.com failed with the following error message : error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed For more information, see the about_Remote_Troubleshooting Help topic.

Any idea why certificate validation would be failing? Needless to say, I checked in a regular PowerShell command prompt and didn't get a failure.

jborean93 commented 3 years ago

Sweet seems like the library is actually being loaded and used so we moving forward. I'm not sure why the certificate is not being verified as the cert MS is using for that site should be valid. I have a few questions:

echo "q" | /opt/local/bin/openssl s_client -connect outlook.office365.com:443 -showcerts
jeff-simeon commented 3 years ago

CONNECTED(00000005) depth=1 C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1 verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = outlook.com verify return:1

Certificate chain 0 s:C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = outlook.com i:C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1 -----BEGIN CERTIFICATE----- MIIItTCCB52gAwIBAgIQC6A+Zp+Sy/+UDY1WT6qi9DANBgkqhkiG9w0BAQsFADBL MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSUwIwYDVQQDExxE aWdpQ2VydCBDbG91ZCBTZXJ2aWNlcyBDQS0xMB4XDTIwMDcwMjAwMDAwMFoXDTIy MDcwMjEyMDAwMFowajELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv bjEUMBIGA1UEAxMLb3V0bG9vay5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDTnR6GEhZkW1rOvA/14sMiYXPJUY482u9Jw0dfdr+cgz60G5vcV9ZK 0XzZEKoFlT9KicbZFuweYFkmWn5VRL4jCwxH2B5qZvPCqXECS4majWqKei2h3XX4 errIJMUTfovvU+tw69eYUC0JMDDRIC1YZFnqTjYNjX+1lqaDuze7raIKZ6RYdxya IablUlcuc5hviHLi0tGPffFWOgQWYGi58eQnwkDVKfx5WLB0nZtwN2eZ5HAbMOgZ ravHUUtX1kn/kvukkbURl01oe3g75vSUt9TXCLfvaZlWjDQCwmulLFu68AgOt5Dp q/yiQm6ynJGmqP0cFwuKkxwQXiznLO7ZAgMBAAGjggV0MIIFcDAfBgNVHSMEGDAW gBTdUdCiMXOpc66PtAF+XYxXy5/w9zAdBgNVHQ4EFgQU8TJQ/7+cOY8E8bK7QjkF tOhDTw8wggIQBgNVHREEggIHMIICA4IWKi5pbnRlcm5hbC5vdXRsb29rLmNvbYIN Ki5vdXRsb29rLmNvbYILb3V0bG9vay5jb22CDW9mZmljZTM2NS5jb22CDyoub2Zm aWNlMzY1LmNvbYIXKi5vdXRsb29rLm9mZmljZTM2NS5jb22CDCoub2ZmaWNlLmNv bYISb3V0bG9vay5vZmZpY2UuY29tghRzdWJzdHJhdGUub2ZmaWNlLmNvbYIbYXR0 YWNobWVudC5vdXRsb29rLmxpdmUubmV0gh1hdHRhY2htZW50Lm91dGxvb2sub2Zm aWNlLm5ldIIgYXR0YWNobWVudC5vdXRsb29rLm9mZmljZXBwZS5uZXSCFmF0dGFj aG1lbnRzLm9mZmljZS5uZXSCFiouY2xvLmZvb3RwcmludGRucy5jb22CFioubnJi LmZvb3RwcmludGRucy5jb22CHWNjcy5sb2dpbi5taWNyb3NvZnRvbmxpbmUuY29t giFjY3Mtc2RmLmxvZ2luLm1pY3Jvc29mdG9ubGluZS5jb22CGHN1YnN0cmF0ZS1z ZGYub2ZmaWNlLmNvbYIaYXR0YWNobWVudHMtc2RmLm9mZmljZS5uZXSCCioubGl2 ZS5jb22CFm1haWwuc2VydmljZXMubGl2ZS5jb22CC2hvdG1haWwuY29tgg0qLmhv dG1haWwuY29tMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI KwYBBQUHAwIwgY0GA1UdHwSBhTCBgjA/oD2gO4Y5aHR0cDovL2NybDMuZGlnaWNl cnQuY29tL0RpZ2lDZXJ0Q2xvdWRTZXJ2aWNlc0NBLTEtZzEuY3JsMD+gPaA7hjlo dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRDbG91ZFNlcnZpY2VzQ0Et MS1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYc aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUH AQEEcDBuMCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcHguZGlnaWNlcnQuY29tMEUG CCsGAQUFBzAChjlodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRD bG91ZFNlcnZpY2VzQ0EtMS5jcnQwDAYDVR0TAQH/BAIwADCCAX8GCisGAQQB1nkC BAIEggFvBIIBawFpAHYAKXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4QA AAFzDca90AAABAMARzBFAiEA/FdP27rYQAgcTBMUTQQH4ZQk2+QJe+YAi/eGSTi/ V8sCIFhLbAp9JbBWwDQ/leygogpuPBysuIUecJQVyRttqkEiAHcAIkVFB1lVJFaW P6Ev8fdthuAjJmOtwEt/XcaDXG7iDwIAAAFzDca+AwAABAMASDBGAiEA8yetDlcF lyhGNmXz2zGdqlUiseIkvC/TQKOIM4JLTf4CIQCFTH0sdcbgMZusClSwD++RPQHi iyADi5kOgkUHX454dAB2AEHIyrHfIkZKEMahOglCh15OMYsbA+vrS8do8JBilgb2 AAABcw3GvaEAAAQDAEcwRQIgY4uUeGAm3x9HfFqDcGPUkG+mnHtpxAh+/M2shYUN LTICIQCcmZeTNIjlJbJQMoL4U/6rMBMNSm37ez43SVBk8Q35CTANBgkqhkiG9w0B AQsFAAOCAQEAzX8uVEEgmIfMgGZs4qwHv1BtAWvHC/r2juagCquWS93NPq3/LRk3 SfEj8BnL8eMwnxP8+8sH3dyFj/2gvbFD3e14LBr2ZUy6y/O/Lnn5wxBEdJqimwfu JTSTbgQj9BTgXmBAIEXeaLtH8/UcW2Lqxe6iwNdiUiSpzKmjWoZwYK1y+YiJQAmW w+g4WFnRj49O0RlQoVss+/ffAcYEH/HKGNZB3J7Q9t903/SdpSt3sI2FUeOXCgMX 4TSTdgmAEbRsXK4BEbiJyd7PZsL3/cuwzCNWk5xfcUlWW/ZAwA8KV/U6SL+4TEnN nwpV2m3OUov9+4a3ST4aWuBpvV9msXoJzw== -----END CERTIFICATE----- 1 s:C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1 i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA -----BEGIN CERTIFICATE----- MIIE5jCCA86gAwIBAgIQDxcaSMbyI4CSGM0u1t3A6DANBgkqhkiG9w0BAQsFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD QTAeFw0yMDA5MjUwMDAwMDBaFw0zMDA5MjQyMzU5NTlaMEsxCzAJBgNVBAYTAlVT MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJTAjBgNVBAMTHERpZ2lDZXJ0IENsb3Vk IFNlcnZpY2VzIENBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDR rfaHFHlUJ1fHLwVoPJs8zWfsRRAshPKkR8TZU0JFCbvk/jPB17xGL9GL5re1Z3h8 anC+/bjltlTPTF6suCJ0c1UpCHPIZPfQlQkOeYNQv1/11MybQmGOgAS5QarOThKZ m6zWxb5bAnO1FqSrcWLUmOpAOYWm9rsv6OeHwov2nDLN7Pg+v4nndCOCS9rqv3Om JTz9v6nlaP/4MKJgxzsuo/PFfzs7/Q8xoXx0D9C/FMS9aPGl52un35sAfkYlTubo E/P2BsfUbwsnIEJdYbw/YNJ8lnLJfLCL//lIBVME+iKvt81RXW3dkHQD8DNP9MfA PlZGR69zIIvcej6j8l3/AgMBAAGjggGuMIIBqjAdBgNVHQ4EFgQU3VHQojFzqXOu j7QBfl2MV8uf8PcwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYD VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNV HRMBAf8ECDAGAQH/AgEAMHYGCCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0 cDovL29jc3AuZGlnaWNlcnQuY29tMEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0 cy5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3J0MHsGA1UdHwR0 MHIwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2Jh bFJvb3RDQS5jcmwwN6A1oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdp Q2VydEdsb2JhbFJvb3RDQS5jcmwwMAYDVR0gBCkwJzAHBgVngQwBATAIBgZngQwB AgEwCAYGZ4EMAQICMAgGBmeBDAECAzANBgkqhkiG9w0BAQsFAAOCAQEANJE52TD/ zFvmYQGp0P3ntVzclyqsN7Aga/s2SmhGoow32hcBWc6OVgQILYjXndBwRdTn6/97 nb+5a0sEfMoc7mto2ALmLim+XgZ6bg2nQX1A2lWYUoFou0YDHzGsKUNcLQOjoJU4 t9UMxv6+Je7RB77+j3mVmsNxBF13Q+LEHWiY+IJSazVqv7w73izbAFo6cF9sK0hp qdmSKdB/MNfnT9YF4/WYlyCwFhpaK3mPuU2XiOzGswPhMMRwgawnk4XTNemtHPSq fP/JzQHsefL75Tx5c8tHJAcp3C/QD+JcUUHocUPuW62x79wO9pNl5N5U4jIVFa4k x6pNQytYvwMPeg== -----END CERTIFICATE-----

Server certificate subject=C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = outlook.com

issuer=C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1


No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA Server Temp Key: ECDH, P-384, 384 bits

SSL handshake has read 4293 bytes and written 481 bytes Verification error: unable to get local issuer certificate

New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 8116FFAE39C9C852D260E258E9296216B2DFC84DF303672FEBBAD42B862BB723 Session-ID-ctx: Master-Key: 38B444EE9B97ABD881B57F84CE514AD51B00656220E3C6EF5FC27A1DCDC71006F3AC9ECFB944C06A2BC0E912193A0E82 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 36000 (seconds) TLS session ticket: 0000 - 00 00 00 00 9f d2 90 4b-75 94 47 4d ae 48 99 c6 .......Ku.GM.H.. 0010 - 73 21 62 27 5f 7c 82 f3-c0 37 22 45 98 6d ea 89 s!b'_|...7"E.m.. 0020 - 0a 28 c3 56 65 f7 15 36-f1 1d a1 f7 27 ea 5a a9 .(.Ve..6....'.Z. 0030 - ad 13 3e 68 07 19 9a 05-8d df 99 2a 30 26 42 61 ..>h.......*0&Ba 0040 - 59 46 18 7f ae 14 15 c5-f8 25 05 d6 48 cb 46 90 YF.......%..H.F. 0050 - 46 46 7c 77 82 9e 6c 8a-e2 e1 5d 53 ef 0f 17 ab FF|w..l...]S.... 0060 - e4 39 7d f9 4b 17 73 83-0b 24 49 b1 cc 89 49 f3 .9}.K.s..$I...I. 0070 - 97 8b 00 d0 32 85 d7 e5-15 34 6b 7d d1 c4 19 b2 ....2....4k}.... 0080 - fc 30 9e d5 20 20 d9 7d-3c 37 86 40 d3 06 20 ee .0.. .}<7.@.. . 0090 - 30 05 99 aa 31 3b d0 c3-4f b7 c5 53 aa 09 f1 df 0...1;..O..S.... 00a0 - 45 b0 20 2f 65 f7 b5 80-2d 63 0f db 68 fb cf 5d E. /e...-c..h..] 00b0 - 62 b9 94 76 30 69 0b 7a-17 9b dc bc c5 9e 12 c1 b..v0i.z........ 00c0 - e2 14 86 52 30 e2 43 56-68 d7 45 f2 0d f8 c0 2d ...R0.CVh.E....- 00d0 - aa c6 9e a3 eb b0 57 e2-10 f8 a5 f8 5a 92 60 d3 ......W.....Z.`. 00e0 - 3a 1e 20 34 af 8a e3 59-26 dd 0a 77 89 3e 78 24 :. 4...Y&..w.>x$ 00f0 - 1a b3 8d b8 33 68 05 e5-0a 2b 46 bf 73 f8 9d a4 ....3h...+F.s... 0100 - 9c cf 2f 3f ../?

Start Time: 1630005415
Timeout   : 7200 (sec)
Verify return code: 20 (unable to get local issuer certificate)
Extended master secret: yes

- The default openssl on the system produces slightly different output:

Jeffs-MBP bin % echo "q" | /opt/local/bin/openssl s_client -connect outlook.office365.com:443 -showcerts

CONNECTED(00000005) depth=1 C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1 verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = outlook.com verify return:1

Certificate chain 0 s:C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = outlook.com i:C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1 -----BEGIN CERTIFICATE----- MIIIsjCCB5qgAwIBAgIQB6RME27Flid4nOOXBveW+DANBgkqhkiG9w0BAQsFADBL MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSUwIwYDVQQDExxE aWdpQ2VydCBDbG91ZCBTZXJ2aWNlcyBDQS0xMB4XDTIwMDcwMjAwMDAwMFoXDTIy MDcwMjEyMDAwMFowajELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv bjEUMBIGA1UEAxMLb3V0bG9vay5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDX/+qGqUnFtATq2hd0y4akGwnBCjm4itz6lDuDAnH2mCSXt1MOCPTD jWVKSZGsb8u4/yLOg+dgh5KGCt05EOrwUHYYFb8uv940ay4FRD/WrSWXcKzgBQyL 5M5H0A95SLPoMsKsnkkg50WnHXMModev1ejy7ixeLHPiurGDqiyUeZ/HVEOIqbD4 uoadynPNO5Os/fhnYKbjbFVwjwA049tGHqMZkYLRLkEAnaA5hcaz3egLwevgQLBV rEm705tgWdfhxXiSDweDXGUg9vUw8yFIUEFqHqF26gkWnOuyCcpqkfTDG4SuXfVb 9zyBnXv+rJ1sBvFAWl93+rOBdbaenfx3AgMBAAGjggVxMIIFbTAfBgNVHSMEGDAW gBTdUdCiMXOpc66PtAF+XYxXy5/w9zAdBgNVHQ4EFgQUaLjr67/LvSUfHM+5mH3K pZ+N+eswggIQBgNVHREEggIHMIICA4IWKi5pbnRlcm5hbC5vdXRsb29rLmNvbYIN Ki5vdXRsb29rLmNvbYILb3V0bG9vay5jb22CDW9mZmljZTM2NS5jb22CDyoub2Zm aWNlMzY1LmNvbYIXKi5vdXRsb29rLm9mZmljZTM2NS5jb22CDCoub2ZmaWNlLmNv bYISb3V0bG9vay5vZmZpY2UuY29tghRzdWJzdHJhdGUub2ZmaWNlLmNvbYIbYXR0 YWNobWVudC5vdXRsb29rLmxpdmUubmV0gh1hdHRhY2htZW50Lm91dGxvb2sub2Zm aWNlLm5ldIIgYXR0YWNobWVudC5vdXRsb29rLm9mZmljZXBwZS5uZXSCFmF0dGFj aG1lbnRzLm9mZmljZS5uZXSCFiouY2xvLmZvb3RwcmludGRucy5jb22CFioubnJi LmZvb3RwcmludGRucy5jb22CHWNjcy5sb2dpbi5taWNyb3NvZnRvbmxpbmUuY29t giFjY3Mtc2RmLmxvZ2luLm1pY3Jvc29mdG9ubGluZS5jb22CGHN1YnN0cmF0ZS1z ZGYub2ZmaWNlLmNvbYIaYXR0YWNobWVudHMtc2RmLm9mZmljZS5uZXSCCioubGl2 ZS5jb22CFm1haWwuc2VydmljZXMubGl2ZS5jb22CC2hvdG1haWwuY29tgg0qLmhv dG1haWwuY29tMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI KwYBBQUHAwIwgY0GA1UdHwSBhTCBgjA/oD2gO4Y5aHR0cDovL2NybDMuZGlnaWNl cnQuY29tL0RpZ2lDZXJ0Q2xvdWRTZXJ2aWNlc0NBLTEtZzEuY3JsMD+gPaA7hjlo dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRDbG91ZFNlcnZpY2VzQ0Et MS1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYc aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUH AQEEcDBuMCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcHguZGlnaWNlcnQuY29tMEUG CCsGAQUFBzAChjlodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRD bG91ZFNlcnZpY2VzQ0EtMS5jcnQwDAYDVR0TAQH/BAIwADCCAXwGCisGAQQB1nkC BAIEggFsBIIBaAFmAHUAKXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4QA AAFzDcbXOQAABAMARjBEAiAodSTv6G64x+ajPkEyZSMsSPkAZ255JCjlhACQUdQx hAIgJnGDNgJl7ttHp4svvPPVfx39glm9Y4XHhOpy3YK4TUoAdgAiRUUHWVUkVpY/ oS/x922G4CMmY63AS39dxoNcbuIPAgAAAXMNxtdqAAAEAwBHMEUCIQDhWjuzRN44 mQ0HEGYorSXCt4TaO50iwKZV4WC0jl7CXAIgPF+hYYdzryesWHomb8k3xZ/v8krA DCapIhXkY9+/wjAAdQBRo7D1/QF5nFZtuDd4jwykeswbJ8v3nohCmg3+1IsF5QAA AXMNxte2AAAEAwBGMEQCIDB7hobhwdpdf3Hcl3umJyEkNGEsSi9dalNFS3FJCAi2 AiAYqoEAuEPhQTOxUNvdRx0XrwrBPe9Bavuxhw2mVincmDANBgkqhkiG9w0BAQsF AAOCAQEALcl7c5NDe31FLd//S2R55QLowT1hsbERD1HNsgNVgPMZBPLEvjVEk/fd QUZ4zjAZhjyihX+DZiSH+5lB5E9QABLGGYxwSVTtzQN/vM2nmSmF24HtUOcIzIm1 UoOqpSPVEnTbik8FvOWfUAfpaxdORQel4PEoNrTAHYZyrxmMR/IupEtW+u3oRvJW pXfUYPMd3/BoycSjIjTRw07xeW9BSENErf/zXcfpzOu/ALHu+j70QALB2fa+Hv0+ PD5gDsiFSZKo9OjjQK8vQVxrse8QnSC4tV3XxHY0974AubB+kQF0i5i7gtfh+qer QvvNpxF/FcuWUo/Emduxf8s97O2qSw== -----END CERTIFICATE----- 1 s:C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1 i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA -----BEGIN CERTIFICATE----- MIIE5jCCA86gAwIBAgIQDxcaSMbyI4CSGM0u1t3A6DANBgkqhkiG9w0BAQsFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD QTAeFw0yMDA5MjUwMDAwMDBaFw0zMDA5MjQyMzU5NTlaMEsxCzAJBgNVBAYTAlVT MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJTAjBgNVBAMTHERpZ2lDZXJ0IENsb3Vk IFNlcnZpY2VzIENBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDR rfaHFHlUJ1fHLwVoPJs8zWfsRRAshPKkR8TZU0JFCbvk/jPB17xGL9GL5re1Z3h8 anC+/bjltlTPTF6suCJ0c1UpCHPIZPfQlQkOeYNQv1/11MybQmGOgAS5QarOThKZ m6zWxb5bAnO1FqSrcWLUmOpAOYWm9rsv6OeHwov2nDLN7Pg+v4nndCOCS9rqv3Om JTz9v6nlaP/4MKJgxzsuo/PFfzs7/Q8xoXx0D9C/FMS9aPGl52un35sAfkYlTubo E/P2BsfUbwsnIEJdYbw/YNJ8lnLJfLCL//lIBVME+iKvt81RXW3dkHQD8DNP9MfA PlZGR69zIIvcej6j8l3/AgMBAAGjggGuMIIBqjAdBgNVHQ4EFgQU3VHQojFzqXOu j7QBfl2MV8uf8PcwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYD VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNV HRMBAf8ECDAGAQH/AgEAMHYGCCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0 cDovL29jc3AuZGlnaWNlcnQuY29tMEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0 cy5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3J0MHsGA1UdHwR0 MHIwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2Jh bFJvb3RDQS5jcmwwN6A1oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdp Q2VydEdsb2JhbFJvb3RDQS5jcmwwMAYDVR0gBCkwJzAHBgVngQwBATAIBgZngQwB AgEwCAYGZ4EMAQICMAgGBmeBDAECAzANBgkqhkiG9w0BAQsFAAOCAQEANJE52TD/ zFvmYQGp0P3ntVzclyqsN7Aga/s2SmhGoow32hcBWc6OVgQILYjXndBwRdTn6/97 nb+5a0sEfMoc7mto2ALmLim+XgZ6bg2nQX1A2lWYUoFou0YDHzGsKUNcLQOjoJU4 t9UMxv6+Je7RB77+j3mVmsNxBF13Q+LEHWiY+IJSazVqv7w73izbAFo6cF9sK0hp qdmSKdB/MNfnT9YF4/WYlyCwFhpaK3mPuU2XiOzGswPhMMRwgawnk4XTNemtHPSq fP/JzQHsefL75Tx5c8tHJAcp3C/QD+JcUUHocUPuW62x79wO9pNl5N5U4jIVFa4k x6pNQytYvwMPeg== -----END CERTIFICATE-----

Server certificate subject=C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = outlook.com

issuer=C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1


No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA Server Temp Key: ECDH, P-384, 384 bits

SSL handshake has read 4290 bytes and written 481 bytes Verification error: unable to get local issuer certificate

New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 184FAACAB6BE93B65195FCA04AE62754D41283DEF6330B6E45C6848ABA03732A Session-ID-ctx: Master-Key: F07DAFD277C26391AF4A1F37A2B4F94B8F3FECAF77EAD1CC02FE5F75F1E14861D6ACD36E88721391DB249C1B81FDAFEF PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 36000 (seconds) TLS session ticket: 0000 - 00 00 00 00 9f d2 90 4b-75 94 47 4d ae 48 99 c6 .......Ku.GM.H.. 0010 - 73 21 62 27 36 33 b1 81-31 f3 40 1b 7e b4 d4 80 s!b'63..1.@.~... 0020 - b4 78 d5 8e 5e 27 de 4c-ac 8b d4 04 dd 8f 1d d1 .x..^'.L........ 0030 - f4 1e de 97 a7 e1 5d d0-6f 2e b3 d0 42 8e 05 b2 ......].o...B... 0040 - 5e 49 9e 0a b2 c9 79 a5-35 1e 3b f5 9f 9d 8a aa ^I....y.5.;..... 0050 - f7 a5 81 06 7a a2 33 5a-7c c2 20 1f 33 0f cf 62 ....z.3Z|. .3..b 0060 - d2 d6 67 eb 46 2b f8 d5-4e cd 24 15 6f be 5f 7d ..g.F+..N.$.o._} 0070 - 84 d8 6b 96 a2 d9 55 9a-b2 6b 76 6e 17 02 67 10 ..k...U..kvn..g. 0080 - c8 b1 03 ec 43 d0 40 68-66 63 fc 70 ce 79 dd 7a ....C.@hfc.p.y.z 0090 - 21 c1 78 85 bb 94 c9 ec-6b 6b 22 65 0c 77 ad f3 !.x.....kk"e.w.. 00a0 - e0 6c 91 0a 48 49 70 7a-cf 84 37 dd e2 9c 13 82 .l..HIpz..7..... 00b0 - e0 bb fc e7 f4 ca a2 af-cb f3 58 9a 14 02 f4 a0 ..........X..... 00c0 - 6d 69 31 0f d1 07 2b 45-6b 1e c0 9c 5b 83 b4 19 mi1...+Ek...[... 00d0 - cf 07 27 48 7c de 1b 87-10 2b b0 66 46 22 b0 c7 ..'H|....+.fF".. 00e0 - 99 a0 13 36 92 e8 68 f5-db 4e 2d e3 ae 84 b4 da ...6..h..N-..... 00f0 - 17 47 ee 90 0e 29 fd b0-79 ec ae 46 d1 d8 3e a4 .G...)..y..F..>. 0100 - 41 6a c2 1f Aj..

Start Time: 1630005474
Timeout   : 7200 (sec)
Verify return code: 20 (unable to get local issuer certificate)
Extended master secret: yes

DONE

jborean93 commented 3 years ago

The default openssl on the system produces slightly different output:

Looks like you used the same OpenSSL for both outputs (/opt/local/bin/openssl). Nevertheless you need to resolve this problem so that OMI can verify the certificate. I have no idea why it cannot verify the issuer of C = US, O = DigiCert Inc, CN = DigiCert Cloud Services CA-1, potentially the root certs for OpenSSL installed with port isn't complete. I know with brew you have to run a separate command to sync the CA certificates with the OS keychain so potentially port is the same. You will have to read up on their documentation, a quick google search brings up packages like certsync or curl-ca-bundle (https://andatche.com/articles/2012/02/fixing-ssl-ca-certificates-with-openssl-from-macports/).

You can disable cert verification by using the env vars OMI_SKIP_CA_CHECK and OMI_SKIP_CN_CHECK but if you are setting them at runtime in your C# app you need to do it in a special way and not through the .NET API. See https://github.com/jborean93/omi/blob/main/docs/https_validation.md for more details. This is really not recommended as you should be relying on the cert verification of HTTPS to ensure the host you are talking to is who it says it is. Luckily it sounds like you just need to sync the CA certificates for the port OpenSSL and you will be in business.

I have a full example here: https://github.com/jeff-simeon/PowerShellWSManBug (no WSManConnectionInfo)

Is there a reason why you are targeting <PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.3" />. You should really be using something in the 7.x releases as 6 is EOL https://docs.microsoft.com/en-us/powershell/scripting/powershell-support-lifecycle?view=powershell-7.1.

jeff-simeon commented 3 years ago

I created that example a year and a half ago :)

jborean93 commented 3 years ago

That would make a lot of sense then :)

jeff-simeon commented 3 years ago

Thanks - Using sudo port install curl-ca-bundle resolved the SSL issue! Should have figured that one out myself.

Next error:

An unhandled exception of type 'System.AggregateException' occurred in System.Private.CoreLib.dll: 'One or more errors occurred.'
 Inner exceptions found, see $exception in variables window for more details.
 Innermost exception     System.Management.Automation.ActionPreferenceStopException : The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: [outlook.office365.com] Connecting to remote server outlook.office365.com failed with the following error message : Basic Authorization failed for user **** For more information, see the about_Remote_Troubleshooting Help topic.

What's odd here is that I'm using Bearer Auth, not basic. However, the way the remote session works is it takes a Basic Auth header with a user id and bearer token. Any idea what I need to do to get bearer auth working? Note that this works when running the same PowerShell code from pwsh.

jborean93 commented 3 years ago

To WSMan the modern auth is essentially basic auth, it’s the service that interprets it differently. Have a look at https://gist.github.com/jborean93/d50041c2a0fed20e87aa46ba32381754#file-new-exopssession-ps1-L176-L188 which implements modern auth in New-PSSession. Keep in mind the URI has a new prefix and the format of the username and password is quite particular.

I’m unsure why it would fail through the SDK but not when done on a pwsh instance but see if you can find any differences between your script and that snippet.

jeff-simeon commented 3 years ago

Got it working! Thank you! Just FYI - as an experiment - I tried using the same install_name_tool commands on bin/runtimes/osx/native/libmi.dylib' and it didn't work (still broke with the originalimage not found` error)...so clearly it's not just an OpenSSL path issue.

jeff-simeon commented 3 years ago

I'm down to one final issue it seems. This isn't a problem with anything related to your OMI fork, but if you have any knowledge on this, would certainly appreciate the help. Exchange Online works fine, but the following code for Security Center works perfectly from Windows (both powershell and pwsh), but bombs on Mac with the error (exact same code with the exact same token...just copy/pasted from Windows to Mac): Connecting to remote server ps.compliance.protection.outlook.com failed with the following error message : Basic Authorization failed for user.

On Mac, this fails both using pwsh and SDK and both with the default libmi as well as the one from PSWSMan.


$global:InformationPreference = 'Continue'
$global:ErrorActionPreference = 'Stop'
$global:ProgressPreference = 'SilentlyContinue'

function Get-Session {
    Get-PSSession |? ConfigurationName -eq 'Microsoft.Exchange'
}

function Remove-Session {
    foreach($s in Get-Session) { 
        try { 
            Write-Information "Removing existing open PSSession $($s.Id) for Microsoft.Exchange at https://ps.compliance.protection.outlook.com/powershell-liveid/?BasicAuthToOAuthConversion=true."        
            $s | Remove-PSSession
        } 
        catch {
            Write-Warning "Encountered an error removing PSSession $($s.Id) ($($_.Exception.Message))."      
        }
    }
}

function Initialize-Session {
    $sw = [System.Diagnostics.Stopwatch]::StartNew()
    $userCredential = New-Object System.Management.Automation.PSCredential('***', (ConvertTo-SecureString 'Bearer ***' -AsPlainText -Force))
    $option = New-PSSessionOption
    $option.IdleTimeout = [TimeSpan]::FromSeconds(60) # inline setting of this property via New-PSSessionOption is not supported on non-Windows platforms
    $option.OpenTimeout = [TimeSpan]::FromSeconds(60)
    Write-Information 'Creating PSSession for Microsoft.Exchange at https://ps.compliance.protection.outlook.com/powershell-liveid/?BasicAuthToOAuthConversion=true.'
    $connectionUri = 'https://ps.compliance.protection.outlook.com/powershell-liveid?BasicAuthToOAuthConversion=true'
    if ($IsMacOS) {
        # https://github.com/PowerShell/PowerShell/issues/7276
        $connectionUri = $connectionUri.Replace('&', '&amp;')
    }
    Write-Host $connectionUri
    $session = New-PSSession -SessionOption $option -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri -Credential $userCredential -Authentication Basic -AllowRedirection -WarningAction SilentlyContinue
    $module = Import-PSSession $session -DisableNameChecking -AllowClobber -WarningAction SilentlyContinue
    Import-Module $module -Global -WarningAction SilentlyContinue
    Write-Information "Imported PSSession $($session.Id) and Module for Microsoft.Exchange at https://ps.compliance.protection.outlook.com/powershell-liveid/?BasicAuthToOAuthConversion=true in $($sw.ElapsedMilliseconds)ms."
}

Remove-Session
Initialize-Session 
jeff-simeon commented 3 years ago

Small update - I tried using Fiddler Anywhere to compare the activity on Windows vs Mac and unfortunately, it doesn't look like PowerShell Core on Mac supports the notion of proxies for WinRM, so I can't get Fiddler to intercept the traffic on Mac...so I'm kind of stuck poking in the dark.

jborean93 commented 3 years ago

I'm unsure really, modern/basic auth is really quite simple from OMI's perspective. It's adding the base64 encoded value you specify so there's really no platform specific logic at play here. I would just make sure the method you use to retrieve the bearer token is the same across the platform and the value it is has a similar structure. I would also remove the $connectionUri = $connectionUri.Replace('&', '&amp;') and see if it's actually required anymore.

As for proxying you might have some luck setting the env var https_proxy=http://my-fidler-host as you start your app as it might just use that by default.

jeff-simeon commented 3 years ago
$connectionUri = $connectionUri.Replace('&', '&amp;')

yes - tried this as well - it definitely IS required for Exchange Online because EXO required the extra query string parameter DelegatedOrg which SC does not...so with the SC config it is a no-op because there is no & in the query string

https_proxy=http://my-fidler-host

yep - already tried that to no avail :(

what's so strange is that it's literally the exact same code and tokens that work/don't work between Windows/Mac

My hunch is that there is something about the content of the XML in the POST requests that is making it lose the fact that it's an OAuth attempt vs a regular basic auth attempt.

jborean93 commented 3 years ago

Not sure what else that could be done, you can enable DEBUG logging for OMI and look at the raw messages there. It should also contain the headers that are sent https://github.com/jborean93/omi#troubleshooting. You probably want to create /opt/omi/var/log which is where OMI places the trace files for the HTTP requests. I don't believe you can control this dir through the omicli.conf but it's been a while since I last played with it.

I know I was definitely able to connect to EXO without replacing the values in the connection URI but I was using the Office 365 URL specified in https://gist.github.com/jborean93/d50041c2a0fed20e87aa46ba32381754#file-new-exopssession-ps1-L176-L188. Unfortunately at this point you are at the mercy of what OMI provides you and are beyond my knowledge sorry.

jeff-simeon commented 3 years ago

Thanks - I enabled the logs and that got me on the right track. It's the redirection...

AllowRedirection in New-PSSession seems to be broken for Mac.

If I use the connection URI $connectionUri = 'https://nam10b.ps.compliance.protection.outlook.com/powershell-liveid/?BasicAuthToOAuthConversion=true'

it works (note the extra nam10b part of the hostname)

I'll see if I can get the redirected hostname manually using a REST call, unless you have an idea on the matter.