From: Brian Candler Date: 2007-05-01T16:46:48+09:00 Subject: Re: run 'some' code as a different user? NET::SSH? On Tue, May 01, 2007 at 05:34:40AM +0900, John Clisham wrote: > Yes, I will authenticate useing their OS username and password. I > haven't used PTY.spawn before. Does it just spawn off a new psuedo > terminal? After doing a 'su -username' and authenicating; I want to > execute a block of ruby code as that user. I was thinking of something like this (untested): username = "foo" password = "bar" require 'pty' require 'expect' inp, out = PTY.spawn("su - #{username}") inp.expect /assword: / out.puts password inp.expect /\$ / out.puts "ruby /path/to/foo.rb" > Ideally that block would > return a ruby object that I could then manipulate in the broader app. That's more difficult, because your web server is running as one uid and the other part is running as a completely different uid, and therefore by definition must be in a separate process. You can run a DRb server in the child process, and have a DRb client (proxy) object in the web service. This will work fine, but DRb doesn't run over stdin/stdout, so you would have to bind each child process to a different port number. This isn't unsurmountable though. I think you can let DRb in the child pick a port number dynamically, and then send that number back over stdout (which you then pick up by reading the PTY) There's a DRb tutorial at http://wiki.rubygarden.org/Ruby/page/show/DrbTutorial which you may find useful. (Personal interest disclaimer: I wrote it :-) > (ie since this is a Rails app, I would execute controller code as the > authenticated user (ie to get job files); and use one set of views for > all users. It seems you have hit against the brick wall which many PHP hosting providers come across: namely, they want to run Apache with mod_php for efficiency, but they don't want one user's PHP scripts to be able to access or modify another user's files. Since Apache runs as a single user, and mod_php runs as that user, this turns out to be tricky. One solution is to run each user's applications as fastcgi scripts, where the users' code runs as a pool of separate processes running under their own uid. A similar solution is to give each user their own completely separate webserver instance (e.g. httpd), either bound to a separate IP, or bound to a separate port with a proxy in front which routes the incoming HTTP requests to the right webserver instance. In your case, this would effectively mean running multiple copies of your entire Rails app, one under each user ID. If the number of users you have is not large, this is probably a reasonable approach. You could do this statically, e.g. with webrick or mongrel (run a separate application instance for each user, bound to a separate port, running as their userid). Or, although I've not tried it myself, it should also be possible to run Rails under fastcgi with suexec or cgiwrap. The advantage of this approach is that when a user is no longer active, the webserver can completely kill off their Rails application instance. In both cases, the app would then take on responsibility for authenticating the user. Once they had authenticated, the controller would have rights to do whatever that user could do. Regards, Brian.