How to configure user and password for neo4j cluster without REST API - neo4j

The version I use is neo4j-enterprise-2.2.0-M02
My question is :
How can I configure a user (like add a new user, change the password ,etc) in backend or browser, instead of REST API? Can I do it via neo4j-shell? imagine that I am a DBA, it is not very convenient to do this by REST API.
Any help will be greatly appreciated!

You can use the browser instead of the API. Just go to http://localhost:7474 (or whatever IP to which the web console is bound) and you will be prompted to change the password. Once authenticated, use the command :server change-password to change the password again.
It is not yet possible to create multiple user accounts within the system.
You can use the command :help server to see available authentication commands.

Although still utilizing the REST API, I'll throw the cURL option out there to anyone who doesn't have access to a web browser (AWS instance, for example):
$ curl -H "Content-Type: application/json" -X POST -d '{"password":"WHATEVER THE PASSWORD IS"}' -u neo4j:neo4j http://localhost:7474/user/neo4j/password

Another option is to modify the auth file directly and restart neo. Doing this, you can even change the username!
Run
find / -name dbms
For me this gave one hit:
/var/lib/neo4j/data/dbms/auth
Save this code as build_auth_string.sh:
#!/bin/bash
DEFAULT_IFS="$IFS"
SALT_LEN=32
# either read from stdin or use the argument
if [ -z "$1" ]; then
read INPUT
else
INPUT="$1"
fi
if [ -z "$INPUT" ]; then
echo "correct format <uname:pass>"
exit
fi
IFS=':'
read -a UNAME_PASS <<< "$INPUT"
UNAME="${UNAME_PASS[0]}"
PASS="${UNAME_PASS[1]}"
# representing the password in hex format like \xAB\x0C etc
# HEX_PASS=$(echo -n $PASS | xxd -p | awk '{print toupper($1);}' | sed -r 's/(.{2})/\\x\1/g')
HEX_PASS=$(echo -n $PASS | hexdump -v -e '"\\\x" 1/1 "%02X"')
# echo $HEX_PASS
# create the salt and store it in hex format
SALT=$(cat /dev/urandom | tr -dc 'a-f0-9' | fold -w $SALT_LEN | head -n 1)
# SALT="28FD26AD92D6D2D8820E969F3F3732B4"
HEX_SALT=$(echo -n $SALT | sed -r 's/(.{2})/\\x\1/g')
# calculate the sha256 sum of the salt and password value
# need to split the output because the output ends with a hyphen
IFS=' '
read -a PASSWORD_HASH_ARRAY <<< $(printf $HEX_SALT$HEX_PASS | sha256sum)
PASSWORD_HASH="${PASSWORD_HASH_ARRAY[0]}"
# echo "$UNAME;$PASS;$SALT"
# echo "$PASSWORD_HASH"
# and print out the auth string
COMBINED=$(echo -n "$PASSWORD_HASH,$SALT" | awk '{print toupper($1);}')
echo "$UNAME:SHA-256,$COMBINED:"
IFS="$DEFAULT_IFS"
The code for the above came from https://github.com/artsince/docker-neo4j-auth/blob/master/build_auth_string.sh - im posting it here just encase..
And then just run the above script like
build_auth_string.sh myUsername:myP#ssw0rd
Copy/paste that into your auth file replacing whatever was there before, and restart neo4j :)

A fresh install of Neo4j 2.2.x has a user 'neo4j', with an initial password 'neo4j'. You are required to change the password before you can do anything.
It's easy to do this from the command line, by calling httpie to interact with the REST API. For example, to set a new password of 'foobar', run this command:
http -a neo4j:neo4j POST http://localhost:7474/user/neo4j/password password=foobar

If you want to reset the password and you dont know the old password :
then for Windows user
go to this path:
C:\Users\xyz\Documents\Neo4j\default.graphdb\dbms
and delete that auth file.
Restart the neo4j they will again ask to set the username and password!!
by default
username:neo4j
password:neo4j

Currently it's not possible to configure authorization using neo4j-shell. As you've mentioned the REST API is the way to go. Using a convenient REST client this is very easy.
My tools of choice is either postman (a plugin for chrome browser) or httpie for the command line. E.g. with httpie changing the password for a user is as simple as:
http localhost:7474/user/neo4j/password password=neo4j new_password=mypass
Be aware that password (and other authorization settings) are not automatically distributed in a cluster, see the manual how to copy over settings between instances.

For Mac users, version 2.3.1 of Neo4J, best way to reset credentials is to remove the file with credential information and start the service again.
Steps to follow
Find where the file that contains credentials is located from the browser console (localhost:7474). Go to Star (Favourites)->System->Server configuration
Search for dbms.security.auth_store.location property to see where it points to. In my case it was /Users/felipe/Documents/Neo4j/default.graphdb/./dbms/auth
Delete that file.
Start the service again and go to the console again (localhost:7474).
By default you will be asked to set the password for the user neo4j.
I hope it helps.

To elaborate on felipe's response (since I do not have enough rep points to comment):
I stopped the server, I deleted the auth files in BOTH:
DBROOT\data\auth
DBROOT\dbms\auth
Restarted the server, and connected to it via the localhost:7474, used the default username/password (neo4j/neo4j) and then it prompted me for a new password.

On Neo4j 4.0+, you can run:
$ cypher-shell
If it's the first time you connect, you can enter neo4j as user and password and you will be prompted to set a new password.
If you want to change the password afterwards, you can write in the Cypher shell:
:server change-password

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.

How to force 'docker login' command to ignore existing credentials helper?

I have a system where I'm trying to run the docker logincommand, it is a headless linux system, but unfortunately only the Docker Credentials Helper docker-credential-secretservice is installed.
This means that I get the following error:
Error saving credentials: error storing credentials - err: exit status 1, out: `Cannot autolaunch D-Bus without X11 $DISPLAY`
It makes sense that I get this as:
By default, Docker looks for the native binary on each of the
platforms, i.e. “osxkeychain” on macOS, “wincred” on windows, and
“pass” on Linux. A special case is that on Linux, Docker will fall
back to the “secretservice” binary if it cannot find the “pass”
binary. If none of these binaries are present, it stores the
credentials (i.e. password) in base64 encoding in the config files
described above.
And since secretservice helper uses a GUI credentials store it tries to open a window, which it can't on the headless system.
I've no control over the system, so I can't remove the /usr/bin/docker-credential-secretservice file to force docker login to fall back to the config file rather than using the secretservice helper.
What I can do is create and list files in my user's home folder. I've tried to run the command as such:
docker --config ./docker login -u <user-name> -p <password> <repository>
I was under the impression that the login command would then create a config.json in the ./docker (I've noticed docker login will create the folder if it doesn't exist). This works on a system that doesn't have any helpers installed, but not on the system in question.
I've also tried to create a ~/.docker/config.json with something like:
echo '{"credStore":""}' > ~/.docker/config.json
Hoping that docker login would get the hint not to use any helpers for the credential store.
Is there a way for a non-admin to force docker login to fall back to:
stores the credentials (i.e. password) in base64 encoding in the config files described above.
Without deleting the credentials helper?
(as a side note, I'll of course ask to have the /usr/bin/docker-credential-secretservice removed but, in case it's not possible or for future reference, are there any alternative solutions?)
Logging out the current user, before logging in with a different user name worked for me. Logging out removed the saved docker credentials.
docker logout <reponame>
docker login <reponame>
To avoid using a credsStore and to store a plaintext auth token in your docker config (e.g. ~/.docker/config.json), delete the "credsStore" key from your docker config file and rerun docker login.
When you run docker login, it will give a warning but will save the auth token into the file.
$ docker login
Username: someuser
Password:
WARNING! Your password will be stored unencrypted in ~/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
The resulting docker config file should look like this:
{
"auths": {
"your.docker.registry": {
"auth": "dXNlcm5hbWU6cGFzc3dvcmQK="
}
}
}
The auth token is simply a base64 encoded string of the form username:password.
This worked for Docker Engine versions 19 and 20.
Unfortunately, Docker (as of 18.06) first looks for the docker-credential-* binaries, and if it finds any of them, it will automatically overwrite the "credsStore" value in ~/.docker/config.json.
Your only workaround would be to install docker-credential-pass in your home directory so that Docker will use that instead of docker-credential-secretservice. docker-credential-pass does not require a GUI.
Steps to install docker-credential-pass:
docker login fails on a server with no X11 installed
You can just ignore all the output by sending everything to /dev/null like:
echo $TOKEN|docker login -u=user --password-stdin myregistry.com > /dev/null 2>&1
where $TOKEN will be your previously exported token or password.
This will be useful as well with CI's when using some automation
I've looked through the code and there appears to be no way to generally disable the use of credential helpers. But you can skip the code path on a per-registry basis.
https://github.com/docker/cli/blob/25eee83d6b8c475548254b2decc9c8e0490d229c/cli/config/configfile/file.go#L308 will look up the helper to use (just the suffix after docker-credential-) in credHelpers from the registry host name. If it is "" it will use the normal unencrypted file store. As far as I can tell, this is undocumented and likely unintended behavior.
With that, in order to bypass the credential helpers for a specific registry, do
mkdir ./docker
echo "{\"credHelpers\": {\"$REGISTRY_HOST\": \"\"}}" > ./docker/config.json
docker --config ./docker login -u $USERNAME -p $PASSWORD $REGISTRY_HOST
I believe the cause why {"credsStore":""} isn't working is the omitempty serialization tag on that field. Setting it to empty is the same as not setting it.
Not an answer to the question, but maybe to the problem:
We can launch dbus ourselves then unlock/lock/query the keyring from the cli.
These are the bash functions I use:
function unlock-keyring () {
export $(dbus-launch)
read -rsp "Password: " pass
export $(echo -n "$pass" | gnome-keyring-daemon --unlock)
unset pass
}
function lock-keyring () {
dbus-send --dest=org.gnome.keyring --print-reply /org/freedesktop/secrets org.freedesktop.Secret.Service.LockService
}
function query-keyring-locked () {
busctl --user get-property org.freedesktop.secrets /org/freedesktop/secrets/collection/login org.freedesktop.Secret.Collection Locked
}
https://unix.stackexchange.com/questions/473528/how-do-you-enable-the-secret-tool-command-backed-by-gnome-keyring-libsecret-an
https://superuser.com/questions/700826/how-to-lock-a-unlocked-gnome-keyring
https://superuser.com/questions/1618970/query-status-of-gnome-keyring
https://unix.stackexchange.com/questions/602313/unlock-gnome-keyring-daemon-from-command-line
Simply rename ~/.docker/config.json to something different, or remove it if you won't need it anymore.
mv ~/.docker/config.json ~/.docker/backup-config.json

How to get Openshift session token using rest api calls

As part of an automated tests suite I have to use OpenShift's REST APIs to send commands and get OpenShift's status. To authenticate these API calls I need to embed an authorization token in every call.
Currently, I get this token by executing the following commands with ssh on the machine where OpenShift is installed:
oc login --username=<uname> --password=<password>
oc whoami --show-token
I would like to stop using the oc tool completely and get this token using HTTP calls to the APIs but am not really able to find a document that explains how to use it. If I use the option --loglevel=10 when calling oc commands I can see the HTTP calls made by oc when logging in but it is quite difficult for me to reverse-engineer the process from these logs.
Theoretically this is not something specific to OpenShift but rather to the OAuth protocol, I have found some documentation like the one posted here but I still find it difficult to implement without specific examples.
If that helps, I am developing this tool using ruby (not rails).
P.S. I know that normally for this type of job one should use Service Account Tokens but since this is a testing environment the OpenShift installation gets removed and reinstalled fairly often. This would force me to re-create the service account every time with the oc command line tool and again prevent me from automatizing the process.
I have found the answer in this GitHub issue.
Surprisingly, one curl command is enough to get the token:
curl -u joe:password -kv -H "X-CSRF-Token: xxx" 'https://master.cluster.local:8443/oauth/authorize?client_id=openshift-challenging-client&response_type=token'
The response is going to be an HTTP 302 trying to redirect to another URL. The redirection URL will contain the token, for example:
Location: https://master.cluster.local:8443/oauth/token/display#access_token=VO4dAgNGLnX5MGYu_wXau8au2Rw0QAqnwq8AtrLkMfU&expires_in=86400&token_type=bearer
You can use token or combination user/password.
To use username:password in header, you can use Authorizartion: Basic. The oc client commands are doing simple authentication with your user and password in header. Like this
curl -H "Authorization: Basic <SOMEHASH>"
where the hash is exactly base64 encoded username:password. (try it with echo -n "username:password" | base64).
To use token, you can obtain the token here with curl:
curl -H Authorization: Basic $(echo -n username:password | base64)" https://openshift.example.com:8443/oauth/authorize\?response_type\=token\&client_id\=openshift-challenging-client
But the token is replied in the ugly format format. You can try to grep it
... | grep -oP "access_token=\K[ˆ&]*"
You need to use the correct url for your oauth server. In my case, I use openshift 4.7 and this is the url:
https://oauth-openshift.apps.<clustername><domain>/oauth/authorize\?response_type\=token\&client_id\=openshift-challenging-client
oc get route oauth-openshift -n openshift-authentication -o json | jq .spec.host
In case you are using OpenShift CRC:
Then the URL is: https://oauth-openshift.apps-crc.testing/oauth/authorize
Command to get the Token:
curl -v --insecure --user developer:developer --header "X-CSRF-Token: xxx" --url "https://oauth-openshift.apps-crc.testing/oauth/authorize?response_type=token&client_id=openshift-challenging-client" 2>&1 | grep -oP "access_token=\K[^&]*"
Note:
2>&1 is required, because curl writes to standard error
--insecure: because I have not set up TLS certificate
Adjust the user and password developer as needed (crc developer/developer is standard user in crc, therefore good for testing.)
Token is per default 24h vaild
Export the Token to an environment Variable
export TOKEN=$(curl -v --insecure --user developer:developer --header "X-CSRF-Token: xxx" --url "https://oauth-openshift.apps-crc.testing/oauth/authorize?response_type=token&client_id=openshift-challenging-client" 2>&1 | grep -oP "access_token=\K[^&]*")
And Use the token then in, e.g., oc login:
oc login --token=$TOKEN --server=https://api.crc.testing:6443

How can I tell if I'm logged in to a private Docker registry from a script?

How can I tell whether or not I'm logged in to a private Docker registry server from a script? In other words, has docker login some.registry.com been run successfully (and is still valid)?
Note: I'm asking about an arbitrary private registry, not the docker.io registry.
if docker login worked, you will find a .docker folder on your home directory (~/.docker/), with a config.json file with credentials in it.
otherwise you would get an error login in.
Note: docker determine what credentials to use by looking at the registry name:
if you do
docker pull myregistry.com/myimage:tag
docker will look if you're logged in, and if not will check if you have the credentials for the registry myregistry.com and login with those.
If not you will get a permission error
This is a bit hacky, but it works in most of the cases for me:
if ! grep -q "my.private.registry.com" ~/.docker/config.json ; then
docker login "my.private.registry.com"
fi
Basically, you search if there is a record of "my.private.registry.com" in ~/.docker/config.json. However, if the session is expired, this check won't catch it.
I believe the error message will vary by registry implementation. However, my own technique is to pull an image that doesn't exist and parse any error message:
$!/bin/sh
repo="$1"
msg=$(docker pull ${repo}/missing:missing 2>&1)
case "$msg" in
*"requested access to the resource is denied"*|*"pull access denied"*)
echo "Logged out";;
*"manifest unknown"*|*"not found"*)
echo "Logged in, or read access for anonymous allowed";;
*"Pulling from"*)
echo "Missing image was not so missing after all?";;
*)
echo "Unknown message: $msg";;
esac
This has been tested with the docker standalone registry and docker_auth. You'll want to test with registries that you may encounter.
If your registry server allows anonymous pulls and you want to verify a push is possible, you can create a dummy empty image and replace the pull with a push of that image. E.g.
#!/bin/sh
repo=$1
# note, I do not like the "." here, better to change it to an empty directory
# see "mktemp" for an option if you cannot make your own empty directory somewhere
docker build -t "${repo}/empty:test" -f - . <<EODF
FROM scratch
EODF
msg=$(docker push "${repo}/empty:test" 2>&1)
rc=$?
if [ "$rc" = "0" ]; then
echo "Access granted to push"
else
case "$msg" in
*"requested access to the resource is denied"*)
echo "Access denied";;
*)
echo "Unknown error message: $msg";;
esac
fi
If you are constrained to examining your local system, it's impossible to know!
... The only way to be sure the credentials docker has stored are still valid is to perform an operation that will cause them to be presented to the registry, and to see if the registry accepts them.
If you want to use the docker CLI to get an answer, then you could use #matanper suggestion of "login again" which will complete automatically if you still have valid credentials.
Another way is to try to pull an image known not to exist, which will show different error message when logged in or not e.g.
# NO VALID LOGIN:
$ docker pull 999999999999.dkr.ecr.us-west-2.amazonaws.com/this/image:does_not_exist
Error response from daemon: pull access denied for 999999999999.dkr.ecr.us-west-2.amazonaws.com/this/image, repository does not exist or may require 'docker login'
versus
# WITH VALID LOGIN:
$ docker pull 999999999999.dkr.ecr.us-west-2.amazonaws.com/this/image:does_not_exist
Error response from daemon: manifest for 999999999999.dkr.ecr.us-west-2.amazonaws.com/this/image:does_not_exist not found
(presume that you didn't want to pull because you don't want any delay or large data tranfser, so the above method is still 'ok')
In the past, when docker always stored credentials in ~/.docker/config.json (or equivalent for your OS), you could parse that file to get the currently stored credentials and then run a simple list operation using curl or similar. However, recent docker versions store the credentials in host OS specific stores (e.g. the keychain on Mac OS X) so that is no longer a portable methodology. If portability is not important, you could still try something like that - the hash in config.json is just the base64 encoded username & password, separated by a colon, as is standard for HTTP basic auth e.g. on linux, with jq to parse JSON, and base64 to decode base64:
$ cat ~/.docker/config.json | jq -r '.auths["registry.example.com"].auth' | base64 -d
username:password
So, completing that with a registry list operation using curl:
REGISTRY="registry.example.com"
CREDENTIALS="$(cat ~/.docker/config.json | jq -r ".auths[\"${REGISTRY}\"].auth" | base64 -d)"
curl -sSf --max-time 3 --user "${CREDENTIALS}" "https://${REGISTRY}/v2/_catalog"
will return exit code zero, and a JSON response if the CREDENTIALS are good; or a non-zero exit code if not
{
"repositories": [
"jamesjj/test-image",
"jamesjj/other-image",
...
...
}
NOTE: When parsing the JSON, the registry address key may or may not include the schema https://, depending on how the original login was performed, so cat ~/.docker/config.json | jq -r ".auths[\"${REGISTRY}\"].auth" | base64 -d)"
... may need to be:
cat ~/.docker/config.json | jq -r ".auths[\"https://${REGISTRY}\"].auth" | base64 -d)"
This is a little hacky, I think until docker will have a command to check login, there won't be any good solution.
You can in your bash script try to login with timeout of x seconds, if you aren't logged in the command will try to prompt for username and then it will timeout with status 124. If you are indeed logged in, it will just log you in again using the save credentials and continue with status 0
#!/bin/bash
timeout -s SIGKILL 3s docker login some.registry.com >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo Logged In!
else
echo Not logged in...
fi
This is somewhat old, but I needed the same thing today. I found
this question first, and from that, I derived this, which I think answers the OP's question directly:
# try to login. If you are logged in, it exits happily. If you aren't, it prompts
# for credentials. By redirecting stdin to /dev/null, we guarantee this fails
docker login ${MY_REG} < /dev/null >& /dev/null
if [ $? -eq 0]; then
echo "Already logged in"
else
echo "Login required"
fi
If MY_REG is unset, it will check against docker.io. Otherwise, against the registry you set.
I do understand that there is a difference between storing credentials and authenticating with the registry, and perhaps that's an important nuance in the OP's use case. In my case, I just wanted to know the former. If the latter is important, then by all means, pull an image.
You can parse .docker/config.json and try to manually connect to each registry specified in the file. The file contains the registry address and encoded username and password so you can script this process. You can do that using a library like docker-registry-client.
pip install docker-registry-client
And then:
import base64
import docker_registry_client
import json
import os.path
def get_authed_registries():
result = []
config_path = os.path.expanduser("~/.docker/config.json")
if not os.path.isfile(config_path):
print("No docker config")
return []
docker_config = json.load(open(config_path))
for registry, auth in docker_config.get("auths", {}).items():
username, password = base64.b64decode(auth["auth"]).decode("utf-8").split(":", 1)
if not registry:
registry = "https://index.docker.io/v1/"
if not registry.startswith("http"):
registry = "https://" + registry
try:
rc = docker_registry_client.DockerRegistryClient(registry, username=username, password=password)
result.append(registry)
except Exception, e:
print(registry, "failed:", e)
return result
get_authed_registries()
A few caveats:
This may fail if you're using a credential store.
Tested on Python 2.7. Might need small adjustments for Python 3.
This code works for authentication, but any further actions on the registry fail. You will need to strip away API version (/v1, /v2, etc.) from the host name for that.
The code assumes all registries are HTTPS (unless specified otherwise in config.json)
An even more correct version will probably strip away anything but the hostname and try both v1 and v2.
That said, I was able to get a list of logged-in registries and it correctly ignored expired ECR login.
When you do the
Docker login <private registry> -u <user> -p <password>
command from your terminal, you will have a response: (stored in $?)
0
Login Succeeded
if you were successful.
In your shell script, you could just look at the response you're receiving, if it does not equal 0, you've failed to login.
sudo docker login <registry> -u <uname> -p <password>
if [ $? -ne 0 ]; then
echo Login failed!
else
echo Login OK!
fi

Execute a sudo command in Ruby on Rails app

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.

Resources