107 lines
4.1 KiB
Diff
107 lines
4.1 KiB
Diff
|
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
|
||
|
|