command/sudoers: Move wrapper string out to a template and use the full path to the scripts in order to make things work properly across different distros
Closes GH-304 Closes GH-305
This commit is contained in:
parent
d3b9d53097
commit
d0642c95fd
3 changed files with 131 additions and 117 deletions
|
@ -8,12 +8,16 @@ IMPROVEMENTS:
|
||||||
|
|
||||||
BUG FIXES:
|
BUG FIXES:
|
||||||
|
|
||||||
|
- Figure out the real executable paths for whitelisted commands on the sudo
|
||||||
|
wrapper script instead of hardcoding Ubuntu paths [[GH-304]] / [[GH-305]]
|
||||||
- Attach to containers using the `MOUNT` namespace when attempting to fetch
|
- Attach to containers using the `MOUNT` namespace when attempting to fetch
|
||||||
container's IP [[GH-300]]
|
container's IP [[GH-300]]
|
||||||
- Escape space characters for synced folders [[GH-291]]
|
- Escape space characters for synced folders [[GH-291]]
|
||||||
- Use Vagrant's ruby on the sudoers file so that it works on systems that don't
|
- Use Vagrant's ruby on the sudoers file so that it works on systems that don't
|
||||||
have a global ruby installation [[GH-289]]
|
have a global ruby installation [[GH-289]]
|
||||||
|
|
||||||
|
[GH-304]: https://github.com/fgrehm/vagrant-lxc/issues/304
|
||||||
|
[GH-305]: https://github.com/fgrehm/vagrant-lxc/issues/305
|
||||||
[GH-300]: https://github.com/fgrehm/vagrant-lxc/issues/300
|
[GH-300]: https://github.com/fgrehm/vagrant-lxc/issues/300
|
||||||
[GH-291]: https://github.com/fgrehm/vagrant-lxc/issues/291
|
[GH-291]: https://github.com/fgrehm/vagrant-lxc/issues/291
|
||||||
[GH-289]: https://github.com/fgrehm/vagrant-lxc/issues/289
|
[GH-289]: https://github.com/fgrehm/vagrant-lxc/issues/289
|
||||||
|
|
|
@ -40,130 +40,21 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
# REFACTOR: Make use ERB rendering after https://github.com/mitchellh/vagrant/issues/3231
|
|
||||||
# lands into core
|
# This requires vagrant 1.5.2+ https://github.com/mitchellh/vagrant/commit/3371c3716278071680af9b526ba19235c79c64cb
|
||||||
def create_wrapper!
|
def create_wrapper!
|
||||||
wrapper = Tempfile.new('lxc-wrapper').tap do |file|
|
wrapper = Tempfile.new('lxc-wrapper').tap do |file|
|
||||||
file.puts "#!/opt/vagrant/embedded/bin/ruby"
|
template = Vagrant::Util::TemplateRenderer.new(
|
||||||
file.puts "# Automatically created by vagrant-lxc"
|
'sudoers.rb',
|
||||||
file.puts <<-EOF
|
:template_root => Vagrant::LXC.source_root.join('templates').to_s,
|
||||||
class Whitelist
|
:cmd_paths => build_cmd_paths_hash
|
||||||
class << self
|
)
|
||||||
def add(command, *args)
|
file.puts template.render
|
||||||
list[command] << args
|
|
||||||
end
|
|
||||||
|
|
||||||
def list
|
|
||||||
@list ||= Hash.new do |key, hsh|
|
|
||||||
key[hsh] = []
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def allowed(command)
|
|
||||||
list[command] || []
|
|
||||||
end
|
|
||||||
|
|
||||||
def run!(argv)
|
|
||||||
begin
|
|
||||||
command, args = `which \#{argv.shift}`.chomp, argv || []
|
|
||||||
check!(command, args)
|
|
||||||
puts `\#{command} \#{args.join(" ")}`
|
|
||||||
exit $?.to_i
|
|
||||||
rescue => e
|
|
||||||
STDERR.puts e.message
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def check!(command, args)
|
|
||||||
allowed(command).each do |checks|
|
|
||||||
return if valid_args?(args, checks)
|
|
||||||
end
|
|
||||||
raise_invalid(command, args)
|
|
||||||
end
|
|
||||||
|
|
||||||
def valid_args?(args, checks)
|
|
||||||
return false unless valid_length?(args, checks)
|
|
||||||
check = nil
|
|
||||||
args.each_with_index do |provided, i|
|
|
||||||
check = checks[i] unless check == '**'
|
|
||||||
return false unless match?(provided, check)
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def valid_length?(args, checks)
|
|
||||||
args.length == checks.length || checks.last == '**'
|
|
||||||
end
|
|
||||||
|
|
||||||
def match?(arg, check)
|
|
||||||
check == '**' || check.is_a?(Regexp) && !!check.match(arg) || arg == check
|
|
||||||
end
|
|
||||||
|
|
||||||
def raise_invalid(command, args)
|
|
||||||
raise "Invalid arguments for command \#{command}, " <<
|
|
||||||
"provided args: \#{args.inspect}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
base = "/var/lib/lxc"
|
|
||||||
base_path = %r{\\A\#{base}/.*\\z}
|
|
||||||
templates_path = %r{\\A/usr/(share|lib|lib64|local/lib)/lxc/templates/.*\\z}
|
|
||||||
|
|
||||||
##
|
|
||||||
# Commands from provider.rb
|
|
||||||
# - Check lxc is installed
|
|
||||||
Whitelist.add '/usr/bin/which', /\\Alxc-\\w+\\z/
|
|
||||||
|
|
||||||
##
|
|
||||||
# Commands from driver.rb
|
|
||||||
# - Container config file
|
|
||||||
Whitelist.add '/bin/cat', base_path
|
|
||||||
# - Shared folders
|
|
||||||
Whitelist.add '/bin/mkdir', '-p', base_path
|
|
||||||
# - Container config customizations and pruning
|
|
||||||
Whitelist.add '/bin/cp', '-f', %r{/tmp/.*}, base_path
|
|
||||||
Whitelist.add '/bin/chown', 'root:root', base_path
|
|
||||||
# - Template import
|
|
||||||
Whitelist.add '/bin/cp', %r{\\A.*\\z}, templates_path
|
|
||||||
Whitelist.add '/bin/cp', %r{\\A.*\\z}, templates_path
|
|
||||||
Whitelist.add '/bin/cp', %r{\\A.*\\z}, templates_path
|
|
||||||
Whitelist.add '/bin/chmod', '+x', templates_path
|
|
||||||
# - Template removal
|
|
||||||
Whitelist.add '/bin/rm', templates_path
|
|
||||||
# - Packaging
|
|
||||||
Whitelist.add '/bin/tar', '--numeric-owner', '-cvzf', %r{/tmp/.*/rootfs.tar.gz}, '-C', base_path, './rootfs'
|
|
||||||
Whitelist.add '/bin/chown', /\\A\\d+:\\d+\\z/, %r{\\A/tmp/.*/rootfs\.tar\.gz\\z}
|
|
||||||
|
|
||||||
##
|
|
||||||
# Commands from driver/cli.rb
|
|
||||||
Whitelist.add '/usr/bin/lxc-version'
|
|
||||||
Whitelist.add '/usr/bin/lxc-ls'
|
|
||||||
Whitelist.add '/usr/bin/lxc-info', '--name', /.*/
|
|
||||||
Whitelist.add '/usr/bin/lxc-create', '-B', /.*/, '--template', /.*/, '--name', /.*/, '**'
|
|
||||||
Whitelist.add '/usr/bin/lxc-destroy', '--name', /.*/
|
|
||||||
Whitelist.add '/usr/bin/lxc-start', '-d', '--name', /.*/, '**'
|
|
||||||
Whitelist.add '/usr/bin/lxc-stop', '--name', /.*/
|
|
||||||
Whitelist.add '/usr/bin/lxc-shutdown', '--name', /.*/
|
|
||||||
Whitelist.add '/usr/bin/lxc-attach', '--name', /.*/, '**'
|
|
||||||
Whitelist.add '/usr/bin/lxc-attach', '-h'
|
|
||||||
|
|
||||||
##
|
|
||||||
# Commands from driver/action/remove_temporary_files.rb
|
|
||||||
Whitelist.add '/bin/rm', '-rf', %r{\\A\#{base}/.*/rootfs/tmp/.*}
|
|
||||||
|
|
||||||
# Watch out for stones
|
|
||||||
Whitelist.run!(ARGV)
|
|
||||||
EOF
|
|
||||||
end
|
end
|
||||||
wrapper.close
|
wrapper.close
|
||||||
wrapper.path
|
wrapper.path
|
||||||
end
|
end
|
||||||
|
|
||||||
# REFACTOR: Make use ERB rendering after https://github.com/mitchellh/vagrant/issues/3231
|
|
||||||
# lands into core
|
|
||||||
def create_sudoers!(user, command)
|
def create_sudoers!(user, command)
|
||||||
sudoers = Tempfile.new('vagrant-lxc-sudoers').tap do |file|
|
sudoers = Tempfile.new('vagrant-lxc-sudoers').tap do |file|
|
||||||
file.puts "# Automatically created by vagrant-lxc"
|
file.puts "# Automatically created by vagrant-lxc"
|
||||||
|
@ -184,6 +75,15 @@ Whitelist.run!(ARGV)
|
||||||
}.flatten
|
}.flatten
|
||||||
system "echo \"#{commands.join("; ")}\" | sudo sh"
|
system "echo \"#{commands.join("; ")}\" | sudo sh"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_cmd_paths_hash
|
||||||
|
{}.tap do |hash|
|
||||||
|
%w( which cat mkdir cp chown chmod rm tar chown ).each do |cmd|
|
||||||
|
hash[cmd] = `which #{cmd}`.strip
|
||||||
|
end
|
||||||
|
hash['lxc_bin'] = Pathname(`which lxc-create`.strip).parent.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
110
templates/sudoers.rb.erb
Normal file
110
templates/sudoers.rb.erb
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#!/opt/vagrant/embedded/bin/ruby
|
||||||
|
# Automatically created by vagrant-lxc
|
||||||
|
|
||||||
|
class Whitelist
|
||||||
|
class << self
|
||||||
|
def add(command, *args)
|
||||||
|
list[command] << args
|
||||||
|
end
|
||||||
|
|
||||||
|
def list
|
||||||
|
@list ||= Hash.new do |key, hsh|
|
||||||
|
key[hsh] = []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def allowed(command)
|
||||||
|
list[command] || []
|
||||||
|
end
|
||||||
|
|
||||||
|
def run!(argv)
|
||||||
|
begin
|
||||||
|
command, args = `which #{argv.shift}`.chomp, argv || []
|
||||||
|
check!(command, args)
|
||||||
|
puts `#{command} #{args.join(" ")}`
|
||||||
|
exit $?.to_i
|
||||||
|
rescue => e
|
||||||
|
STDERR.puts e.message
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def check!(command, args)
|
||||||
|
allowed(command).each do |checks|
|
||||||
|
return if valid_args?(args, checks)
|
||||||
|
end
|
||||||
|
raise_invalid(command, args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_args?(args, checks)
|
||||||
|
return false unless valid_length?(args, checks)
|
||||||
|
check = nil
|
||||||
|
args.each_with_index do |provided, i|
|
||||||
|
check = checks[i] unless check == '**'
|
||||||
|
return false unless match?(provided, check)
|
||||||
|
end
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_length?(args, checks)
|
||||||
|
args.length == checks.length || checks.last == '**'
|
||||||
|
end
|
||||||
|
|
||||||
|
def match?(arg, check)
|
||||||
|
check == '**' || check.is_a?(Regexp) && !!check.match(arg) || arg == check
|
||||||
|
end
|
||||||
|
|
||||||
|
def raise_invalid(command, args)
|
||||||
|
raise "Invalid arguments for command #{command}, " <<
|
||||||
|
"provided args: #{args.inspect}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
base = "/var/lib/lxc"
|
||||||
|
base_path = %r{\A#{base}/.*\z}
|
||||||
|
templates_path = %r{\A/usr/(share|lib|lib64|local/lib)/lxc/templates/.*\z}
|
||||||
|
|
||||||
|
##
|
||||||
|
# Commands from provider.rb
|
||||||
|
# - Check lxc is installed
|
||||||
|
Whitelist.add '<%= cmd_paths['which'] %>', /\Alxc-\w+\z/
|
||||||
|
|
||||||
|
##
|
||||||
|
# Commands from driver.rb
|
||||||
|
# - Container config file
|
||||||
|
Whitelist.add '<%= cmd_paths['cat'] %>', base_path
|
||||||
|
# - Shared folders
|
||||||
|
Whitelist.add '<%= cmd_paths['mkdir'] %>', '-p', base_path
|
||||||
|
# - Container config customizations and pruning
|
||||||
|
Whitelist.add '<%= cmd_paths['cp'] %>', '-f', %r{/tmp/.*}, base_path
|
||||||
|
Whitelist.add '<%= cmd_paths['chown'] %>', 'root:root', base_path
|
||||||
|
# - Template import
|
||||||
|
Whitelist.add '<%= cmd_paths['cp'] %>', %r{\A.*\z}, templates_path
|
||||||
|
Whitelist.add '<%= cmd_paths['chmod'] %>', '+x', templates_path
|
||||||
|
# - Template removal
|
||||||
|
Whitelist.add '<%= cmd_paths['rm'] %>', templates_path
|
||||||
|
# - Packaging
|
||||||
|
Whitelist.add '<%= cmd_paths['tar'] %>', '--numeric-owner', '-cvzf', %r{/tmp/.*/rootfs.tar.gz}, '-C', base_path, './rootfs'
|
||||||
|
Whitelist.add '<%= cmd_paths['chown'] %>', /\A\d+:\d+\z/, %r{\A/tmp/.*/rootfs\.tar\.gz\z}
|
||||||
|
|
||||||
|
##
|
||||||
|
# Commands from driver/cli.rb
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-version'
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-ls'
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-info', '--name', /.*/
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-create', '-B', /.*/, '--template', /.*/, '--name', /.*/, '**'
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-destroy', '--name', /.*/
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-start', '-d', '--name', /.*/, '**'
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-stop', '--name', /.*/
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-shutdown', '--name', /.*/
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-attach', '--name', /.*/, '**'
|
||||||
|
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-attach', '-h'
|
||||||
|
|
||||||
|
##
|
||||||
|
# Commands from driver/action/remove_temporary_files.rb
|
||||||
|
Whitelist.add '<%= cmd_paths['rm'] %>', '-rf', %r{\A#{base}/.*/rootfs/tmp/.*}
|
||||||
|
|
||||||
|
# Watch out for stones
|
||||||
|
Whitelist.run!(ARGV)
|
Loading…
Reference in a new issue