hashicorp / vagrant

Vagrant is a tool for building and distributing development environments.
https://www.vagrantup.com
Other
26.02k stars 4.42k forks source link

2.2.10 broke SMB synced_folder in enterprise environments #11945

Open braddeicide opened 3 years ago

braddeicide commented 3 years ago

Vagrant version

2.2.10

Host operating system

Windows 10

Guest operating system

Linux

Expected behavior

When using an authenticated SMB synced_folder Vagrant up continues after entering the correct credentials when prompted

Actual behavior

Vagrant up fails as authentication always fails

Steps to reproduce

  1. Have an SMB synced_folder
  2. Be on a machine you only have access to with AD credentials
  3. Vagrant up
  4. Enter correct AD credentials when prompted

References

https://github.com/hashicorp/vagrant/commit/c2df34298f27fc41d90320256945979ddcdd7cc0

I suspect by passing machine, local authentication is being requested which we don't have. In 2.2.9 AD credentials succeed. In 2.2.10 we ctrl-c the prompt and ssh into the machine manually mounting the local /vagrant share works with AD creds.

I don't currently have a dev env to test removing machine from that call.

dlarubia commented 3 years ago

Same here. I'm using 2.2.10 too, but i'm not in enterprise environment and the guests that I tried were Ubuntu 18.04LTS and Windows server 2019. When I set the variables in Vagrantfile the machines go up normally, but I cant access the folders equally

image

Sebjugate commented 3 years ago

We are having this issue as well with version 2.2.10. It seems that Vagrant's initial credential check wants DOMAIN\user or user@domain, but when vagrant tries to mount the share on the guest OS (CentOS 6), the credentials that were provided earlier get mangled and authentication fails. Windows event log showed failed authentication as using domain SAMBA despite the username already including the domain.

We've tried various arrangements, DOMAIN\user, user@domain, user@domain.tld, user, etc. including quoting the username string. There doesn't seem to be a variant that satisfies both vagrant's initial credential check and the guest OS's needs for mounting the share.

2.2.9 allows us to enter credentials as simply the username. Vagrant does not seem to immediately validate those credentials, as I can enter known incorrect values. So that may be why it works in 2.2.9. My suspicion is that 2.2.10 added some preliminary validation of the credentials, and that validation doesn't match what the guest OS needs when trying to mount the share.

lopsided98 commented 3 years ago

I don't think the change proposed in #11989 will fix this issue (unless there are multiple issues here). I experimented with it a bit and passing -contextType Domain seems to just make the script always fail no matter what credentials are given.

As others have said, check_credentials.ps1 is expecting DOMAIN\user, and it validates the credentials correctly if given that format (using ContextType::Machine). I believe the correct fix would be to split the user@DOMAIN string into its user and domain components and pass them in the correct format to check_credentials.ps1.

mhalano commented 2 years ago

I'm experiencing this with 2.2.18.

ashantyk commented 2 years ago

same here. 2.2.18

onpubcom commented 2 years ago

So on my end I was able to fix this issue by patching Vagrant's check_credentials.ps1 script (full path for my install is: C:\HashiCorp\Vagrant\embedded\gems\2.2.19\gems\vagrant-2.2.19\plugins\hosts\windows\scripts\check_credentials.ps1) by changing the following section from:

$DSContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext(
    [System.DirectoryServices.AccountManagement.ContextType]::Domain,
    $env:COMPUTERNAME
)
if ( $DSContext.ValidateCredentials( $username, $password ) ) {
    exit 0
} 

To:

$DSContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext(
    [System.DirectoryServices.AccountManagement.ContextType]::Domain,
    $env:USERDOMAIN
)
if ( $DSContext.ValidateCredentials( $username, $password ) ) {
    exit 0
} 

Note the only difference above is that we're constructing the PrincipalContext object with the current domain name via the $env:USERDOMAIN environment variable instead of the computer name $env:COMPUTERNAME environment var.

This appears to make it so that when I enter my username in the form of user[@domain] when prompted, the $DSContext.ValidateCredentials( $username, $password ) check now works as expected when the ContextType the script is checking against is [System.DirectoryServices.AccountManagement.ContextType]::Domain.

More info for this specific API can be found here:

Doc says the following for the above PrincipalContext object in regards to the second name constructor param:

The name of the domain or server for Domain context types

Couple other things I noticed in testing my patch above:

Let me know if this works for other folks on this thread, thanks!

PS: Without the above patch applied, when I entered my username in the form of domain\user the credentials check would work on the Windows side, but then when the SMB/CIFS mount command would be attempted inside the Linux guest VM, then the mount would fail with a permission denied error. This is because it seems like the script that generates the mount command fails to parse out the domain string in this case, because it's looking for it in the form of user@domain. So a potential alternate fix for this bug would be to patch the script that generates the guest mount command to also accept SMB username in the form of domain\user.

hegyre commented 2 years ago

I had the same issue, and I tested your workaround @onpubcom but this forces me to enable the VPN (so I did not tested entirely your solution). On vagrant 2.2.9, which was the last working version before this issue happened, that worked well without the VPN (probably using Windows domain cached credentials).

So I went to some files and dropped / reverted some lines of code:

C:\HashiCorp\Vagrant\embedded\gems\2.2.18\gems\vagrant-2.2.18\plugins\hosts\windows\scripts\check_credentials.ps1 Revert this commit: https://github.com/hashicorp/vagrant/pull/12428/files#diff-bd06477b1f03fce48a72b47419172c8634d05ef148982f9f0b3f4e8efd490382

C:\HashiCorp\Vagrant\embedded\gems\2.2.18\gems\vagrant-2.2.18\templates\locales\synced_folder_smb.yml Remove lines 13 and 14 (invalid credentials part) (Maybe not needed)

From https://github.com/soapy1/vagrant/commit/c2df34298f27fc41d90320256945979ddcdd7cc0#diff-ba2e76f88b2d746bad0e0dfc36c7f3db9518524d1cb1bf51511822cb49f819f7 : C:\HashiCorp\Vagrant\embedded\gems\2.2.18\gems\vagrant-2.2.18\plugins\synced_folders\smb\synced_folder.rb Remove "machine," line 69 (Maybe not needed)

C:\HashiCorp\Vagrant\embedded\gems\2.2.18\gems\vagrant-2.2.18\plugins\hosts\windows\plugin.rb Remove

      host_capability("windows", "smb_validate_password") do
        require_relative "cap/smb"
        Cap::SMB
      end

That last one (plus possible ones above which might not be needed) did the trick!

naresh97 commented 2 years ago

Still facing this issue on 2.2.18

dlkj commented 2 years ago

Also experiencing the same issue with domain credentials on 2.2.19.

@onpubcom workaround is working for me but I'd appreciate a fix that works offline.

StefanD986 commented 2 years ago

Almost 2 years later this bug is still there and its essentially a blocker for windows guest VMs. @soapy1 When can we expect a fix for this?

onpubcom commented 2 years ago

Also experiencing the same issue with domain credentials on 2.2.19.

@onpubcom workaround is working for me but I'd appreciate a fix that works offline.

@dlkj If you or anyone else in this thread knows of some way to check the cached/offline AD credential store via PowerShell, then it should be possible to do what you're requesting, but so far in my (admittedly brief) research I haven't found a way to do that. If anyone has any pointers on how to make my patch work offline, then I'd be happy to try and revise it and then submit it as a PR from there.

hegyre commented 2 years ago

@onpubcom Would that be helpful? https://techgenix.com/managing-cached-credentials/

TBBle commented 2 years ago

I hit this issue as well in 2.2.19, and the workaround in https://github.com/hashicorp/vagrant/issues/11945#issuecomment-918763938 turned out to be insufficient in my environment.

I ended up with the following block:

$DSContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext(
    [System.DirectoryServices.AccountManagement.ContextType]::Domain,
    $env:USERDNSDOMAIN
)
if ( $DSContext.ValidateCredentials( $username, $password, [System.DirectoryServices.AccountManagement.ContextOptions]::Negotiate ) ) {
    exit 0
} 

The two changes are using $env:USERDNSDOMAIN (although I'm not sure that was necessary, the workaround's $env:USERDOMAIN would probably work too), and adding [System.DirectoryServices.AccountManagement.ContextOptions]::Negotiate to the ValidateCredentials call.

The latter change (inspired by this blog post from 2015, so it's not new) wasn't needed when I ran the same script under PowerShell 7; so I suspect the default in .NET Core is different from .NET Framework. I also suspect this is needed because the default in .NET Framework was something like NTLM, which is now held to be insecure and has been disabled by my employer.

I only tested this with a username in the form user@corp.employer.local, and $env:USERDNSNAME is CORP.EMPLOYER.LOCAL.

Edit: I tried with the other username form user@employer.net, and that passed the credential check script, but failed when mounting inside the Linux VM I was building. Not sure if this is a linux/CIFS issue, an issue with the way the mount command is built, or only works due to something Windows does that Linux/CIFS does not and so it isn't expected to work.

I think in a proper fix, the $env:COMPUTERNAME that both workarounds are replacing should be the domain value extracted from the username if present with @ or \\ separator, since that's what's actually done on the in-VM side, as noted at the end of https://github.com/hashicorp/vagrant/issues/11945#issuecomment-918763938.

onpubcom commented 1 year ago

So my sense of this issue as it stands now is that it's not currently possible to use the Windows cached credentials store to validate existing credentials @hegyre @TBBle , even if we were to use the module described here https://techgenix.com/managing-cached-credentials/, correct me if I'm wrong though.

I've browsed the various core PowerShell/.NET API docs, and I didn't see anywhere there either which offers checking of cached AD credentials.

So a person really does need a network connection to their domain controllers in order to validate their login credentials when using my patch, it seems. I would argue this is still better than the currently still broken (last I checked) domain validation logic in the core Vagrant releases.

How would you feel about merging my patch in to an upcoming release @hegyre ? I'd be happy to create a PR at some point soon if you agree with my assessment here, lmk.

hegyre commented 1 year ago

Hey @onpubcom , Well, honestly I would personnally not be very happy to connect to the VPN each time I run vagrant (and also because that disconnects me from other things since all the traffic would go to the VPN, and I cannot change that).

That worked great with 2.2.9, why we couldn't simply revert to what it was with 2.2.9 ?

onpubcom commented 1 year ago

Fair enough @hegyre. Though I would argue that most people who have their machines connected to an AD are likely doing it because of their job or on a work computer, so in that case most folks would either be connected directly to their corporate network or VPN already when starting up their VMs via Vagrant, though I of course agree that this is the least desirable option if we can somehow still check local/cached credentials in a completely offline way.

I think at some point I'll test 2.2.9 on my domain connected machine to see if the logic in that version still works as expected on newer versions of Windows etc. Is there an older revision hash for that powershell script file in this repo that we could also look at to compare what the logic looks like in 2.2.9 vs. the current powershell logic for this flow? If you don't have that handy somewhere, I can try to dig it up sometime soon since that could also give some clues as to have broke in 2.2.10 and newer releases. Will circle back sometime soon, thanks.

hegyre commented 1 year ago

If I remember well (when my colleague tested my workaround above), by just removing that in C:\HashiCorp\Vagrant\embedded\gems\gems\vagrant-2.3.7\plugins\hosts\windows should make it works again:

     host_capability("windows", "smb_validate_password") do
        require_relative "cap/smb"
        Cap::SMB
      end
Clonkex commented 1 year ago

Is it possible to get this prioritised? It's straight-up broken, and seems an easy fix. I can maybe try to do a pull request at some point, although I'm not familiar with Ruby at all and I've never looked at Vagrant's internals.

At least I can confirm onpubcom's workaround works for me (although I found the file at C:\HashiCorp\Vagrant\embedded\gems\gems\vagrant-2.3.6\plugins\hosts\windows\scripts in my version).

Currently I have no choice but to include instructions on how to modify your Vagrant installation (!) in the readme for running on Windows, which is... less than ideal.

pingram3030 commented 3 months ago

fixing the domain check to use $env:USERDOMAIN is the most logical fix IMO as the current use of COMPUTERNAME is using your remote credentials to authenticate to the local host, which is analogous to using your local machine creds when authenticating to a remote server.

If a user with a domain joined computer needs to use their domain credentials, then they absolutely need to ensure they are on a network which can contact the DC; this is a user, not a vagrant, problem.

I am +1 to altering check_credentials.ps1 to ensure that domain authentication is made against the domain controller as the current local machine target is broken.

Vagrant: 2.4.1

onpubcom commented 3 months ago

Agreed, there's no way I found to check against any kind of cached AD credential from Powershell that I'm aware of (last I checked), so the patch I previously suggested is likely the only viable fix for this 🤷

hegyre commented 3 months ago

As of today my machine is now connected to the domain but with Azure AD, so when I go to the computer management, it's still seen as "Workgroup" but I'm really AAD-joined. Dunno if this thing plays a role here. Anyway if you need some testers I'm avail.

pingram3030 commented 1 month ago

I don't believe this plugin supports AAD at all, so that is another ticket all together.