1

I use OpenVPN at my company and am trying to automate user creation process. There's a problem at the certificate generation step I faced now. When trying to build a key for the user (all parameters are predefined) program has to press Enter multiple times and in the end "y" and "Enter" 2 times. I tried using Popen and PIPE, but no luck so far. Would appreciate any insight.

import sys, os
from subprocess import Popen, PIPE
# Generate an .ovpn file

try:
    username = sys.argv[1]
except:
    print "Error. Supply a username!"
    sys.exit()

print("Adding user")
os.system("useradd" + " -m" + " -s" + " /bin/bash" + username)
print("Sourcing vars")
os.system('source + /home/myuser/openvpn-ca/vars')
enter = Popen(['/home/myuser/openvpn-ca/build-key {}'.format(username)]), 
stdin=PIPE, shell=True)
enter.communicate(input='\n')

Edit:

This is different than what it was marked [duplicate] for. Here's why:

I don't need to generate a custom certificate, change any values etc. It just needs to press "Enter" multiple times and input "yes" and "Enter" 2 times.

yusif
  • 13
  • 5
  • Haven't tried this myself, but what happens if you put `time.sleep(x)` in between `enter.communicate(input='\n')`s, where `x` is a number of seconds to sleep? – sbbs Mar 11 '19 at 06:00
  • It raises an error. ./pkitool not found, /home/myuser/whichopensslcnf: not found. Also, subprocess raises errors in communicate and _stdin_write. – yusif Mar 11 '19 at 06:29
  • Your code only supplies a single newline, what happens if you put two? This is probably a duplicate of another question, though at this time I am reluctant to reopen it more because it is unclear. Can you please [edit] your question to indicate what happens if you put two newlines, with a pause between them if the client program requires it? – tripleee Mar 11 '19 at 06:31
  • It returns: ./pkitool: 293: can't shift that many waits for the amount of time I provided and the exits – yusif Mar 11 '19 at 07:07
  • Seems vaguely unrelated: https://askubuntu.com/questions/812299/error-building-openvpn-key – tripleee Mar 11 '19 at 08:46
  • Shouldn't you have a space after `/bin/bash`? – tripleee Mar 11 '19 at 08:47
  • @tripleee Key-building is fine. I do it manually often enough. That's exactly why I want to write this code to do the job for me. Adding user works fine, the build-key part is the one I'm having trouble with. – yusif Mar 11 '19 at 10:21

1 Answers1

0

You cannot source a shell script from Python; or rather, you can, but it will simply start a new subprocess which sources something and then disappears, without changing anything in your Python environment or subsequent subprocesses.

Try something like this instead:

import sys
import logging   # to get diagnostics on standard error instead
import subprocess

# Maybe switch to level=logging.WARNING once you are confident this works
logging.basicConfig(level=logging.INFO, format='%(module)s:%(asctime)s:%(message)s')

try:
    username = sys.argv[1]
except:
    logging.error("Error. Supply a username!")
    sys.exit()

logging.info("Adding user")
subprocess.run(["useradd", "-m", "-s", "/bin/bash", username],
    check=True, universal_newlines=True)
logging.info("Building key")
subprocess.run('''
        source /home/myuser/openvpn-ca/vars
        /home/myuser/openvpn-ca/build-key {}'''.format(username),
    shell=True, check=True, input='\n\n', universal_newlines=True)

The switch to subprocess.run() requires a reasonably new version of Python 3. In older versions, subprocess.check_call() would do roughly the same thing, but didn't have an input= argument, so you really did have to use the basic Popen() for this.

Additional notes:

  • The plus sign after source was obviously a syntax error
  • We use check=True throughout to make sure Python checks that the commands finish successfully.
  • Mixing os.system() with subprocess is not an error, but certainly a suspicious code smell.

(Much) more about using subprocess on U*x here: https://stackoverflow.com/a/51950538/874188

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thanks for the link! I've never thought about using subprocess before. I can't see the part of pressing "Enter" multiple times on signing certificate prompt. That's the piece of code I'm curious about. – yusif Mar 12 '19 at 05:39
  • 1
    `input='\n\n'` passes two newlines as standard input to the subprocess. If it doesn't blindly accept stdin, you need something like `pexpect`. – tripleee Mar 12 '19 at 07:57