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
How to Manage Multiple Gemsets and Ruby Versions with Rvm
How to Get Parent Node in Capybara
How to Create a Ruby Date Object from a String
Convert String to Specific Datetime Format
How to Make the Class Constructor Private in Ruby
Nicely Formatting Output to Console, Specifying Number of Tabs
How to Create a Delete Link for a Related Object in Ruby on Rails
Ruby/Rails CSV Parsing, Invalid Byte Sequence in Utf-8
How to Get Constants Defined by Ruby's Module Class via Reflection
Ruby Loading Config (Yaml) File in Same Dir as Source
How to Read a Password from the Command Line in Ruby
When to Call a "Require" in Rails
Rails Fields_For Form Not Showing Up, Nested Form
Adding a Staging Environment to the Workflow
How to Install Ruby on Rails 3 on Osx
Ruby Greed Koan - How to Improve My If/Then Soup
Is Every Relavant Calculation Performed Every Time the Page Is Loaded