dbatools icon indicating copy to clipboard operation
dbatools copied to clipboard

"unable to load DLL 'Microsoft.Data.SqlClient.SNI.dll'" errors with pwsh and credentials

Open paschott opened this issue 2 years ago • 36 comments

Verified issue does not already exist?

Yes

What error did you receive?

Started getting "unable to load DLL 'Microsoft.Data.SqlClient.SNI.dll' " errors w/ dbatools in pwsh when trying to run commands using credentials.

e.g., Get-DbaMaxMemory machinename -SqlCredential $cred throws that error.

I seem to get it whenever passing in a credential w/ a dbatools function, but that same credential works for a native command like "Enter-PSSession".

Steps to Reproduce

Get-DbaMaxMemory machinename -SqlCredential $cred

Get "unable to load DLL 'Microsoft.Data.SqlClient.SNI.dll' " error

Are you running the latest release?

Yes

Other details or mentions

This command worked within the last month or so as I use dbatools functions pretty regularly and have to pass in alternate credentials to connect to various machines. Here are the changes I can think of: SSMS v18.11.1 upgrade dbatools upgrade (to latest releases) pwsh.exe upgrade to v7.2.2

These functions work on the same machine using Windows PowerShell v5.1

What PowerShell host was used when producing this error

PowerShell Core (pwsh.exe)

PowerShell Host Version

Name Value


PSVersion 7.2.2 PSEdition Core GitCommitId 7.2.2 OS Microsoft Windows 10.0.19043 Platform Win32NT PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…} PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 WSManStackVersion 3.0

SQL Server Edition and Build number

n/a

.NET Framework Version

.NET 6.0.3

paschott avatar Mar 30 '22 20:03 paschott

Quick note - Get-DbaDiskSpace seems to work with the -Credential parameter, but Get-DbaMaxMemory does not work with a credential parameter. Tested using the same credential and the same target machine using pwsh.

paschott avatar Mar 31 '22 22:03 paschott

Same behavior w/ v1.1.86 and pwsh.exe.

paschott avatar Apr 04 '22 21:04 paschott

I was able to load the file in the dbatools bin\smo folder by using "add-type" for the file, but still get an Access Denied error when trying to use the -SqlCredential option with dbatools.

paschott avatar Apr 20 '22 14:04 paschott

Hi @paschott - can you still reproduce the issue?

andreasjordan avatar Oct 24 '22 09:10 andreasjordan

@andreasjordan I ended up working around it by granting permissions to that "admin" account for the PS Modules folder, so I stopped getting the error there. That's the only machine I really use that for right now so the problem is mitigated, but that's with a workaround. I'll have to try removing permissions from that folder to see if I'm still getting the error w/ the latest pwsh + dbatools module.

paschott avatar Oct 24 '22 14:10 paschott

Thanks for the feedback. I will leave this open for a while, happy to hear from you.

andreasjordan avatar Oct 24 '22 14:10 andreasjordan

I think the new library in the upcoming dbatools 2.0 will suit you a lot better. no idea why the admin thing worked (cuz i dont understand dlls) but im doing it very differently and it should be more reliable.

potatoqualitee avatar Oct 24 '22 14:10 potatoqualitee

Well, it was some way it handled the permissions. If I called a dbatools function that queried some server but used credentials. For some reason, those credentials seemed to be used to access my local files. Once I granted permissions to that credential account to my local folder, the calls worked. I hadn't thought about it too much since making that tweak. Of course, that wouldn't work for cases where the domain isn't trusted or similar. I'll re-test shortly once I get over to that machine.

paschott avatar Oct 24 '22 14:10 paschott

Just verified - I removed permissions for that admin account from my local PowerShell\Modules folder and got the same error. Latest dbatools + pwsh (updated today for both).

paschott avatar Oct 24 '22 15:10 paschott

Ahhhh, okay. There will be nothing I can do on my end -- I never considered this as a side effect of installing to the current user scope! Please continue with this workaround or install to the system scope.

potatoqualitee avatar Oct 26 '22 06:10 potatoqualitee

@potatoqualitee @andreasjordan I can confirm this issue still exists even in the new code changes coming in 2.0 release.

The issue that is happening is once a credential is provided PowerShell is performing an impersonation trying to create the DLL file in a location within the user's PATH environment. You can observe in the screenshot below all the CreateFile operations occurring where it is going through the paths in my PATH environment trying to create that DLL file.

image

This is not normal but I'm not aware of why it is happening yet.

The error being returned as ConnectionError is coming from this code section, so I'm not 100% sure why this triggers the DLL being created across the PATH values.

https://github.com/dataplat/dbatools/blob/b8fe96052245edab3e568c11bd43c468a8b0fc8a/functions/Connect-DbaInstance.ps1#L920-L929

wsmelton avatar Dec 20 '22 17:12 wsmelton

I opened up PowerShell and did nothing (I was planning to import SqlServer) and had similar results

image

Weirdly, when I import SqlServer, i get no hits for SNI. I just have no clue how they import things but I imagine it's drastically different because everything is compiled.

Ultimately, the permission denied thing makes sense to me if the module is installed in the user scope. Enter-PSSession works because it's available in the global scope. Get-DbaDiskSpace uses purely remotely available calls and can be run against non-SQL Servers, while Test-DbaMaxMemory makes a call to SQL Server and thus needs the SqlClient DLLs. If this worked previously, it's because we used System.Data and not Microsoft.Data. System.Data is available system-wide whereas Microsoft.Data is available in our module. Ultimately, I'd say to install with the AllUsers scope and there should be no issue.

potatoqualitee avatar Dec 21 '22 12:12 potatoqualitee

Oh also, the CreateFile is a misnomer if I had to guess. I think it is actually just trynna open it.

potatoqualitee avatar Dec 21 '22 12:12 potatoqualitee

All user scope won't fix this because I'm using the module from a saved path (c:\git\dbatools\dbatools.psd1). Recall I'm using the development branch of GitHub (local development) so the module exist under a completely separate path that is not even part of the PSModule paths.

wsmelton avatar Dec 21 '22 13:12 wsmelton

Yes, that account is not aware of that path which alluserscope would fix, I'm guessing. testing now!

potatoqualitee avatar Dec 21 '22 14:12 potatoqualitee

I added the github path via registry to all users to emulate alluser scope and tested with success

image

AW BRUH, I did this all with powershell.exe. BRB

potatoqualitee avatar Dec 21 '22 14:12 potatoqualitee

no idea how to work around this :( anyone know more about interoperability?

image

potatoqualitee avatar Dec 21 '22 14:12 potatoqualitee

It is only the core library module that has to be installed in all user scope, follow now. That is a pretty big breaking change for those users that don't use Install-Module or Install-PSResource in their environment. (Not sure we have that many anymore as we used to)

wsmelton avatar Dec 21 '22 14:12 wsmelton

yeah, i drew the line there and wont support install.ps1 anymore. they'll have to find a machine with install-module or save-module or download the zips manually.

potatoqualitee avatar Dec 21 '22 14:12 potatoqualitee

This will need some docs if that is the solution. Or like, figure out how to do 7 to 7 without much fuss. Any idea?

potatoqualitee avatar Dec 21 '22 15:12 potatoqualitee

image ?

niphlod avatar Dec 21 '22 15:12 niphlod

nope but .... https://github.com/PowerShell/PowerShell/issues/11616

niphlod avatar Dec 21 '22 16:12 niphlod

Not sure remoting plays into here because there is no session created. I'm local on my machine doing this and the impersonation is a thread within pwsh running under that cred context.

wsmelton avatar Dec 21 '22 17:12 wsmelton

I dont believe you can do Invoke-Command -ComputerName localhost -Credential $cred without remoting being enabled. I had to enable it for my machine. Maybe the underlying framework (or we) skips it? or doesnt skip it?

potatoqualitee avatar Dec 22 '22 12:12 potatoqualitee

but a session must be created to downgrade to 5.1 from 7? ohh lemme check the pid

potatoqualitee avatar Dec 22 '22 12:12 potatoqualitee

innnnnnnnnnnnnterresting

[7ms] C:/github❯ $pid
11952
[1ms] C:/github❯ Invoke-Command -ComputerName workstation -Credential $cred -ScriptBlock { $pid }
8684
[272ms] C:/github❯ Invoke-Command -ComputerName workstation -Credential $cred -ScriptBlock { $pid }
20568

potatoqualitee avatar Dec 22 '22 13:12 potatoqualitee

We may need to separate this to another issue because there is a difference between PS Remoting and the issue with credential from our Connect function.

User awareness is responsible for invoke calls to a remote Windows devices. PowerShell remote configuration on their environment has to be changed and managed in order for them to get a PS7 to PS7 session.

The connect using a credential and impersonating is something with the library and/or something PS is doing locally in the same thread/session.

wsmelton avatar Dec 22 '22 13:12 wsmelton

If a user wants to run the module in Windows PowerShell from PS 7 on their local machine they can Import-Module ... -UseWindowsPowerShell. That will create a runspace in PS7 session with a remote session to the 5.1 host on their local machine.

wsmelton avatar Dec 22 '22 13:12 wsmelton

Unfortunately, that's probably not going to be too helpful.

PowerShell 7.3.1
PS C:\github> Import-Module -UseWindowsPowerShell dbatools
WARNING: Module dbatools is loaded in Windows PowerShell using WinPSCompatSession remoting session; please note that all input and output of commands from this module will be deserialized objects. If you want to load this module into PowerShell please use 'Import-Module -SkipEditionCheck' syntax.
PS C:\github> Connect-DbaInstance -SqlInstance sqlcs

ComputerName Name  Product Version   HostPlatform IsAzure IsClustered ConnectedAs
------------ ----  ------- -------   ------------ ------- ----------- -----------
             sqlcs         15.0.4236
Out-Default: urn could not be resolved at level OleDbProviderSetting.

potatoqualitee avatar Dec 22 '22 14:12 potatoqualitee

I'm using 7.3.1 and whether I'm passing in a credential or creating a connection with credential I don't see the issue occurring with PS Remoting. A credential being passed to SMO does not interact with PowerShell nor PS Remoting, it is thread based and doing an impersonation only.

image

wsmelton avatar Dec 22 '22 14:12 wsmelton