I have build a function, which calls sudo commands from python, because I don’t want to run every command as sudo (I am pulling in the process data from a repo, which I control, but this could be an angle of attack I wanted to mitigate):
streamer = SysStreamer
def _logable_sudo(cmds: List[str], password: str) -> List[str]:
sudo_cmds = ["sudo", "-S"]
sudo_cmds.extend(cmds)
streamer.stream_command(
sudo_cmds,
stdout_handler=self.streamer.stdout_handler,
stdin=PIPE,
password=password,
)
return streamer.stdout_lines
Where SysStreamer
is the following class:
class SysStreamer:
def __init__(self) -> None:
self.flush_stdout_cache()
self.logger = load_logger(__name__)
def flush_stdout_cache(self):
self.stdout_lines = []
def stream_command(
self,
args,
*,
stdout_handler=logging.info,
check=True,
text=True,
stdin=None,
stdout=PIPE,
stderr=STDOUT,
password=None,
**kwargs,
):
"""Mimic subprocess.run, while processing the command output in real time."""
with Popen(args, text=text, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs) as process:
if password:
process.stdin.write(f"{password}n")
process.stdin.flush()
for line in process.stdout:
stdout_handler(line[:-1])
retcode = process.poll()
if check and retcode:
raise CalledProcessError(retcode, f"{process.args}:Check Logs!")
return CompletedProcess(process.args, retcode)
def stdout_handler(self, line):
self.logger.info(line)
self.stdout_lines.append(line)
The SysStreamer
is just a workaround to have access to the return values of the process and also save them for other use cases.
The Issue I have with this approach, that I need to gather the Password myself and having it in plaintext visible while debugging.
So my first intention was to use the systems sudo
call instead of requesting the password earlier before the sudo
call and I think it would be the best approach. The only thing what is worrying me: What if I need to call a second sudo
call later, and the sudo-timer has reseted?
I had this issue with this specific workflow in the past and I needed to run the complete workflow again to verify that the system is in the actual needed state.
So my final question: How should I handle sudo
and help the process not to reset the sudo-timer, while my script is still running?