Skip to content

Commit

Permalink
add support for owner, group, and mount_options
Browse files Browse the repository at this point in the history
There are some toplevel options that can be provided
to synced_folders plugins that include `owner`, `group`
and `mount_options` [1] . Let's try to add support for
them here.

The owner/group settings haven't really been an issue
for us I think because we pass in `-o allow_other` to
sshfs, but we had a request for support so let's try
to comply.

Closes #127

[1] https://github.com/hashicorp/vagrant/blob/2c3397c46851ef29a3589bf3214a3eee12da8484/website/content/docs/synced-folders/basic_usage.mdx#options
  • Loading branch information
dustymabe committed Jun 20, 2022
1 parent e76db4d commit b77809e
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 24 deletions.
22 changes: 21 additions & 1 deletion lib/vagrant-sshfs/cap/guest/linux/sshfs_forward_mount.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require "vagrant/util/retryable"
require "vagrant/util/platform"
require "tempfile"
require Vagrant.source_root.join("plugins/synced_folders/unix_mount_helpers")

# This is already done for us in lib/vagrant-sshfs.rb. We needed to
# do it there before Process.uid is called the first time by Vagrant
Expand All @@ -15,6 +16,7 @@ module GuestLinux
module Cap
class MountSSHFS
extend Vagrant::Util::Retryable
extend VagrantPlugins::SyncedFolder::UnixMountHelpers
@@logger = Log4r::Logger.new("vagrant::synced_folders::sshfs_mount")

def self.list_mounts_command
Expand Down Expand Up @@ -80,7 +82,25 @@ def self.sshfs_forward_mount_folder(machine, opts)
hostpath = File.expand_path(opts[:hostpath], machine.env.root_path)
hostpath = Vagrant::Util::Platform.fs_real_path(hostpath).to_s
end


# Support for user provided mount_options, owner, group
# https://github.com/hashicorp/vagrant/blob/2c3397c46851ef29a3589bf3214a3eee12da8484/website/content/docs/synced-folders/basic_usage.mdx#options
mount_options = opts.fetch(:mount_options, [])
# Determine owner/group info to use
if (opts.has_key?(:owner) and opts[:owner]) or
(opts.has_key?(:group) and opts[:group])
detected_ids = detect_owner_group_ids(
machine, expanded_guest_path, mount_options, opts)
mount_uid = detected_ids[:uid]
mount_gid = detected_ids[:gid]
mount_options.append("uid=#{mount_uid}")
mount_options.append("gid=#{mount_gid}")
end
# Combine mount_options into sshfs_opts_append (also user provided)
if not mount_options.empty?()
opts[:sshfs_opts_append] =
opts[:sshfs_opts_append].to_s + ' -o ' + mount_options.join(',') + ' '
end

# Add in some sshfs/fuse options that are common to both mount methods
opts[:sshfs_opts] = ' -o allow_other ' # allow non-root users to access
Expand Down
41 changes: 41 additions & 0 deletions lib/vagrant-sshfs/cap/host/linux/sshfs_reverse_mount.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,50 @@ def self.sshfs_mount(machine, opts)

ssh_opts_append = opts[:ssh_opts_append].to_s # provided by user

# Support for user provided mount_options, owner, group
# https://github.com/hashicorp/vagrant/blob/2c3397c46851ef29a3589bf3214a3eee12da8484/website/content/docs/synced-folders/basic_usage.mdx#options
mount_options = opts.fetch(:mount_options, [])
if (opts.has_key?(:owner) and opts[:owner]) or
(opts.has_key?(:group) and opts[:group])
# Find the `id` command on the system and set the error class
id_command = Vagrant::Util::Which.which('id')
getent_command = Vagrant::Util::Which.which('getent')
error_class = VagrantPlugins::SyncedFolderSSHFS::Errors::SSHFSFindUIDGIDFailed
# Identify the uid
cmd = "#{id_command} -u #{opts[:owner]}"
result = Vagrant::Util::Subprocess.execute(*cmd.split())
if result.exit_code != 0
raise error_class, command: cmd, stdout: result.stdout, stderr: result.stderr
end
mount_uid = result.stdout.chomp
# Identify the gid. If a group was provided use that otherwise use
# the group detected with the detected user id.
if opts.has_key?(:group) and opts[:group]
cmd = "#{getent_command} group #{opts[:group]}"
result = Vagrant::Util::Subprocess.execute(*cmd.split())
if result.exit_code != 0
raise error_class, command: cmd, stdout: result.stdout, stderr: result.stderr
end
mount_gid = result.stdout.split(':').at(2).to_s.chomp
else
cmd = "#{id_command} -g #{mount_uid}"
result = Vagrant::Util::Subprocess.execute(*cmd.split())
if result.exit_code != 0
raise error_class, command: cmd, stdout: result.stdout, stderr: result.stderr
end
mount_gid = result.stdout.chomp
end
# Add them to the mount options
mount_options.append("uid=#{mount_uid}")
mount_options.append("gid=#{mount_gid}")
end

# SSHFS executable options
sshfs_opts = opts[:sshfs_opts]
sshfs_opts_append = opts[:sshfs_opts_append].to_s # provided by user
if not mount_options.empty?()
sshfs_opts_append+= ' -o ' + mount_options.join(',') + ' '
end

username = machine.ssh_info[:username]
host = machine.ssh_info[:host]
Expand Down
4 changes: 4 additions & 0 deletions lib/vagrant-sshfs/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class SSHFSExeNotAvailable < SSHFSError
class SSHFSGetAbsolutePathFailed < SSHFSError
error_key(:get_absolute_path_failed)
end

class SSHFSFindUIDGIDFailed < SSHFSError
error_key(:find_uid_gid_failed)
end
end
end
end
14 changes: 14 additions & 0 deletions locales/synced_folder_sshfs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,18 @@ en:
Stderr from the command:
%{stderr}
find_uid_gid_failed: |-
Attempting to find the UID/GID failed.
The command and output are:
%{command}
Stdout from the command:
%{stdout}
Stderr from the command:
%{stderr}
36 changes: 21 additions & 15 deletions test/misc/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,46 @@
# To test we will first create the directory on the machine where
# we will mount the guest /etc/ into the host (the reverse mount).

mkdir /tmp/reverse_mount_etc
mkdir /tmp/reverse_mount_etc_uid_gid/

# Next we will define where our 3rd party host is (the normal mount).
# This can be another vagrant box or whatever machine you want.
export THIRD_PARTY_HOST='192.168.121.73'
export THIRD_PARTY_HOST_USER='vagrant'
export THIRD_PARTY_HOST='192.168.121.73'
export THIRD_PARTY_HOST_USER='vagrant'
export THIRD_PARTY_HOST_PASS='vagrant'

# Open an extra file descriptor to test it is not passed onto child processes
# https://github.com/dustymabe/vagrant-sshfs/issues/120
tmpfile=$(mktemp)
exec {extra_fd}<> "$tmpfile"

# Next vagrant up - will do 4 mounts
# Next vagrant up - will do 5 mounts
# - slave
# - slave with owner/group
# - slave with sym link
# - normal
# - reverse
# - normal (from 3rd party host)
# - reverse with owner/group
vagrant up

# Next run the script to test the mounts:
$ bash dotests.sh
Testing slave forward mount!
d635332fe7aa4d4fb48e5cb9357bdedf
1358d4a18a2d4ba7be380b991e899952
Testing slave forward mount with owner/group!
root:wheel
1358d4a18a2d4ba7be380b991e899952
Testing slave forward mount with a symlink!
d635332fe7aa4d4fb48e5cb9357bdedf
1358d4a18a2d4ba7be380b991e899952
Testing normal forward mount!
6ccc3034df924bd289dd16205bf3d629
Testing reverse mount!
508619e7e68e446c84d1fcdf7e0dc577

# We are printing out the machine-id under each mount. The first two
should be the same, because they are from the same machine. The last
two should be different.
ef56862ae88f43c0a81962ba6f68a668
Testing reverse mount with owner/group!
root:wheel
ef4f3b50e2034b3593a9eb8b71350abe

# We are printing out the machine-id under each mount. The first three
should be the same, because they are from the same machine (the host).
The last two should be different; one from 3rd party machine and one
from the test VM itself (read from the host).

# Close our file descriptor. No other process should be using it
exec {extra_fd}>&-
Expand Down
31 changes: 25 additions & 6 deletions test/misc/Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,41 @@ Vagrant.configure(2) do |config|

# Test a forward slave mount:
# mounting /etc/ from the vagrant host into the guest
config.vm.synced_folder "/etc/", "/tmp/forward_slave_mount_etc/", type: "sshfs"
config.vm.synced_folder "/etc/", "/tmp/forward_slave_mount_etc/",
type: "sshfs",
mount_options: ['ro']

# Test a forward slave with owner/group info:
# mounting /etc/ from the vagrant host into the guest
config.vm.synced_folder "/etc/", "/tmp/forward_slave_mount_etc_uid_gid/",
type: "sshfs",
mount_options: ['ro', 'default_permissions'],
owner: "root",
group: "wheel"

# Test a forward mount to a location that is a symbolic link
# https://github.com/dustymabe/vagrant-sshfs/issues/44
config.vm.synced_folder "/etc/", "/var/run/forward_slave_mount_sym_link_test/", type: "sshfs"
config.vm.synced_folder "/etc/", "/var/run/forward_slave_mount_sym_link_test/",
type: "sshfs",
mount_options: ['ro']

# Test a forward normal mount:
# mounting a folder from a 3rd party host into guest
config.vm.synced_folder "/etc/", "/tmp/forward_normal_mount_etc/", type: "sshfs",
config.vm.synced_folder "/etc/", "/tmp/forward_normal_mount_etc/",
type: "sshfs",
ssh_host: ENV['THIRD_PARTY_HOST'],
ssh_username: ENV['THIRD_PARTY_HOST_USER'],
ssh_password: ENV['THIRD_PARTY_HOST_PASS']
ssh_password: ENV['THIRD_PARTY_HOST_PASS'],
mount_options: ['ro']

# Test a reverse mount:
# Test a reverse mount with owner/group
# mounting /etc/ from vagrant guest into vagrant host
config.vm.synced_folder "/tmp/reverse_mount_etc/", "/etc", type: "sshfs", reverse: true
config.vm.synced_folder "/tmp/reverse_mount_etc_uid_gid/", "/etc",
type: "sshfs",
reverse: true,
owner: "root",
group: "wheel",
mount_options: ['ro']

host = 'sshfs-tests'
box = 'fedora/34-cloud-base'
Expand Down
11 changes: 9 additions & 2 deletions test/misc/dotests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@ set -eu
echo -en "Testing slave forward mount!\n\t"
vagrant ssh -- cat /tmp/forward_slave_mount_etc/machine-id

echo -en "Testing slave forward mount with owner/group!\n\t"
vagrant ssh -- stat --printf '%U:%G' /tmp/forward_slave_mount_etc_uid_gid
echo -en "\n\t"
vagrant ssh -- cat /tmp/forward_slave_mount_etc_uid_gid/machine-id

# https://github.com/dustymabe/vagrant-sshfs/issues/44
echo -en "Testing slave forward mount with a symlink!\n\t"
vagrant ssh -- cat /run/forward_slave_mount_sym_link_test/machine-id

echo -en "Testing normal forward mount!\n\t"
vagrant ssh -- cat /tmp/forward_normal_mount_etc/machine-id

echo -en "Testing reverse mount!\n\t"
cat /tmp/reverse_mount_etc/machine-id
echo -en "Testing reverse mount with owner/group!\n\t"
stat --printf '%U:%G' /tmp/reverse_mount_etc_uid_gid/
echo -en "\n\t"
cat /tmp/reverse_mount_etc_uid_gid/machine-id

0 comments on commit b77809e

Please sign in to comment.