# Automatic CRL files converter

In my job we use our internal CA, which runs on a Windows server. When I want to use its CRL on a Linux machine I have to do these steps:

2. covert them to x509
3. merge into one file (CRL.pem)

For this I wrote the small script below, which I run automatically by timer unit (cron on systems without systemd) once a day.

#!/usr/bin/env bash

crls=(RootCA IntermediateCA IntermediateCA2)
new_crl="newcrl.pem"
crl_temp=$(mktemp -q -d /tmp/pullcrl.XXXXX) crl_dir="/etc/pki/tls/misc" for crl in${crls[@]}; do
if curl -s http://url_of_crls/${crl}.crl -o${crl_temp}/${crl}.crl; then openssl crl -in${crl_temp}/${crl}.crl -inform DER -out${crl_temp}/${crl}.pem else echo "Download a crl file failed!" exit 1 fi done cat${crl_temp}/*.pem > ${crl_temp}/${new_crl}

mv ${crl_temp}/${new_crl} ${crl_dir}/${new_crl}


Could I do something better?

for crl in ${crls[@]}; do  It's a good habit to always double-quote array expansions. Cleaning up the temp directory after a successful run would be a nice touch (or do away with it altogether; see below). cat${crl_temp}/*.pem > ${crl_temp}/${new_crl}
mv ${crl_temp}/${new_crl} ${crl_dir}/${new_crl}


I assume you're doing this to get atomic replacement? It only works if /tmp and /etc are on the same filesystem. If they're not, you could get an empty destination file when (for example) the target is full. Consider creating a working directory under /etc to be certain.

You could be more concise using cd and brace expansion and bash's own error handling (via set -euxo pipefail):

set -euxo pipefail

cd /etc/pki/tls/misc
temp=$( mktemp -p . ) for url in http://…blahblah…/{RootCA,IntermediateCA,IntermediateCA2}.crl ; do curl$url | openssl crl -in - -inform DER
done > $temp mv$temp newcrl.pem

• Hi, thanks a lot for the hints. Im using the rm cleaning at the end, just copy and paste issue. I thought about set -e, but I need to tell an other script, started on different time, that the result was failure - my mistake, I should have done the note about that in code. (I expect to that by writing a note into a file.). The other things looks really tasty :) Thanks again. – David Mosler Sep 16 at 17:29
• I like the part with curl and the pipe. It works fine in GNU bash, version 4.4.19(1)-release but in GNU bash, version 4.2.46(2)-release I got this error (23) Failed writing body. – David Mosler Sep 17 at 8:56
• that's not bash causing the failure. It's a different curl, or a different openssl, or a .curlrc exists that changes how curl works, or one of the two commands is aliased to have different behaviour. – Oh My Goodness Sep 17 at 15:56
• You are right, I found out it already. But due to that, isn't much more safely, just download all CLRs files and then convert them in separate way? Your example is pretty good, but I don't want to tune system by system that works. – David Mosler Sep 17 at 16:06
• Note that unchecked cd (without set -e) is a common dangerous anti-pattern. It's clear that you understand the importance, but might be worth pointing that up for passing readers! – Toby Speight Sep 18 at 14:45

I merge my previous code with hints provided by @Oh My Goodness.

• I excluded the variable clr_dir. The code thanks to is much more readable.
• And I moved temp dir to the same filesystem as is final destination of new CRL.
#!/usr/bin/env bash

set -euo pipefail
cd /etc/pki/tls/misc

crls=(RootCA IntermediateCA IntermediateCA2)
crl_temp=$(mktemp -p .) for crl in "${crls[@]}"; do
curl -s http://url_of_crls/crl/"${crl}".crl -o "${crl}".crl
openssl crl -in "${crl}".crl -inform DER rm -rf "${crl}".crl
done > "$crl_temp" mv "$crl_temp" CRL.pem


I omitted the pipe for curl due to problems which it caused on systems with curl version 7.29.0. (It works fine on version 7.58.0.)