Tony Arcieri wrote in post #955286:
I guess my question is what exactly are you trying to accomplish? Do you
want a small DSL of commands to work with files as root, or are you
expecting everything to be executed in the context of the setuid root
VM?
My immediate, practical need is to deal with files; but in the longer
term it would be nice to develop something more general, as I wrote in
my first post. Or something intermediate, as you will read later.
If it's the former, try this:
include FileUtils
cp "somefile", "anotherfile"
Actually this works fine:
# server.rb, run as root
# ...
DRb.start_service(URI, File)
# client.rb, non-root
# ...
module Sudo
File = DRbObject.new_with_uri(SERVER_URI)
end
puts Sudo::File.read '/etc/shadow' # only readable by root
It also works with FileUtils instead of Files and probably other classes
and modules.
But what if I want to distribute multiple classes/modules? In general,
what is the proper way to distribute multiple dRuby front objects?
The most obvious solution, to me, was an Array of objects as a front
object.
I tried this:
# server.rb
DRb.start_service(URI, [File, FileUtils])
# client.rb
module Sudo
File, FileUtils = DRbObject.new_with_uri(SERVER_URI)
end
but, again, It doesn't work:
client.rb:8:in `<module:Sudo>': can't convert DRb:
RbObject to Array
(DRb:
RbObject#to_ary gives DRb:
RbUnknown) (TypeError)
from client.rb:7:in `<main>'
So I am compelled to run several DRb server instances?
That should operate as expected. Beyond that, you would need to use
ParseTree or ripper to extract the Ruby code you want executed on the
remote
VM or something like that, but then you need to ensure that all the
classes/objects it's using are actually loaded on the new VM.
I see... looks like *a lot* of work...
For practicality's sake I'd suggest exposing a small DSL for doing what
you
want to do as root. FileUtils provides everything I'd think you need,
but
perhaps you have a use case I'm not envisioning.
As a more flexible alternative, you should be able to say if you want to
Sudo-ize FileUtils or other modules/classes.
A possible API might look like this:
Sudo.autoload :MyClass, 'mygem/myclass'
Sudo.require 'fileutils'
Sudo.enable :File, :FileUtils, :MyClass
my_super_object = Sudo::MyClass.new
Sudo::File.open ...
Sudo::FileUtils.cp
So you use superuser powers only explicitly when you really need them.