Running Code as Another User

Problem

While writing a Ruby script that runs as root, you need to take some action on behalf of another user: say, run an external program or create a file.

Solution

Simply set Process.euid to the UID of the user. When you e done, set it back to its previous value (that is, roots UID). Heres a method Process.as_uid that runs a code block under a different user ID and resets it at the end:

	module Process
	 def as_uid(uid)
	 old_euid, old_uid = Process.euid, Process.uid
	 Process.euid, Process.uid = uid, uid
	 begin
	 yield
	 ensure
	 Process.euid, Process.uid = old_euid, old_uid
	 end
	 end
	 module_function(:as_uid)
	end

Discussion

When a Unix process tries to do something that requires special permissions (like access a file), the permissions are checked according to the "effective user ID" of the process. The effective user ID starts out as the user ID you used when you started the process, but if you e root you can change the effective user ID with Process.euid=. The operating system will treat you as though you were really that user.

This comes in handy when you e administering a system used by others. When someone asks you for help, you can write a script that impersonates them and runs the commands they don know how to run. Rather than creating files as root and using chown to give them to another user, you can create the files as the other user in the first place.

Heres an example. On my system the account leonardr has UID 1000. When run as root, this code will create one directory owned by root and one owned by leonardr:

	Dir.mkdir("as_root")
	Process.as_uid(1000) do
	 Dir.mkdir("as_leonardr")
	 %x{whoami}
	end
	# => "leonardr
"

Here are the directories:

	$ ls -ld as_*
	drwxr-xr-x 2 leonardr root 4096 Feb 2 13:06 as_leonardr/
	drwxr-xr-x 2 root root 4096 Feb 2 13:06 as_root/

When you e impersonating another user, your permissions are restricted to what that user can do. I can remove the as_root directory as a nonroot user, because I created it as root:

	Process.as_uid(1000) do
	 Dir.rmdir("as_root")
	end
	# Errno::EPERM: Operation not permitted - as_root
	
	Dir.rmdir("as_root") # => 0

On Windows, you can do something like this by splitting your Ruby script into two, and running the second one through runas.exe:

	# script_one.rb
	system 
unas /user:frednerk ruby script_two.rb

See Also

  • Recipe 6.2, "Checking Your Access to a File"
  • If you want to pass in the name of the user to impersonate, instead of their UID, you can adapt the technique shown in Recipe 23.10, "Killing All Processes for a Given User"


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Similar book on Amazon

Flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net