-
Notifications
You must be signed in to change notification settings - Fork 256
Add CIFS/SMB based file sharing for windows #3308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
still need to test on a clean vm if the msi is able to set everything up, and also verify the assumption that |
97fd763 to
2b4517a
Compare
|
@gbraad PTAL |
| Before="EnableSMBFeature" | ||
| Sequence="execute"/> | ||
| <CustomAction Id="EnableSMBFeature" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="deferred" Impersonate="no" Return="ignore" /> | ||
| <SetProperty Action="CAEnableFileAndPrinterSharing" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it required to enable the sharing both for private and public? We are going to only use it for host -> VM communication, so maybe one of the 2 profiles will be enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think its needed to enable for both, because if we don't enable for both then we have a pre-condition that users need to be using the profile for which we enabled this to use shared dirs which i wanted avoid,
the way the profiles are set is If user's don't select a profile (when first time connecting to a new network) then windows will set the "Public" profile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which is a security feature. you don't wanna bypass this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its not a bypass, its just that I want the shared folders to be accessible in both "Private" and "Public" network profiles as we cannot predict what profile will be active on the user's machine
also the share is created giving access to only the login/current user and needs a password to access
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a bypass as you do not need 'public' access, as that is based on what the user has chosen.
If the users clicks this away, that is a 'user error'.
we cannot predict what profile will be active on the user's machine
Yes you can. Inform the user of proper use.
This is why you need to check for reachability of the share before using.
Password or not, that is a different problem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a bypass as you do not need 'public' access,
The network profiles in windows are about what type of network you are connected to (home aka private network vs cafe wifi aka public network) and not in the sense of if something is publicly accessible, based on the user's selection of the network profile some default settings are applied
Enabling it for both the profiles, lets the user have shared folders without worrying about what network profile is currently active, otherwise if we only enable it for one profile, "Private" network profile, as said we need the pre-condition "To use shared folders in windows users need to set the Private profile as the active network profile"
This is why you need to check for reachability of the share before using.
If we have properly setup the SMB share, there won't be any need to do this check, if we only enable sharing for "Private" network we can just check if the current active network profile is "Private"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as said we need the pre-condition "To use shared folders in windows users need to set the Private profile as the active network profile"
Can you check for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes there's a cmd Get-NetConnectionProfile but it also needs an interface (seems profiles are per interface, so we need to first find the active interface)
https://docs.microsoft.com/en-us/powershell/module/netconnection/get-netconnectionprofile?view=windowsserver2022-ps#example-1-get-a-connection-profile
pkg/drivers/hyperv/hyperv_windows.go
Outdated
| dir.Target = convertToUnixPath(dir.Target) | ||
| dir.Type = "cifs" | ||
| dir.Tag = smbShareUNCPathFromTag(dir.Tag) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imo this should be done in pkg/crc/machine/hyperv/driver_windows.go / pkg/crc/machine/config/driver.go when we are setting up the driver, rather than doing it lazily in GetSharedDirs. Better to have valid directory sharing information from the start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed the existing SharedDirs struct setup from pkg/crc/machine/config/driver.go and added to machine/vfkit/driver_darwin.go and machine/libvirt/driver_linux.go its the same code duplicated cba3a6c
next commit follows the same pattern and configures shared dirs for hyperv in machine/hyperv/driver_windows.go
pkg/drivers/hyperv/hyperv_windows.go
Outdated
|
|
||
| func convertToUnixPath(path string) string { | ||
| // converts a path like c:\users\crc to /mnt/c/users/crc | ||
| return fmt.Sprintf("/mnt/c%s", strings.TrimLeftFunc(filepath.ToSlash(path), func(r rune) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The podman function does not hardcode c as the drive, maybe we could reuse this helper directly rather than reimplementing it? (assuming vendoring this code does not make the binary a lot bigger).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a 9MB increase in the output binary which is not a lot, but the amount of code that is pulled in is huge! thinking to just c&p the relevent part from that function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather see us re-use code. c&p is not just unethical, we are supposed to share and combine most of the codebase over time anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, apart from the extra code in vendor, we don't need the full functionality of that Function in https://github.com/containers/podman/blob/67c4068bb35fd1aad95b1701c94ed11183d0fd66/pkg/specgen/winpath.go#L23-L41
i still think just c&p the relevant line is better then vendoring the whole podman codebase!
pkg/drivers/hyperv/hyperv_windows.go
Outdated
| func smbShareUNCPathFromTag(tag string) string { | ||
| hostname, err := cmdOut("hostname") | ||
| if err == nil { | ||
| return fmt.Sprintf("//%s.mshome.net/%s", strings.TrimSpace(hostname), tag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if we could use an IP there instead of hostname.mshome.net? Not sure it's better, maybe it would make the code simpler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have to figure out the ip address on one of the interfaces of the host or the "Default Switch" the default switch name might be localized, but this gives the ip address for default switch (Get-NetIPAddress -InterfaceAlias "vEthernet (Default Switch)").IPv4Address
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In minishift we extracted the IP address, verified reachability before allowing it to be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to use an ip address instead of hostname.mshome.net for the UNC path
526670c to
427a8cc
Compare
| KubeAdminPassword = "kubeadmin-password" | ||
| Preset = "preset" | ||
| EnableSharedDirs = "enable-shared-dirs" | ||
| SharedDirPassword = "shared-dir-password" // #nosec G101 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gbraad Changed this to shared-dir-password instead of smb-share-password more generic, can be reused when we do the sshfs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
password aren't shared among dirs, as they apply to each individual share.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh, but i couldn't find a way to set password per share in windows, either from the GUI or from the the smbshare powerhsell cmdlets
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Windows bases that on the UNC path; they can be assigned a different user and password combination. In the current case of CIFS use you only deal with a USERFOLDER and not 'arbitrary' options given by the user.
|
Just based on some of the comments from Christophe I say there is still some open issues; code re-use, IP address for use, etc. |
pkg/crc/config/settings.go
Outdated
|
|
||
| // Shared directories configs | ||
| if runtime.GOOS == "windows" { | ||
| validateSmbPasswordSet := func(value interface{}) (bool, string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this not a regular named function inside a _windows.go file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its following the same pattern that's in the config package.. and we can't use a _windows.go in there without a lot of refactor because of how we are registering the settings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so it is impossible to create a file named settings_windows.go and place this inside as a named function ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah looks like, if we do that we have to duplicate all of the common settings in settings_windows.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or RegisterSettings could call a registerOSSpecificSettings(), this should avoid the duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would prefer to do this refactor separate from this PR :) moved the function definition near the other similar functions, hopefully the code looks a bit better then before
| SSHKeyPath string | ||
| KubeConfig string | ||
| SharedDirs []string | ||
| SharedDirPassword string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so when we deal with sshfs, you are only able to use a single password for each of them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar to #3308 (comment) i was not thinking about sshfs internally that much, was only thinking about the user facing config options as of now, when implementing sshfs we might have to change this
| KubeConfig string | ||
| SharedDirs []string | ||
| SharedDirPassword string | ||
| SharedDirUsername string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto for the username?
pkg/crc/machine/driver.go
Outdated
|
|
||
| sharedDir := []libmachine.SharedDir{} | ||
| for _, dir := range driver.SharedDirs { | ||
| dir.Password = password |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so we assume all shares share the same password.
Which username is associated... do not see this relation in this part of code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, for windows its based on the user account, so shares themselves don't have passwords i am not considering about sshfs here, when we implement that we might have to change this
| Target: convertToUnixPath(dir), | ||
| Tag: smbShareUNCPathFromTag("crc-dir0"), // smb share 'crc-dir0' is created in the msi | ||
| Type: "cifs", | ||
| Username: machineConfig.SharedDirUsername, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so we associate the username at this point, but not the password? Why do we need to do this in the previous part in an update function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because we don't want to store the password in the machine config file, so that's handled by the update function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are concerned about the password, this is an association as a credential (username + password). It would make more sense to place the username in the update function too. Otherwise you are still 'leaking' information about the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its not as much about leaking information but storing a secret on disk unencrypted which we want to prevent, on the user's machine any non-privilege process can just run whoami and get that username, so it should be fine to store in the machine config?
btw this was suggested in #3308 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any non-privilege process can just run whoami and get that username,
People share the virtual machine folder as we do not offer an export function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh, but that'd be a very special unsupported use case, assume most of our users don't do this, also we don't test it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It turns out to be different from what I suggested earlier, but maybe this should all be coming from the keyring then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only the password needs to be securely stored, username we can derive during start, we just skip writing it to machine config json same as the password
|
PR rebased on top of #3333 |
gbraad
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved for podman bundle
Unable to test for the OpenShift bundle
Follow-up issues needed for the initial flow. Can't be enabled by default as an explicit password is needed.
|
/retest |
tested with the new |
cfergeau
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this waiting for a second ACK? Gerard approved this a while ago.
| if !cfg.Get(HostNetworkAccess).AsBool() { | ||
| return false, fmt.Sprintf("%s can only be used with %s set to 'true'", | ||
| EnableSharedDirs, HostNetworkAccess) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way to restrict this to only the ports needed for file sharing?
The VM having access to all the services running on the host, and also knowing the user login/password does not sound great from a security perspective. We've removed a big part of the isolation between host and guest imo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't know if its possible to filter for ports, i guess that will also need changes to gvisor-tap-vsock
maybe we could try adding a :port to the NAT table entries setup during daemon start and see if that works!
| func RequiresCleanupAndSetupMsg(key string, _ interface{}) string { | ||
| return fmt.Sprintf("Changes to configuration property '%s' are only applied during 'crc setup'.\n"+ | ||
| "Please run 'crc cleanup' followed by 'crc setup' for this configuration to take effect.", key) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow-up issue to make this more dynamic would be useful to have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: cfergeau, gbraad The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
This enbles file and printer sharing for the 'Private' and 'Public' network profiles Sharing is enabled during install and disabled during uninstall
This creates a samba share named 'crc-dir0' of the logon user's home folder during installation
options needed for the shared dirs such as the source path, target path and types etc. differs between drivers and its best to configure those at the specific driver level although currently both libvirt and vfkit have the same options for their shared directories, hyperv will have different options to use smb instead of virtiofs
it allows users to mount the host's home folder at /mnt/c/users/$username directory in the crc vm to determine if folder sharing is supported/enabled it checks that a smb share named 'crc-dir0' exists which should've been created during msi installation since CIFS/SMB is a network file system and needs a username and password for getting access two new fields 'SharedDirUsername' and 'SharedDirPassword' is added to the MachineConfig and StartConfig structs
this adds a new error type MaskedSecretError to the errors package
currently we need this to get the username in windows for mounting the shared directories, which is CIFS/SMB based and needs the username for access
this adds an additional config 'shared-dir-password' to store the needed password for mounting the samba share and modifies the help message of 'enable-shared-dirs' config for linux and macOS the 'shared-dir-password' config is a secret config and is not listed in the reponse from the config api when getting all the config options
since we filter out the secret configs in the response from config api we need to also skip them in the api client test case to make it pass addition of the 'enable-shared-dirs' secret config makes the test fail in the previous commit this was missed in 105ad05
changes to 'host-network-access' only works when the daemon is restarted for this to happen user needs to run 'crc cleanup' and then 'crc setup' this adds a new function 'RequiresCleanupAndSetupMsg' config package
|
New changes are detected. LGTM label has been removed. |

Needs crc-org/machine#66
Solution/Idea
the default CIFS/SMB feature provided from windows
can be used to share directories over the network
we can use it to share files between host and crc
vm
Adds the following config options:
enable-shared-dirs(was present on macOS and linux now added to windows)smb-share-passwordTesting
msifrom this PR to installcrccrc config set enable-shared-dirs trueand follow the instructions from the validation msg (it should ask to configuresmb-share-passwordfirst)crc config set preset podmanandcrc setupcrc startwith podman preset and bundle from Add cifs-utils package to hyperV bundle snc#565 should succeed (download from openshift CI artifacts)podman run -v /mnt/home/crc/conf:/etc/http/conf httpd