bash 使用easy rsa,如何自动化客户端/服务器创建过程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22415601/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:55:40  来源:igfitidea点击:

Using easy rsa, how to automate client / server creation process

bash

提问by mirx

I use easy rsa (https://github.com/OpenVPN/easy-rsa) to build my tiny ca and its clients / servers. Since its just for learning purposes, I was thinking about doing some automatization. Normally I can create files needed by client typing:

我使用简单的 rsa ( https://github.com/OpenVPN/easy-rsa) 来构建我的小型 ca 及其客户端/服务器。由于它只是为了学习目的,我正在考虑做一些自动化。通常我可以创建客户端键入所需的文件:

./easyrsa build-client-full client

./easyrsa build-client-full client

but what when I need ~ 500 different client files? cpits not what I want here.

但是当我需要大约 500 个不同的客户端文件时怎么办?cp这不是我想要的。

I tried to write a little bash script to help myself out:

我试着写一个小 bash 脚本来帮助自己:

#!/bin/bash

clients=3
pass=randompass
capass=castrongpassword

for i in `seq 1 $clients`
do
    ./easyrsa build-client-full test$i $pass $pass $capass
done

But it simply 'does not work'. When I build my client files in terminal I have to give 2 client passwords and the ca password. The main problem is I dont know how on earth pass it within script - is that possible? My script gives me Ignoring unknown command option:as output.

但它只是“不起作用”。当我在终端中构建我的客户端文件时,我必须提供 2 个客户端密码和 ca 密码。主要问题是我不知道到底如何在脚本中传递它 - 这可能吗?我的脚本给了我Ignoring unknown command option:作为输出。

回答by Joskar

Update (2020-04-03)

更新 (2020-04-03)

There has been some changes to EasyRSA script since I wrote the first answer.

自从我写下第一个答案以来,EasyRSA 脚本发生了一些变化。

  • EasyRSA 3.0.6 (released 2019-02-02) added --passinand --passoutoptions which correctly pass the options to OpenSSL as described in my original answer
  • EasyRSA 3.0.7 (released 2020-03-31) added the ability to supply the passwords through the EASYRSA_PASSINand EASYRSA_PASSOUTenvironment variables
  • 添加了 EasyRSA 3.0.6(2019-02-02 发布)--passin--passout正确将选项传递给 OpenSSL 的选项,如我的原始答案中所述
  • EasyRSA 3.0.7(发布2020年3月31日)增加通过提供密码的能力EASYRSA_PASSINEASYRSA_PASSOUT环境变量

Original answer

原答案

Reading through the easyrsa source code, it seems that the build-client-fullcommand only takes one argument: name. So, the error that you get is simply because it does not know what to do with the passwords you have added on the command line. I guess that the program asks you for these passwords interactively, so you mustsupply them to the program via stdin.

通读easyrsa源代码,该build-client-full命令似乎只需要一个参数:name. 因此,您得到的错误仅仅是因为它不知道如何处理您在命令行中添加的密码。我猜该程序会以交互方式要求您提供这些密码,因此您必须通过stdin.

Hacking easyrsa

黑客攻击 easyrsa

NOTE: OpenSSL (the backend of easyrsa) does not listen to stdinby default. To make it do so, we must add "-passout stdin"(since it is a password saved in an output file) to the OpenSSL command line. Alternatively, one could add "-passout file:passfile"if the passwords are kept in the file passfile'. To make it harder,easyrsa` does not have an easy way of adding arguments to the OpenSSL command. Thus, we must change the source code somehow. However, this is easy.

注意:默认情况下,OpenSSL(的后端easyrsa)不侦听stdin。为此,我们必须"-passout stdin"在 OpenSSL 命令行中添加(因为它是保存在输出文件中的密码)。或者,"-passout file:passfile"如果密码保存在文件中,则可以添加passfile'. To make it harder,easyrsa 没有一种简单的方法可以向 OpenSSL 命令添加参数。因此,我们必须以某种方式更改源代码。然而,这很容易。

To be able to use the alternatives below, add this into the gen_reqfunction of easyrsaafter the definition of local opts=:

为了能够使用下面的替代方案,将其添加到定义之后的gen_req函数easyrsalocal opts=

gen_req() {
    ....
    local opts=
    opts="-passout stdin" # ADD THIS LINE
    # Alternatively: opts="-passout file:passfile"
    ....
}

Also, it seems that OpenSSL closes the stdinstream after its first use (in gen_req), so it can't also be used for signing with the CA certificate (in sign_req). We can tell OpenSSL to read from a file instead of reading from stdin(it may also be used for the above)

此外,似乎 OpenSSLstdin在第一次使用(在gen_req)后关闭流,因此它也不能用于使用 CA 证书(在sign_req)进行签名。我们可以告诉 OpenSSL 从文件中读取而不是从文件中读取stdin(它也可以用于上述情况)

sign_req() {
    local crt_type="" opts=
    opts="-passin file:capassfile" # ADD THIS LINE (also: create capassfile)
    ...
}


(NOTE: The solutions below are kept mostly for future reference, in cases where multiple calls to OpenSSL is not involved...)

(注意:在不涉及多次调用 OpenSSL 的情况下,以下解决方案主要保留以供将来参考......)

"General solution" #1: Pipes

“通用解决方案”#1:管道

One way to pass passwords through stdin is to start a subshell and then pipe it to easyrsa, which would simulate the actual keypresses you would have done manually. Your example would then look like this:

通过 stdin 传递密码的一种方法是启动一个子 shell,然后将其通过管道传输到 easyrsa,这将模拟您手动完成的实际按键操作。您的示例将如下所示:

#!/bin/bash

clients=3
pass=randompass
#capass=castrongpassword   # (create the file 'capassfile' instead)

for i in `seq 1 $clients`
do
    (echo $pass; echo $pass) | ./easyrsa build-client-full test$i
done

Instead of creating a subshell, you could change the (echo $pass; echo ...)to

而不是创建一个子shell的,你可以改变(echo $pass; echo ...),以

printf '%s\n' $pass $pass | ./easyrsa build-client-full test$i

or

或者

echo -e "$pass\n$pass" | ./easyrsa build-client-full test$i

depending on what you find the most readable.

取决于您认为最易读的内容。

"General solution" #2: stdin redirection

“通用解决方案”#2:标准输入重定向

The above alternative has the drawback that the passwords will appear in process listings (such as ps), and is thus from a security standpoint a bad ideaif you are on a shared box. A better way would to create a file with the passwords, like this:

上述替代方案的缺点是密码将出现在进程列表中(例如ps),因此从安全角度来看,如果您在共享框中,这是一个坏主意。更好的方法是使用密码创建文件,如下所示:

randompass
randompass

Then, you invoke easyrsa in your loop above by simply writing:

然后,您只需编写以下代码即可在上面的循环中调用 easyrsa:

...
for i in `seq 1 $clients`
do
    ./easyrsa build-client-full test$i <passfile
done

where passfileis your file with the passwords. This of course assumes that you have the same password for all files.

passfile带密码的文件在哪里。这当然假设您对所有文件都有相同的密码。