How to Read a Password from the Command Line in Ruby

How can I read a password from the command line in Ruby?

To answer my own question, and for the benefit of anyone else who would like to know, there is a Ruby gem called HighLine that you need.

require 'rubygems'
require 'highline/import'

def get_password(prompt="Enter Password")
ask(prompt) {|q| q.echo = false}
end

thePassword = get_password()

How to hide password input from terminal in ruby script

Best method from @eclectic923's answer:

require 'io/console'
password = STDIN.noecho(&:gets).chomp

For 1.9.3 (and above), this requires you adding require 'io/console' to your code.

Original Answer:

Ruby "Password" is another alternative.

Passing variable from Ruby as a password for shell

For security reasons, sudo doesn't accept passwords on standard input by default. You should configure your sudoers file with a NOPASSWD: tag for the commands you want to execute without prompting, and invoke sudo with the -n flag to ensure that your script doesn't get hung up waiting for input.

If you insist on passing in passwords, see if your sudo supports the -S flag, which (on my system) says:

   -S          The -S (stdin) option causes sudo to read the password from
the standard input instead of the terminal device. The
password must be followed by a newline character.

How do you prompt for a sudo password using Ruby?

In my opinion, running a script that does stuff internally with sudo is wrong. A better approach is to have the user run the whole script with sudo, and have the script fork lesser-privileged children to do stuff:

# Drops privileges to that of the specified user
def drop_priv user
Process.initgroups(user.username, user.gid)
Process::Sys.setegid(user.gid)
Process::Sys.setgid(user.gid)
Process::Sys.setuid(user.uid)
end

# Execute the provided block in a child process as the specified user
# The parent blocks until the child finishes.
def do_as_user user
unless pid = fork
drop_priv(user)
yield if block_given?
exit! 0 # prevent remainder of script from running in the child process
end
puts "Child running as PID #{pid} with reduced privs"
Process.wait(pid)
end

at_exit { puts 'Script finished.' }

User = Struct.new(:username, :uid, :gid)
user = User.new('nobody', 65534, 65534)

do_as_user(user) do
sleep 1 # do something more useful here
exit! 2 # optionally provide an exit code
end

puts "Child exited with status #{$?.exitstatus}"
puts 'Running stuff as root'
sleep 1

do_as_user(user) do
puts 'Doing stuff as a user'
sleep 1
end

This example script has two helper methods. #drop_priv takes an object with username, uid, and gid defined and properly reduces the permissions of the executing process. The #do_as_user method calls #drop_priv in a child process before yielding to the provided block. Note the use of #exit! to prevent the child from running any part of the script outside of the block while avoiding the at_exit hook.

Often overlooked security concerns to think about:

  • Inheritance of open file descriptors
  • Environment variable filtering
  • Run children in a chroot?

Depending on what the script is doing, any of these may need to be addressed. #drop_priv is an ideal place to handle all of them.



Related Topics



Leave a reply



Submit