5

I have a general question about system administration scripts that require "some" commands to be executed with root access, and other as a normal non-root user (ie myusername, etc.). I should mention I'm using Ruby 1.8.6 on a Linux Red Hat 4 system. The suggestions I've seen so far are:

  1. Allow access from sudoers:
    USERNAME = NOPASSWD: /path/to/script, /etc/init.d/httpd, /path/to/somethingelse
    Is this syntax correct? If so, am I correct that I would want to list all the specific commands needed in the script where I did not want to be prompted for password?

  2. Set suid
    http://www.wellho.net/mouth/733_Perl-for-Systems-Admin-suid-scripts.html
    To run a Perl script with root privilage:
    a) Set the owner of the script to root
    b) Set the suid bit on the file on (chmod u+s filename)
    c) Turn off read permission, and on execute permission to the file to everyone except root (chmod go=x)
    But other research suggests that you can only set suid on binaries for later Linux systems (my script will actually run on an older version of RH4 but we may end up upgrading so I'd like to be forward compatible). I don't think I want to create a binary just for this!

  3. 'Use ssh with generated public/private keys. The key can be configured to allow only certain commands to be execute with it.'

  4. Leave in sudo for any scripted commands that require root:
    system 'sudo rake ts:rebuild' (of course this has the drawback of having all those password prompts!)

  5. Execute script as root
    But what about commands I want ran as a normal user?

  6. Execute as root su username (for tasks that need to be ran as the normal user)
    'Run script as root, do a bunch of tasks as root, su newUser do a bunch of tasks as newUser, exit (exits back to the root user) do a bunch more tasks as root.' (proposed by James below)

I feel ashamed to not have a better grasp of this topic, but I'm a bit surprised at how many Ruby "scripting books" I referred to that do not address this! I guess it's more of a 'nix thing, but it seems that to do any thing of substantial use, you'd likely run into this.

Edit: Some things like mysql I can use options in the command like --password so I've used this to do that:

puts "Remote Password: "
system('stty -echo')
password = STDIN.gets.chomp
puts "Mysql Password (local): "
mysql_local_password = STDIN.gets.chomp
system('stty echo')

And then I can use those passwords from within the script but they never get seen as clear text. But this doesn't work for everything of course.

The other thing I should mention is that there commands that need to be ran as different users (in addition to just root and one normal user, there may be a 'build' user, etc.,etc)

Question: Please help me to understand the pros and cons of these (and any other proposed or better solutions). Also, if there's a definitive book, links, man pages, etc., that addresses how scripts interact with the underlying system's permissions that you can refer me to that would be great as well.

Thanks all!

Rob
  • 203
  • 2
  • 9

6 Answers6

5

Yes, you can su to any user in a script as root without requiring a password. This is a bit of a hack, but it will work. You might have some hiccups along the way (your environment changes when you su, for instance), but you'll be able to make it work. I don't think it's "right". Also, root can do everything, so you can always find a way to do everything as root.

I recommend using sudo for everything.

For interactive stuff, sudo with password prompts is OK. I prefer it to prompt you for your own password, not root's. This way you can grant limited administrative rights without giving away root's password (and thus, full privileges). Having to type your password is good for the "hey! I'm typing my password, this means I'm doing something potentially dangerous, let's check before I type". You can also set sudo not to prompt repeatedly for passwords (i.e. once you type it in, sudo invocations within n minutes do not prompt).

Also, you can make sudo let a user perform any action as root, not just a limited set of commands. I use this on boxes I admin; it's nicer than "su -", gives you some audit stuff out of the box, you can always "sudo -i" (or "-s", sometimes) to get a root shell, etc.

For noninteractive stuff, there's more choice.

I'm not very fond of suid binaries. This should be used only for very commonly used binaries which need root privileges, which are very simple and which have been thoroughly audited. ping, for instance, requires root privileges to do its work. However, any security flaw in a suid binary is potentially very dangerous.

Using ssh is a very complex way of achieving this.

Use sudo, set it up to not require a password for the specific commands the script requires. "man sudoers" is a long read, but definitely interesting- there's so much stuff you can do with sudo...

alex
  • 1,329
  • 6
  • 9
2

I'd go with #4:

Leave in sudo for any scripted commands that require root: system 'sudo rake ts:rebuild'

You don't need to worry too much about repeated password prompts; sudo will cache the fact that you authenticated with a password for a short while (around 5 minutes by default. From the man page:

Once a user has been authenticated, a timestamp is updated and the user may then use sudo without a password for a short period of time (5 minutes unless overridden in sudoers).

from man sudoers:

timestamp_timeout

Number of minutes that can elapse before sudo will ask for a passwd again. The default is 5. Set this to 0 to always prompt for a password. If set to a value less than 0 the user's timestamp will never expire. This can be used to allow users to create or delete their own timestamps via sudo -v and sudo -k respectively.

So as long as the script is going to take <5 minutes to run, the user should only see one password prompt - none at all if they've authenticated recently.

James Polley
  • 2,089
  • 15
  • 13
2

Did you ever looked into things like capistrano, puppet, ansible or chef for your tasks?

You don't mention what's the scope of you work is, so I have no idea if they are of any use to you.

I would avoid "suid" at any cost. There is no point of using it having sudo installed, which seems to be the best choice for your requirements of running commands with different permissions/user ids ('sudo -u user2 command2', etc) .

Also you might want to run some sudo commands password-less as permitted commands in you key-based ssh session (ssh sshkeyaccessonlyuser@yourhost 'sudo command'). This can take care of the caching problem if you don't want to have longer password caches in sudo, and your script will not finish running a sudo command in time.

Jonathan
  • 252
  • 1
  • 13
monomyth
  • 971
  • 1
  • 5
  • 9
1

I'd go sudo aswell, with solution 1 and 5. Note that you can also use aliases to make your setup cleaner, such as:

Cmnd_Alias RUBY_TOOLS = /path/to/cmnd1, /path/to/cmnd2, etc.
Cmnd_Alias RUBY_TOOLS_NPW = /path/to/cmnd3
User_Alias RUBY_USERS = user1, user2, etc.
User_Alias RUBY_SPECIAL_USERS = root
RUBY_USERS ALL=(RUBY_SPECIAL_USERS) RUBY_TOOLS, NOPASSWD: RUBY_TOOLS_NPW

The rule will restrict the access to the RUBY_TOOLS command(s) as user(s) RUBY_SPECIAL_USERS, and use no password for RUBY_TOOLS_NPW.

Sudo is very flexible. You can also play with Host_Alias to specify hosts on which to apply the rules. If you need to automate the generation of your sudo rules, you can use Augeas for that.

The only downsides of this method that I see are:

  1. sudo is required on the machine (kind of obvious)
  2. you need to call sudo when everytime you want a script to be executed

One way around the 2nd issue is to setup a SUCMD variable in your configuration, and use it in front of all your exec calls. By default, SUCMD will be sudo, but you could set it to 'su' later if you wish to user another system, or just to nothing if you wish to not use a SUCMD and setup your system with setuid or group privileges.

raphink
  • 11,337
  • 6
  • 36
  • 47
0

I'd like to say that first of all, I'm not familiar with ruby at all as it seems to be an unconventional choice as a language for admin tasks. Looking at the options listed below, 5 seems like the best choice. If any part of your script needs root permissions, I would say that running the script requires root permission.

Give all the choices above, I didn't see the the option of running the script as root and just running "su username" before running commands as the user. It has the benefit of not requiring password prompts (don't need password permissions as root) and it should fulfill all your needs.

Run script as root, do a bunch of tasks as root, su newUser do a bunch of tasks as newUser, exit (exits back to the root user) do a bunch more tasks as root.

  • 5
    Ruby is a common language for system administration tasks. – womble Dec 25 '09 at 22:31
  • Actually, when I do this: su user; system 'command'; exit; it actually exits the script instead of returning to root user. I don't have root so I have to do sudo bash before running so perhaps that's the problem for me using this approach. – Rob Dec 28 '09 at 15:44
  • Try su root; system 'command'; su user; –  Jan 08 '10 at 18:52
  • You're not familiar with Ruby *because* it's unconventional, or you think it's unconventional because you're unfamiliar with it? :) –  Apr 21 '10 at 08:35
0

There is another method here which I have used from time to time. If you really don't want a password, and don't want to depend on sudo, you could use a wrapper suid script which then calls your script. "sudo" has its advantages, but sometimes it is harder to use than a simple wrapper, say from a cron job or as PART of another script.

I had to do this in my web log processing. A script running as a normal user would mv the log files out of the way, then it called a suid script to send a HUP to apache to make it re-open the new log files. Only the HUP needed to run as root, so only that part was suid.

Michael Graff
  • 6,588
  • 1
  • 23
  • 36