Ability to run scripts as different user.

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

@ -8,8 +8,17 @@ import logging
import stat
import os
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):
"""
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
the output, depending on the output type.
"""
# FIXME: This doesn't really belong in FormCOnfig.
form = self.get_form_def(form_name)
# Validate params
@ -90,26 +100,54 @@ class FormConfig(object):
for key, value in form_values.items():
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
# the browser. Otherwise we store it for later displaying.
if form.output == 'raw':
proc = subprocess.Popen(form.script, shell=True,
stdout=stdout,
stderr=stderr,
env=env,
close_fds=True)
stdout, stderr = proc.communicate(input)
return proc.returncode
try:
proc = subprocess.Popen(form.script, shell=True,
stdout=stdout,
stderr=stderr,
env=env,
close_fds=True,
preexec_fn = run_as(uid, gid, groups))
stdout, stderr = proc.communicate(input)
return proc.returncode
except OSError as err:
self.log.exception(err)
stderr.write(str(err) + '. Please see the log file.')
return -1
else:
proc = subprocess.Popen(form.script, shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env,
close_fds=True)
stdout, stderr = proc.communicate()
return {
'stdout': stdout,
'stderr': stderr,
'exitcode': proc.returncode
}
try:
proc = subprocess.Popen(form.script, shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env,
close_fds=True,
preexec_fn = run_as(uid, gid, groups))
stdout, stderr = proc.communicate()
return {
'stdout': stdout,
'stderr': stderr,
'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,
output='escaped', hidden=False, submit_title="Submit",
allowed_users=None):
allowed_users=None, run_as='nobody'):
self.name = name
self.title = title
self.description = description
@ -29,6 +29,7 @@ class FormDefinition(object):
self.hidden = hidden
self.submit_title = submit_title
self.allowed_users = allowed_users
self.run_as = run_as
self.validate_field_defs(self.fields)

@ -115,7 +115,8 @@ class ScriptForm(object):
output=form.get('output', 'escaped'),
hidden=form.get('hidden', False),
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(

Loading…
Cancel
Save