subprocess - Automate stdin with Python using stdin.write() -
i trying automate setup of generating self-signed ssl certificate. code:
#!/usr/bin/env python import subprocess pass_phrase = 'example' common_name = 'example.com' webmaster_email = 'webmaster@example.com' proc = subprocess.popen(['openssl', 'req', '-x509', '-newkey', 'rsa:2048', '-rand', '/dev/urandom', '-keyout', '/etc/pki/tls/private/server.key', '-out', '/etc/pki/tls/certs/server.crt', '-days', '180'], stdout=subprocess.pipe, stdin=subprocess.pipe, stderr=subprocess.pipe) in range(2): proc.stdin.write(pass_phrase) in range(5): proc.stdin.write('.') proc.stdin.write(common_name) proc.stdin.write(webmaster_email) proc.stdin.flush() stdout, stderr = proc.communicate()
when run it, still prompts me pem passphrase, returns error:
country name (2 letter code) [xx]:weird input :-( problems making certificate request
it should feed in passphrase above , not prompt me anything. ideas what's going wrong?
ps. know pexpect. please don't suggest me.
edit: upon further investigation, i've figured out. if don't specify -nodes, private key encrypted. so, openssl prompt pem passphrase immediately. means order of stdin.write() gets messed up. guess alternative use -nodes , encrypt private key later.
there several errors in code e.g., no newlines sent child process.
the main issue openssl
expects pass phrase directly terminal (like getpass.getpass()
in python). see first reason in why not use pipe (popen())?:
first application may bypass stdout , print directly controlling tty. ssh when asks password. why cannot redirect password prompt because not go through stdout or stderr.
pexpect
provides pseudo-tty works fine in case:
#!/usr/bin/env python import sys pexpect import spawn, eof pass_phrase = "dummy pass phr6se" common_name = "example.com" email = "username@example.com" keyname, certname = 'server.key', 'server.crt' cmd = 'openssl req -x509 -newkey rsa:2048 -rand /dev/urandom '.split() cmd += ['-keyout', keyname, '-out', certname, '-days', '180'] child = spawn(cmd[0], cmd[1:], timeout=10) child.logfile_read = sys.stdout # show openssl output debugging _ in range(2): child.expect('pass phrase:') child.sendline(pass_phrase) _ in range(5): child.sendline('.') child.sendline(common_name) child.sendline(email) child.expect(eof) child.close() sys.exit(child.status)
an alternative try use -passin
option instruct openssl
pass phrase different source (stdin, file, pipe, envvar, command-line). don't know whether works openssl req
command.
Comments
Post a Comment