Ability to run scripts as different user.

pull/7/head
Ferry Boender 9 years ago
parent ddfdf3c053
commit 901e0d5938
  1. 42
      src/formconfig.py
  2. 3
      src/formdefinition.py
  3. 3
      src/scriptform.py

@ -8,8 +8,17 @@ import logging
import stat import stat
import os import os
import subprocess import subprocess
import pwd
import grp
def run_as(uid, gid, groups):
def set_acc():
os.setgroups(groups)
os.setgid(gid)
os.setuid(uid)
return set_acc
class FormConfigError(Exception): class FormConfigError(Exception):
""" """
Default error for FormConfig errors Default error for FormConfig errors
@ -77,6 +86,7 @@ class FormConfig(object):
callback should be written. The output of the script is hooked up to callback should be written. The output of the script is hooked up to
the output, depending on the output type. the output, depending on the output type.
""" """
# FIXME: This doesn't really belong in FormCOnfig.
form = self.get_form_def(form_name) form = self.get_form_def(form_name)
# Validate params # Validate params
@ -90,26 +100,54 @@ class FormConfig(object):
for key, value in form_values.items(): for key, value in form_values.items():
env[key] = str(value) env[key] = str(value)
# Get the user uid, gid and groups we should run as
pw = pwd.getpwnam(form.run_as)
gr = grp.getgrgid(pw.pw_gid)
groups = [g.gr_gid for g in grp.getgrall() if pw.pw_name in g.gr_mem]
uid = pw.pw_uid
gid = pw.pw_gid
msg = "Running script as user={0}, gid={1}, groups={2}"
self.log.info(msg.format(pw.pw_name, gr.gr_name, str(groups)))
if os.getuid() != 0:
self.log.error("Not running as root! Running as different user "
"will probably fail!")
# If the form output type is 'raw', we directly stream the output to # If the form output type is 'raw', we directly stream the output to
# the browser. Otherwise we store it for later displaying. # the browser. Otherwise we store it for later displaying.
if form.output == 'raw': if form.output == 'raw':
try:
proc = subprocess.Popen(form.script, shell=True, proc = subprocess.Popen(form.script, shell=True,
stdout=stdout, stdout=stdout,
stderr=stderr, stderr=stderr,
env=env, env=env,
close_fds=True) close_fds=True,
preexec_fn = run_as(uid, gid, groups))
stdout, stderr = proc.communicate(input) stdout, stderr = proc.communicate(input)
return proc.returncode return proc.returncode
except OSError as err:
self.log.exception(err)
stderr.write(str(err) + '. Please see the log file.')
return -1
else: else:
try:
proc = subprocess.Popen(form.script, shell=True, proc = subprocess.Popen(form.script, shell=True,
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
env=env, env=env,
close_fds=True) close_fds=True,
preexec_fn = run_as(uid, gid, groups))
stdout, stderr = proc.communicate() stdout, stderr = proc.communicate()
return { return {
'stdout': stdout, 'stdout': stdout,
'stderr': stderr, 'stderr': stderr,
'exitcode': proc.returncode 'exitcode': proc.returncode
} }
except OSError as err:
self.log.exception(err)
return {
'stdout': '',
'stderr': 'Internal error: {0}. Please see the log ' \
'file.'.format(str(err)),
'exitcode': -1
}

@ -19,7 +19,7 @@ class FormDefinition(object):
""" """
def __init__(self, name, title, description, fields, script, def __init__(self, name, title, description, fields, script,
output='escaped', hidden=False, submit_title="Submit", output='escaped', hidden=False, submit_title="Submit",
allowed_users=None): allowed_users=None, run_as='nobody'):
self.name = name self.name = name
self.title = title self.title = title
self.description = description self.description = description
@ -29,6 +29,7 @@ class FormDefinition(object):
self.hidden = hidden self.hidden = hidden
self.submit_title = submit_title self.submit_title = submit_title
self.allowed_users = allowed_users self.allowed_users = allowed_users
self.run_as = run_as
self.validate_field_defs(self.fields) self.validate_field_defs(self.fields)

@ -115,7 +115,8 @@ class ScriptForm(object):
output=form.get('output', 'escaped'), output=form.get('output', 'escaped'),
hidden=form.get('hidden', False), hidden=form.get('hidden', False),
submit_title=form.get('submit_title', 'Submit'), submit_title=form.get('submit_title', 'Submit'),
allowed_users=form.get('allowed_users', None)) allowed_users=form.get('allowed_users', None),
run_as=form.get('run_as', 'nobody'))
) )
form_config = FormConfig( form_config = FormConfig(

Loading…
Cancel
Save