2016-08-01 19 views
3

我在嘗試驗證帶有CA包文件的證書。最初的Bash命令需要兩個像這樣的文件參數;運行帶有兩個字符串輸入的子進程命令

openssl verify -CAfile ca-ssl.ca cert-ssl.crt 

我試圖找出如何運行蟒子上面的命令,同時具有ca-ssl.ca和CERT-ssl.crt可變字符串(而不是文件)。

如果我在bash中用變量(而不是文件)運行命令,那麼這將工作;

ca_value=$(<ca-ssl.ca) 
cert_value=$(<cert-ssl.crt) 

openssl verify -CAfile <(echo "$ca_value") <(echo "$cert_value") 

不過,我掙扎弄清楚如何做上述與Python,最好是不需要使用shell=True。我已經嘗試了以下,但不起作用,而是打印openssl的「幫助」命令;

certificate = ''' cert string ''' 
ca_bundle = ''' ca bundle string ''' 

def ca_valid(cert, ca): 
    ca_validation = subprocess.Popen(['openssl', 'verify', '-CAfile', ca, cert], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=1) 
    ca_validation_output = ca_validation.communicate()[0].strip() 
    ca_validation.wait() 

ca_valid(certificate, ca_bundle) 

任何有關我需要進一步研究的指導/線索將不勝感激。

+0

作爲一個簡單的出路,你會考慮使用[tempfile](https://docs.python.org/3/library/tempfile.html)模塊嗎? – wim

+0

也許使用'os.system()'來代替? – baranskistad

+0

你確定你有這個命令嗎?當我運行直接在終端中創建的命令時,我也會得到openssl的使用幫助字符串。 – xgord

回答

-2

如果你想使用進程替換,你會使用shell=True。這是不可避免的。進程替換語法是bash語法;您只需調用bash即可解析並執行此類代碼。

此外,您必須確保bash被調用,而不是sh。在某些系統上,sh可能指的是舊的Bourne shell(與Bourne-again shell bash相反),在這種情況下,進程替換肯定不起作用。在某些系統上,sh將調用bash,但進程替換仍然不起作用,因爲在名稱sh下調用時,bash shell會輸入一種稱爲POSIX模式的內容。下面是從bash手冊頁的一些摘錄:

...

INVOCATION

...當作爲sh的時候,bash進入POSIX模式啓動文件被讀取後。 ....

...

另請參閱

...

http://tiswww.case.edu/~chet/bash/POSIX - 的POSIX模式

說明...

從上面的網頁鏈接:

  1. 過程替換不可用。

/bin/sh似乎是在Python默認的shell,您是否使用os.system()subprocess.Popen()。因此,如果要指定完整路徑,則必須指定參數executable='bash'executable='/bin/bash'

這是爲我工作:

subprocess.Popen('printf \'argument: "%s"\\n\' verify -CAfile <(echo ca_value) <(echo cert_value);',executable='bash',shell=True).wait(); 
## argument: "verify" 
## argument: "-CAfile" 
## argument: "/dev/fd/63" 
## argument: "/dev/fd/62" 
## 0 

下面是你實際上可以從變量嵌入字符串值:到底

bashEsc = lambda s: "'"+s.replace("'","'\\''")+"'"; 
ca_value = 'x'; 
cert_value = 'y'; 
cmd = 'printf \'argument: "%%s"\\n\' verify -CAfile <(echo %s) <(echo %s);'%(bashEsc(ca_value),bashEsc(cert_value)); 
subprocess.Popen(cmd,executable='bash',shell=True).wait(); 
## argument: "verify" 
## argument: "-CAfile" 
## argument: "/dev/fd/63" 
## argument: "/dev/fd/62" 
## 0 
1

猛砸進程替換<(...)提供的是一個文件路徑作爲參數openssl

您將需要一個輔助函數來創建此功能,因爲Python沒有說讓你管內聯數據到一個文件,並提交其路徑上的任何運營商:

import subprocess 
def validate_ca(cert, ca): 
    with filearg(ca) as ca_path, filearg(cert) as cert_path: 
     ca_validation = subprocess.Popen(
      ['openssl', 'verify', '-CAfile', ca_path, cert_path], 
      stdout=subprocess.PIPE, 
     ) 
     return ca_validation.communicate()[0].strip() 

filearg是上下文管理器,它用你想要的文本創建一個命名的臨時文件,關閉它,把路徑交給你,然後在with作用域結束後刪除它。

import os 
import tempfile 
from contextlib import contextmanager 

@contextmanger 
def filearg(txt): 
    with tempfile.NamedTemporaryFile('w', delete=False) as fh: 
     fh.write(txt) 
    try: 
     yield fh.name 
    finally: 
     os.remove(fh.name) 

訪問此臨時文件(如子進程)的任何內容都需要在上下文管理器中工作。

順便說一句,Popen.wait(self)冗餘,因爲Popen.communicate(self)等待終止。

相關問題