0

I've written a small custom REST service that runs via a python3 wsgi app under gunicorn, and is managed on the system via an upstart init script. (The host is ubuntu 14.04.1). The service is a git post-commit hook, which I'll call git-hook here for simplicity.

The service is deployed via a jenkins pipeline, and the deploy job does a stop/update/start sequence, as the account release, to update the files and restart the service.

The problem is that when the jenkins job gets to the step where it runs

sudo service stop git-hook 

it appears to fail at that step and the deploy is aborted. This is what the job is supposed to do if a command fails, but it's not 100% visible what exactly the failure was, only that something went wrong while trying to run that step.

Here's what I know:

The service works

  • The service itself runs 100% correctly and as expected, provided I execute the init commands interactively with a (non-root) admin account, which has basically full sudo permissions. Specifically, the command is sudo /usr/sbin/service git-hook start|stop

The service won't start or stop as the release user

  • The 'release' account has been given limited sudo access to run the same start|stop commands for this service, but when I try either one interactively as the release account, it always fails with the message git-hook: unrecognized service

The sudo rule appears to work (at least as far as the 'sudo' functionality is concerned)

  • When running the start|stop as any user, the system logs the sudo command, but doesn't give any indication that it has failed (though functionally it always fails for the release user)
  • When I instead run a sudo command that release does not have access for, it does correctly fail to a password prompt, and sudo logs that the command is not allowed.
  • The sudoer file is syntactically valid, checked with visudo.
  • The same sudoer file has other rules for this user, and those work fine, so I at least know it's loading correctly.

Permissions seem correct

  • The 'release' account owns all the hook service application files, as it needs full write to deploy new code
  • The www-data user also has equivalent read/write perms via membership in a common group that owns the application files. This is because the actual wsgi application runs as the www-data user.

Here is the sudoers rule, implemented as a separate file in /etc/sudoers.d/:

Host_Alias  TOOLS = tools??.*.ourdomain.com

Cmnd_Alias  RELEASE_GITHOOK_SERVICE =\
    /usr/sbin/service git-hook stop,\
    /usr/sbin/service git-hook start

release TOOLS = NOPASSWD:\
    RELEASE_GITHOOK_SERVICE

And here is the upstart init file, /etc/init/git-hook.conf, which has has perms: -rw-r--r-- and ownership root:root

description "git-hook service"

start on (filesystem)
stop on runlevel [016]

respawn
setuid www-data
setgid deploy

env APPHOME="/var/www/git_hook"
env GUNICORN="/var/www/git_hook/venv/bin/gunicorn"
env HOSTNAME="0.0.0.0"
env PORT="5000"

script
    chdir $APPHOME
    exec $GUNICORN --workers 4 --bind $HOSTNAME:$PORT hook:app
end script

So the question is, why does the init command work fine under one account and not under the other? It would seem to have some connection to the more restrictive sudo rules, however it appears the sudo call actually is successful, so maybe something it calls is what fails. Is there some other, implied command that /usr/sbin/service runs that I also need a rule for? Or some other access permission I'm missing?

  • What is the output of which initctl and initctl version when run by the release user? – zwets Aug 8 '18 at 21:03
  • Asking this because /usr/sbin/service is just a wrapper script isolating you from sysvinit, upstart, and systemd. But as you know that your service is an upstart thingy (because you put it there), there's no point in being generic. Just invoke initctl stop git-hook directly, and allow this for user release in sudoers. I'm quite sure that will solve your issue. – zwets Aug 8 '18 at 21:15
  • looks like that may have been the problem, more or less. /sbin/ is not in the path for the release user, so it can't find initctl – Christopher Hunter Aug 8 '18 at 21:50
  • Furthermore, running sudo /sbin/initctl stop git-hook directly seems to do the right thing, but it'll take me a bit to run the necessary changes to allow that. – Christopher Hunter Aug 8 '18 at 22:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.