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.
There has been some changes to EasyRSA script since I wrote the first answer.
--passin
and --passout
options which correctly pass the options to OpenSSL as described in my original answerEASYRSA_PASSIN
and EASYRSA_PASSOUT
environment variablesExample:
./easyrsa --passout=file:passfile --passin=file:capassfile build-client-full $cn
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
.
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...)
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.
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.
With a few steps and with openssl 1.1.1h& easyrsa3, I tried a similar solution which allows option -passin stdin
and/or -passout file:passfile
hardcode the option at function sign_req() line #834 in file easy-rsa/easyrsa3/easyrsa
. change opts=""
to opts="-passin stdin"
use this function to create cert a single client,
#function gen_full_client
gen_full_client() {
CN=$1
OVERWRITE=$2
#Generate client using cn and sign it
if [ -f "$EASYRSA_DIR/pki/private/$CN.key" ]; then
cat <<-EOF | sudo $EASYRSA gen-req $CN nopass
$OVERWRITE
$CN
EOF
else
cat <<-EOF | sudo $EASYRSA gen-req $CN nopass
$CN
EOF
fi
#give it some time
sleep 2
CA_PASSWORD=$3
#Generate client using cn and sign it
if [ -f "$EASYRSA_DIR/pki/private/$CN.key" ]; then
#cat <<-EOF | sudo $EASYRSA opts="-passout stdin" build-client-full $CN
cat <<-EOF | sudo $EASYRSA sign-req client $CN
yes
$(echo $CA_PASSWORD)
EOF
fi
}
a simple call would create a single client entry
gen_full_client $1 $2 "$3"
iterate it over your for loop with passwords and pass it to the function and voila! It's done.
for i in `seq 1 $clients`
do
gen_full_client test$i $pass $pass $capass
done
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With