mirror of
https://github.com/outbackdingo/labca.git
synced 2026-01-27 10:19:34 +00:00
Replace openssl certificate / CRL generation with the tool as used by Let's Encrypt, storing the keys on SoftHSMv2, a simulated HSM (Hardware Security Module). Include migration of old setups where key files were also stored on disk.
313 lines
11 KiB
Bash
Executable File
313 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
LOGFILE=/opt/logs/commander.log
|
|
|
|
err_report() {
|
|
echo "ERROR! On line $1 in commander script"
|
|
}
|
|
|
|
trap 'err_report $LINENO' INT TERM ERR
|
|
|
|
dn=$(dirname $0)
|
|
source "$dn/utils.sh"
|
|
|
|
function wait_server() {
|
|
local url="$1"
|
|
|
|
local status=0
|
|
local cnt=0
|
|
|
|
set +e
|
|
res=$(curl -o /dev/null -sSLk --head --write-out '%{http_code}\n' $url 2>&1)
|
|
if [ $? -ne 0 ]; then
|
|
echo -n $res
|
|
fi
|
|
set -e
|
|
while [ $cnt -lt 40 ] && [ "$status" != "200" ]; do
|
|
status=$(curl -o /dev/null -sSL --head --write-out '%{http_code}\n' $url 2>>$LOGFILE)
|
|
let cnt=$cnt+1
|
|
if [ "$status" != "200" ]; then
|
|
sleep 5
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
read txt
|
|
case $txt in
|
|
"docker-restart")
|
|
cd /opt/boulder
|
|
COMPOSE_HTTP_TIMEOUT=120 docker compose restart boulder bmysql bconsul bpkilint gui nginx &>>$LOGFILE
|
|
sleep 45
|
|
wait_up $PS_MYSQL &>>$LOGFILE
|
|
wait_up $PS_CONSUL 2 &>>$LOGFILE
|
|
wait_up $PS_PKILINT &>>$LOGFILE
|
|
wait_up $PS_LABCA &>>$LOGFILE
|
|
wait_up $PS_BOULDER $PS_BOULDER_COUNT &>>$LOGFILE
|
|
;;
|
|
"acme-request")
|
|
wait_up $PS_BOULDER $PS_BOULDER_COUNT &>>$LOGFILE
|
|
cd /etc/nginx/ssl
|
|
[ -e account.key ] || openssl genrsa 4096 > account.key
|
|
[ -L labca_key.pem ] || mv labca_key.pem labca_key_rsa.pem
|
|
[ -e labca_key_rsa.pem ] || openssl genrsa 4096 > labca_key_rsa.pem
|
|
[ -e labca_key_ecdsa.pem ] || openssl ecparam -name secp384r1 -genkey -out labca_key_ecdsa.pem
|
|
|
|
set +e
|
|
curve_count=$(openssl pkey -pubin -in /opt/boulder/labca/certs/webpki/issuer-01-pubkey.pem -text | grep -i curve | wc -l)
|
|
set -e
|
|
[ "$curve_count" == "0" ] && ln -sf labca_key_rsa.pem labca_key.pem || /bin/true
|
|
[ "$curve_count" != "0" ] && ln -sf labca_key_ecdsa.pem labca_key.pem || /bin/true
|
|
|
|
if [ -e labca_cert.pem ]; then
|
|
if [ ! -e domain.csr ]; then
|
|
san=$(openssl x509 -noout -text -in labca_cert.pem | grep DNS:)
|
|
openssl req -new -utf8 -sha256 -key labca_key.pem -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=$san")) > domain.csr
|
|
fi
|
|
|
|
hash=$(openssl x509 -hash -noout -in labca_cert.pem)
|
|
issuer_hash=$(openssl x509 -issuer_hash -noout -in labca_cert.pem)
|
|
fi
|
|
if [ "$hash" == "$issuer_hash" ] || ! expires=$(openssl x509 -checkend 172800 -noout -in labca_cert.pem); then
|
|
url=$(grep 'DEFAULT_DIRECTORY_URL =' /opt/labca/acme_tiny.py | sed -e 's/.*=[ ]*//' | sed -e 's/\"//g')
|
|
wait_server $url
|
|
sleep 10
|
|
/opt/labca/renew
|
|
|
|
sleep 5
|
|
cd /opt/boulder
|
|
docker compose exec -i boulder ./bin/boulder crl-updater --config labca/config/crl-updater.json -runOnce -debug-addr :18021
|
|
/opt/labca/checkcrl
|
|
fi
|
|
|
|
ln -sf /opt/labca/cron_d /etc/cron.d/labca
|
|
ln -sf /opt/labca/logrotate_d /etc/logrotate.d/labca
|
|
;;
|
|
"acme-change")
|
|
read fqdn
|
|
cd /etc/nginx/ssl
|
|
[ -L labca_key.pem ] || mv labca_key.pem labca_key_rsa.pem
|
|
[ -e labca_key_rsa.pem ] || openssl genrsa 4096 > labca_key_rsa.pem
|
|
[ -e labca_key_ecdsa.pem ] || openssl ecparam -name secp384r1 -genkey -out labca_key_ecdsa.pem
|
|
|
|
set +e
|
|
curve_count=$(openssl pkey -pubin -in /opt/boulder/labca/certs/webpki/issuer-01-pubkey.pem -text | grep -i curve | wc -l)
|
|
set -e
|
|
[ "$curve_count" == "0" ] && ln -sf labca_key_rsa.pem labca_key.pem || /bin/true
|
|
[ "$curve_count" != "0" ] && ln -sf labca_key_ecdsa.pem labca_key.pem || /bin/true
|
|
|
|
openssl req -new -utf8 -sha256 -key labca_key.pem -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:$fqdn")) > domain.csr
|
|
url=$(grep 'DEFAULT_DIRECTORY_URL =' /opt/labca/acme_tiny.py | sed -e 's/.*=[ ]*//' | sed -e 's/\"//g')
|
|
wait_server $url
|
|
sleep 10
|
|
/opt/labca/renew
|
|
;;
|
|
"nginx-remove-redirect")
|
|
perl -i -p0e 's/\n # BEGIN temporary redirect\n location = \/ \{\n return 302 \/admin\/;\n }\n # END temporary redirect\n//igs' /etc/nginx/conf.d/labca.conf
|
|
;;
|
|
"nginx-reload")
|
|
cd /opt/boulder
|
|
docker compose exec nginx nginx -s reload &>>$LOGFILE
|
|
;;
|
|
"nginx-restart")
|
|
cd /opt/boulder
|
|
docker compose restart nginx &>>$LOGFILE
|
|
;;
|
|
"log-cert")
|
|
[ -f /etc/nginx/ssl/acme_tiny.log ] && tail -200 /etc/nginx/ssl/acme_tiny.log || /bin/true
|
|
exit 0
|
|
;;
|
|
"log-commander")
|
|
[ -f $LOGFILE ] && tail -200 $LOGFILE || /bin/true
|
|
exit 0
|
|
;;
|
|
"log-control-notail")
|
|
cd /opt/boulder
|
|
docker compose logs --no-color --tail=50 control
|
|
;;
|
|
"log-cron")
|
|
[ -f /opt/logs/cron.log ] && tail -n200 -f /opt/logs/cron.log || /bin/true
|
|
exit 0
|
|
;;
|
|
"log-boulder")
|
|
cd /opt/boulder
|
|
docker compose logs -f --no-color --tail=50 boulder
|
|
;;
|
|
"log-boulder-notail")
|
|
cd /opt/boulder
|
|
docker compose logs --no-color --tail=50 boulder
|
|
;;
|
|
"log-audit")
|
|
cd /opt/boulder
|
|
docker compose logs --no-color boulder | grep "\[AUDIT\]" | grep -v "grpc: parseServiceConfig error unmarshaling due to unexpected end of JSON input" | tail -50
|
|
docker compose logs -f --no-color --tail=0 boulder | grep "\[AUDIT\]"
|
|
;;
|
|
"log-activity")
|
|
cd /opt/boulder
|
|
echo "GMT"
|
|
docker compose logs --no-color boulder | grep "\[AUDIT\]" | grep -v "grpc: parseServiceConfig error unmarshaling due to unexpected end of JSON input" | tail -15
|
|
exit 0
|
|
;;
|
|
"log-labca")
|
|
cd /opt/boulder
|
|
docker compose logs -f --no-color --tail=50 gui
|
|
;;
|
|
"log-labca-notail")
|
|
cd /opt/boulder
|
|
docker compose logs --no-color --tail=50 gui
|
|
;;
|
|
"log-web")
|
|
cd /opt/boulder
|
|
docker compose logs -f --no-color --tail=50 nginx
|
|
;;
|
|
"log-components")
|
|
nginx=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -nginx-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
|
|
svc=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -control-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
|
|
boulder=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -boulder-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
|
|
labca=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- labca-gui) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
|
|
mysql=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -bmysql-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
|
|
consul=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -bconsul-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
|
|
pkilint=$(docker inspect $(docker ps --format "{{.Names}}" | grep -- -bpkilint-) | grep -i started | grep -v depends_on | sed -e "s/[^:]*:\(.*\)/\1/" | sed -e "s/.*\"\(.*\)\".*/\1/")
|
|
echo "$nginx|$svc|$boulder|$labca|$mysql|$consul|$pkilint"
|
|
exit 0
|
|
;;
|
|
"log-uptime")
|
|
timezone=$(cat /etc/timezone)
|
|
uptime=$(uptime -s)
|
|
echo "$timezone|$uptime"
|
|
exit 0
|
|
;;
|
|
"log-stats")
|
|
docker stats --no-stream -a | grep " labca-"
|
|
;;
|
|
"revoke-cert")
|
|
read serial
|
|
read reason
|
|
cd /opt/boulder
|
|
docker compose exec boulder bin/boulder admin -config labca/config/admin.json revoke-cert -serial $serial -reason $reason -dry-run=false 2>&1
|
|
;;
|
|
"test-email")
|
|
read recipient
|
|
cd /opt/boulder
|
|
docker compose exec boulder bin/boulder mail-tester --config labca/config/expiration-mailer.json $recipient 2>&1
|
|
;;
|
|
"boulder-start")
|
|
cd /opt/boulder
|
|
COMPOSE_HTTP_TIMEOUT=120 docker compose up -d bmysql bconsul bpkilint
|
|
wait_up $PS_MYSQL &>>$LOGFILE
|
|
wait_up $PS_CONSUL 2 &>>$LOGFILE
|
|
wait_up $PS_PKILINT &>>$LOGFILE
|
|
COMPOSE_HTTP_TIMEOUT=120 docker compose up -d boulder
|
|
wait_up $PS_BOULDER $PS_BOULDER_COUNT &>>$LOGFILE
|
|
;;
|
|
"boulder-stop")
|
|
cd /opt/boulder
|
|
docker compose stop boulder
|
|
docker compose stop bmysql bconsul bpkilint
|
|
wait_down $PS_MYSQL &>>$LOGFILE
|
|
wait_down $PS_CONSUL &>>$LOGFILE
|
|
wait_down $PS_PKILINT &>>$LOGFILE
|
|
wait_down $PS_BOULDER &>>$LOGFILE
|
|
;;
|
|
"boulder-restart")
|
|
cd /opt/boulder
|
|
COMPOSE_HTTP_TIMEOUT=120 docker compose restart boulder bmysql bconsul bpkilint &>>$LOGFILE
|
|
sleep 30
|
|
wait_up $PS_MYSQL &>>$LOGFILE
|
|
wait_up $PS_CONSUL 2 &>>$LOGFILE
|
|
wait_up $PS_PKILINT &>>$LOGFILE
|
|
wait_up $PS_BOULDER $PS_BOULDER_COUNT &>>$LOGFILE
|
|
;;
|
|
"labca-restart")
|
|
cd /opt/boulder
|
|
COMPOSE_HTTP_TIMEOUT=120 docker compose restart gui
|
|
sleep 15
|
|
wait_up $PS_LABCA &>>$LOGFILE
|
|
;;
|
|
"mysql-restart")
|
|
cd /opt/boulder
|
|
set +e
|
|
COMPOSE_HTTP_TIMEOUT=120 docker compose restart bmysql
|
|
set -e
|
|
;;
|
|
"consul-restart")
|
|
cd /opt/boulder
|
|
set +e
|
|
COMPOSE_HTTP_TIMEOUT=120 docker compose restart bconsul
|
|
set -e
|
|
;;
|
|
"pkilint-restart")
|
|
cd /opt/boulder
|
|
set +e
|
|
COMPOSE_HTTP_TIMEOUT=120 docker compose restart bpkilint
|
|
set -e
|
|
;;
|
|
"log-backups")
|
|
ls -1tr /opt/backup || /bin/true
|
|
exit 0
|
|
;;
|
|
"log-server-backup")
|
|
/opt/labca/backup
|
|
exit 0
|
|
;;
|
|
"backup-delete")
|
|
read backup
|
|
rm -f /opt/backup/$backup
|
|
;;
|
|
"backup-restore")
|
|
read backup
|
|
/opt/labca/restore "$backup"
|
|
sleep 3
|
|
;;
|
|
"server-restart")
|
|
cd /opt/boulder
|
|
nohup docker compose restart gui & >/dev/null
|
|
nohup docker compose restart nginx & >/dev/null
|
|
;;
|
|
"version-update")
|
|
cd $dn
|
|
branch="$(git symbolic-ref --short HEAD 2>/dev/null)" || branch="(none)"
|
|
if [ "$branch" == "master" ] || [ "$branch" == "main" ] || [ "$branch" == "(none)" ]; then
|
|
nohup /labca/install &>>$LOGFILE
|
|
else
|
|
nohup /labca/install -b $branch &>>$LOGFILE
|
|
fi
|
|
;;
|
|
"gen-root-crl")
|
|
cd /opt/labca/gui
|
|
/opt/labca/bin/labca-gui -config /opt/labca/data/config.json -renewcrl 999 &>>$LOGFILE
|
|
/opt/labca/checkcrl &>>$LOGFILE
|
|
;;
|
|
"gen-issuer-crl")
|
|
cd /opt/boulder
|
|
docker compose exec -i boulder ./bin/boulder crl-updater -config labca/config/crl-updater.json -runOnce -debug-addr :18021 &>>$LOGFILE
|
|
/opt/labca/checkcrl &>>$LOGFILE
|
|
;;
|
|
"check-crl")
|
|
/opt/labca/checkcrl &>>$LOGFILE
|
|
;;
|
|
"apply")
|
|
[ ! -e /opt/labca/apply ] || /opt/labca/apply &>>$LOGFILE
|
|
[ ! -e /opt/labca/gui/apply ] || /opt/labca/gui/apply &>>$LOGFILE
|
|
[ -e /opt/labca/apply ] || [ -e /opt/labca/gui/apply ] || echo "Could not find apply script!"
|
|
;;
|
|
"git-version")
|
|
if [ -x /usr/bin/git ]; then
|
|
git config --global --add safe.directory /opt/labca &>>$LOGFILE
|
|
gd=$(git describe --always --tags HEAD)
|
|
echo "$gd"
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown command '$txt'. ERROR!"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo "ok"
|