ipa/0003-Add-runas-option-to-run-function.patch

107 lines
4.1 KiB
Diff
Raw Normal View History

From b4791862852770711be87ca63ed85b23e72baea3 Mon Sep 17 00:00:00 2001
From: Martin Kosek <mkosek@redhat.com>
Date: Thu, 16 Jan 2014 14:10:42 +0100
Subject: [PATCH 3/9] Add runas option to run function
Run function can now run the specified command as different user by
setting the both real and effective UID and GID for executed process.
Add both the missing run function attribute doc strings as well as
a doc string for the runas attribute.
---
ipapython/ipautil.py | 59 +++++++++++++++++++++++++++++++++-------------------
1 file changed, 38 insertions(+), 21 deletions(-)
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 92569c3b487bdbbfc4f0033813fda56c8928f20c..f7a2443af940a695321da7989457a392d6451d44 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -42,6 +42,7 @@
import netaddr
import time
import krbV
+import pwd
from dns import resolver, rdatatype
from dns.exception import DNSException
@@ -246,29 +247,35 @@ def shell_quote(string):
return "'" + string.replace("'", "'\\''") + "'"
def run(args, stdin=None, raiseonerr=True,
- nolog=(), env=None, capture_output=True, skip_output=False, cwd=None):
+ nolog=(), env=None, capture_output=True, skip_output=False, cwd=None,
+ runas=None):
"""
Execute a command and return stdin, stdout and the process return code.
- args is a list of arguments for the command
-
- stdin is used if you want to pass input to the command
-
- raiseonerr raises an exception if the return code is not zero
-
- nolog is a tuple of strings that shouldn't be logged, like passwords.
- Each tuple consists of a string to be replaced by XXXXXXXX.
-
- For example, the command ['/usr/bin/setpasswd', '--password', 'Secret123', 'someuser']
-
- We don't want to log the password so nolog would be set to:
- ('Secret123',)
-
- The resulting log output would be:
-
- /usr/bin/setpasswd --password XXXXXXXX someuser
-
- If an value isn't found in the list it is silently ignored.
+ :param args: List of arguments for the command
+ :param stdin: Optional input to the command
+ :param raiseonerr: If True, raises an exception if the return code is
+ not zero
+ :param nolog: Tuple of strings that shouldn't be logged, like passwords.
+ Each tuple consists of a string to be replaced by XXXXXXXX.
+
+ Example:
+ We have a command
+ ['/usr/bin/setpasswd', '--password', 'Secret123', 'someuser']
+ and we don't want to log the password so nolog would be set to:
+ ('Secret123',)
+ The resulting log output would be:
+
+ /usr/bin/setpasswd --password XXXXXXXX someuser
+
+ If a value isn't found in the list it is silently ignored.
+ :param env: Dictionary of environment variables passed to the command.
+ When None, current environment is copied
+ :param capture_output: Capture stderr and stdout
+ :param skip_output: Redirect the output to /dev/null and do not capture it
+ :param cwd: Current working directory
+ :param runas: Name of a user that the command shold be run as. The spawned
+ process will have both real and effective UID and GID set.
"""
p_in = None
p_out = None
@@ -298,9 +305,19 @@ def run(args, stdin=None, raiseonerr=True,
root_logger.debug('Starting external process')
root_logger.debug('args=%s' % arg_string)
+ preexec_fn = None
+ if runas is not None:
+ pent = pwd.getpwnam(runas)
+ root_logger.debug('runas=%s (UID %d, GID %s)', runas,
+ pent.pw_uid, pent.pw_gid)
+
+ preexec_fn = lambda: (os.setregid(pent.pw_gid, pent.pw_gid),
+ os.setreuid(pent.pw_uid, pent.pw_uid))
+
try:
p = subprocess.Popen(args, stdin=p_in, stdout=p_out, stderr=p_err,
- close_fds=True, env=env, cwd=cwd)
+ close_fds=True, env=env, cwd=cwd,
+ preexec_fn=preexec_fn)
stdout,stderr = p.communicate(stdin)
stdout,stderr = str(stdout), str(stderr) # Make pylint happy
except KeyboardInterrupt:
--
1.8.5.3