Issue
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:
./easyrsa build-client-full client
but what when I need ~ 500 different client files? cp
its not what I want here.
I tried to write a little bash script to help myself out:
#!/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.
Solution
Update (2020-04-03)
There has been some changes to EasyRSA script since I wrote the first answer.
- EasyRSA 3.0.6 (released 2019-02-02) added
--passin
and--passout
options 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_PASSIN
andEASYRSA_PASSOUT
environment variables
Example:
./easyrsa --passout=file:passfile --passin=file:capassfile build-client-full $cn
Original answer
Reading through the easyrsa source code, it seems that the build-client-full
command 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 must supply them to the program via stdin
.
Hacking easyrsa
NOTE: OpenSSL (the backend of easyrsa
) does not listen to stdin
by
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.
To be able to use the alternatives below, add this into the gen_req
function of easyrsa
after the definition of local opts=
:
gen_req() {
....
local opts=
opts="-passout stdin" # ADD THIS LINE
# Alternatively: opts="-passout file:passfile"
....
}
Also, it seems that OpenSSL closes the stdin
stream 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)
sign_req() {
local crt_type="$1" 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...)
"General solution" #1: Pipes
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:
#!/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
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
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 idea if you are on a shared box. A better way would to create a file with the passwords, like this:
randompass
randompass
Then, you invoke easyrsa in your loop above by simply writing:
...
for i in `seq 1 $clients`
do
./easyrsa build-client-full test$i <passfile
done
where passfile
is your file with the passwords. This of course assumes that you have the same password for all files.
Answered By - Joskar Answer Checked By - Pedro (WPSolving Volunteer)