Execute a sudo command in Ruby on Rails app - ruby-on-rails

I am trying to execute a command like this from a Ruby on Rails app:
sudo service squid3 restart
If i try it with this code:
output = ´sudo service squid3 retsart´
It don't work, in the console i see that linux asks the password.
How can i pass a password with this command? Or other suggestions...

You can add the following line to your sudoers file (/etc/sudoers)
rails_user ALL=(root) NOPASSWD:/usr/sbin/service
This will basically let the rails_user user execute the service command as sudo, and the system won't ask you for a password.
rails_user should be replaced with whatever user that you are running your rails process under. And you should also make sure that
Defaults requiretty
is not present in your /etc/sudoers. If not you won't be able use sudo from a script.

You can try the sudo -S flag if available on you system (check man):
echo secretPasswd | sudo -S service squid3 restart
This means that the password will be in clear so you can add the user which needs to perform the task to the sudoers (which creates another security issue by the way).

Does your sudo have a -A switch?
-A
Normally, if sudo requires a password, it will read it from the current terminal. If the -A (askpass) option is specified, a helper program is executed to read the user's password and output the password to the standard output. If the SUDO_ASKPASS environment variable is set, it specifies the path to the helper program. Otherwise, the value specified by the askpass option in sudoers(5) is used.
I wouldn't recommend having the password available in any way to your web server processes though so you'd want to use the sudoers file.

You can use the expect method to catch the password prompt and send the password. However, it might be a better idea to allow your Rails user access to the service command without a password using the NOPASSWD option in /etc/sudoers.

Related

How to call "mysql" with STDIN redirection from inside Rails

I am trying to use redirection to load a SQL database schema using:
system("mysql -p -h db.server.local -u admin -D some_db < schema.sql")
I expect it to prompt for a password, and it works correctly when run from IRB. However, when run via Rails' runner it fails
as if I had hit the Enter key at the password prompt. In Rails console it looks like this:
pry(main)> system("mysql -p -h db.server.local -u admin -D some_db < schema.sql")
Enter password: ERROR 1045 (28000): Access denied for user 'admin'#'mylocalpc' (using password: NO)
It did not give me a chance to enter the password. When I removed the redirection (<), it correctly prompts for a password. So it appears that somehow, when run via Rails, the STDIN redirection is disrupting the password prompt. I tried with backticks and had the same issue.
I assume that the mysql executable must be using some magic so that the STDIN redirection does not disrupt the password prompt, but it appears to be broken when the executable is launched via Rails.
Is Rails overriding System() and if so, is there some way to call the real System()?
Does anyone have other ideas of how to work around this, or what could be happening here?
The mysql executable is skipping the request for a password because in order to except stdin for the password, the command needs to be executed with TTY enabled. Ruby system command and backticks do not execute the command using a TTY enabled interface to the underlying system. There are a couple gems that allow for TTY enabled execution on the command line, I would check out the tty-command gem if you’d like to force the command prompt to ask for the password.
Though for the ideal solution that I would suggest, since you’re executing the command from within Rails, you should have access to Rails.credentials. I would store the necessary credentials (username and password) for the database within the credentials store, and use this to populate the -u and -P flag values for the mysql command. This will avoid the need to prompt for the password entirely.

jenkins execute shell over ssh hangs when using "sudo su"

The field Exec command of execute shell over ssh, I only put command sudo su in there.
But when I build the project, it always stop at the command sudo su till timeout.
The image show what I get in console output.
Welcome to StackOverflow.
sudo
sudo is used for custom installations, system files modification, etc
Interactive shells (human in front of monitor)
When you exec some command preceded by sudo, this shell will ask you for the password of some privileged user. This ask event waits for user response:
Background executions
Some process, crons, scripts or applications like jenkins needs to execute sudo commands. But in this mode , there is no way to enter the password. This is the reason of your timeout
Solutions
disable requiretty
https://gist.github.com/jrichardsz/1adaaa07885b45d497b519431701a943
Security risk of this approach:
https://unix.stackexchange.com/a/65789/188975
use a pseudo TTY in Jenkins
https://unix.stackexchange.com/a/373843/188975
You can try using the expect directive.

Could not login with bash shell by default

I want to run a Ruby on Rails application. When I tried to run it, it shows me this,
The program 'rails' is currently not installed. You can install it by typing:
sudo apt install ruby-railties
So, I figured out the problem and I found that the problem is due to not login into bash shell. My terminal could not execute 'ruby' or 'ruby on rails' scripts. I checked .bashrc and .bash_profile files if PATH variable is set to point to rvm file.
When I did,
/bash/bin -l
it shows me ruby or rails are installed on system and I could start Rails server successfully. But if I opened another Terminal window, same problem occurs. Basically, I want to log into bash shell by default. Please correct and help me to sort out this. Thanks!
If you are sure the location of your bash shell is /bin/bash you could use this command (replacing "username" with your username):
chsh -s /bin/bash username
That will change your default shell in most unix like operating systems.
Afterwards you can verify it checking /etc/passwd where you will see the default shell at the end of the line of your username.
Warning: Try it first with a new user, in order to avoid losing your shell access if the path to bash is different :-)

Non-privileged, non-root, user to start or restart webserver server such as nginx without root or sudo

I'm using capistrano to deploy a rails web app. I want to give the deploy user on the webserver as few privileges as I can. I was able to do everything I need to do as a non-privileged user except restart the webserver.
I'm doing this on an ubuntu server, but this problem is not specific to my use case (rails, capistrano, deployment), and I've seen a lot of approaches to this problem that seem to involve poor security practices. Wondering whether others can vet my solution and advise whether it's secure?
First, not necessary, but I have no idea why /etc/init.d/nginx would need any (even read) access by other users. If they need to read it, make them become root (by sudo or other means), so I:
chmod 750 /etc/init.d/nginx
Since the ownership is owner root, group root (or can be set such with chown root:root /etc/init.d/nginx) only root, or a user properly sudo'ed, can read, change or run /etc/init.d/nginx, and I'm not going to give my deploy user any such broad rights. Instead, I'm only going to give the deploy user the specific sudo right to run the control script /etc/init.d/nginx. They will not be able to run an editor to edit it, because they will only have the ability to execute that script. That means that if a someone gets access to my box as the deploy user, they can restart and stop, etc, the nginx process, but they cannot do more, like change the script to do lots of other, evil things.
Specifically, I'm doing this:
visudo
visudo is a specific tool used to edit the sudoers file, and you have to have sudoer privileges to access it.
Using visudo, I add:
# Give deploy the right to control nginx
deploy ALL=NOPASSWD: /etc/init.d/nginx
Check the sudo man page, but as I understand this, the first column is the user being given the sudo rights, in this case, “deploy”. The ALL gives deploy access from all types of terminals/logins (for example, over ssh). The end, /etc/init.d/nginx, ONLY gives the deploy user root access to run /etc/init.d/nginx (and in this case, the NOPASSWD means without a password, which I need for an unattended deployment). The deploy user cannot edit the script to make it evil, they would need FULL sudo access to do that. In fact, no one can unless they have root access, in which case there's a bigger problem. (I tested that the user deploy could not edit the script after doing this, and so should you!)
What do you folks think? Does this work? Are there better ways to do this? My question is similar to this and this, but provides more explanation than I found there, sorry if it's too duplicative, if so, I'll delete it, though I'm also asking for different approaches.
The best practice is to use /etc/sudoers.d/myuser
The /etc/sudoers.d/ folder can contain multiple files that allow users to call stuff using sudo without being root.
The file usually contains a user and a list of commands that the user can run without having to specify a password. Such as
sudo service nginx restart
Note that we are running the command using sudo. Without the sudo the sudoers.d/myuser file will never be used.
An example of such a file is
myuser ALL=(ALL) NOPASSWD: /usr/sbin/service nginx start,/usr/sbin/service nginx stop,/usr/sbin/service nginx restart
This will allow the myuser user to call all start, stop and restart for the nginx service.
You could add another line with another service or continue to append them to the comma separated list, for more items to control.
Also make shure you have run the command below to secure things
chmod 0440 /etc/sudoers.d/myuser
This is also the way I start and stop services my own created upstart scripts that live in /etc/init
It can be worth checking that out if you want to be able to run your own services easily.
Instructions:
In all commands, replace myuser with the name of your user that you want to use to start, restart, and stop nginx without sudo.
Open sudoers file for your user:
$ sudo visudo -f /etc/sudoers.d/myuser
Editor will open. There you paste the following line:
$ myusername ALL=(ALL) NOPASSWD: /usr/sbin/service nginx start,/usr/sbin/service nginx stop,/usr/sbin/service nginx restart
Save by hitting ctrl+o. It will ask where you want to save, simply press enter to confirm the default. Then exit out of the editor with ctrl+x.

can not run sudo in a rails resque worker

I have a resque worker which will run some shell command.
for example
ruby
`sudo echo "XXX" >> xx.log`
but when worker run, will raise below error
sudo: no tty present and no askpass program specified
I have add 'whoami' debug code to find which user run this sudo command,
and also set this user's group "test" when execute command will don't need password.
I'm also run same command in shell console, it works right, don't need input password.
sudo visudo
%test ALL=NOPASSWD:ALL
but when the worker run sudo, will says above error, require input password.
Who can tell me why?
Thanks.
I am really hesitant to offer this as a "fix" because #AJcodez asks correctly, "why do you need sudo?" However, you can probably get around the tty requirement by adding the following:
Defaults requiretty
Defaults: %test !requiretty
to the /etc/sudoers file, but please use the visudo command. Also, is test here a user or a group? I also suspect that your sudoers line is malformed. The syntax is:
jane ALL=(LIST_OF_COMMANDS) NOPASSWD: ALL
Where you seem to have it set to run the NOPASSWD setting for all zero commands the %test group can run. Or I could be misunderstanding your paste here.

Resources