mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
change(docker): use step-ca for CA + cert generation
Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
e558e979ff
commit
b98159d5b9
10 changed files with 160 additions and 69 deletions
|
@ -1,58 +1,123 @@
|
|||
#!/bin/bash
|
||||
# Initialize step-ca and request certificates from it.
|
||||
#
|
||||
# Certificates created by this service are meant to be used in
|
||||
# aurweb Docker's nginx service.
|
||||
#
|
||||
# If ./data/root_ca.crt is present, CA generation is skipped.
|
||||
# If ./data/${host}.{cert,key}.pem is available, host certificate
|
||||
# generation is skipped.
|
||||
#
|
||||
set -eou pipefail
|
||||
|
||||
if [ -f /data/ca.root.pem ]; then
|
||||
echo "Already have certs, skipping."
|
||||
exit 0
|
||||
# /data-based variables.
|
||||
DATA_DIR="/data"
|
||||
DATA_ROOT_CA="$DATA_DIR/root_ca.crt"
|
||||
DATA_CERT="$DATA_DIR/localhost.cert.pem"
|
||||
DATA_CERT_KEY="$DATA_DIR/localhost.key.pem"
|
||||
|
||||
# Host certificates requested from the CA (separated by spaces).
|
||||
DATA_CERT_HOSTS='localhost'
|
||||
|
||||
# Local step paths and CA configuration values.
|
||||
STEP_DIR="$(step-cli path)"
|
||||
STEP_CA_CONFIG="$STEP_DIR/config/ca.json"
|
||||
STEP_CA_ADDR='127.0.0.1:8443'
|
||||
STEP_CA_URL='https://localhost:8443'
|
||||
STEP_CA_PROVISIONER='admin@localhost'
|
||||
|
||||
# Password file used for both --password-file and --provisioner-password-file.
|
||||
STEP_PASSWD_FILE="$STEP_DIR/password.txt"
|
||||
|
||||
# Hostnames supported by the CA.
|
||||
STEP_CA_NAME='aurweb'
|
||||
STEP_CA_DNS='localhost'
|
||||
|
||||
make_password() {
|
||||
# Create a random 20-length password and write it to $1.
|
||||
openssl rand -hex 20 > $1
|
||||
}
|
||||
|
||||
setup_step_ca() {
|
||||
# Cleanup and setup step ca configuration.
|
||||
rm -rf $STEP_DIR/*
|
||||
|
||||
# Initialize `step`
|
||||
make_password "$STEP_PASSWD_FILE"
|
||||
step-cli ca init \
|
||||
--name="$STEP_CA_NAME" \
|
||||
--dns="$STEP_CA_DNS" \
|
||||
--address="$STEP_CA_ADDR" \
|
||||
--password-file="$STEP_PASSWD_FILE" \
|
||||
--provisioner="$STEP_CA_PROVISIONER" \
|
||||
--provisioner-password-file="$STEP_PASSWD_FILE" \
|
||||
--with-ca-url="$STEP_CA_URL"
|
||||
|
||||
# Update ca.json max TLS certificate duration to a year.
|
||||
update-step-config "$STEP_CA_CONFIG"
|
||||
|
||||
# Install root_ca.crt as read/writable to /data/root_ca.crt.
|
||||
install -m666 "$STEP_DIR/certs/root_ca.crt" "$DATA_ROOT_CA"
|
||||
}
|
||||
|
||||
start_step_ca() {
|
||||
# Start the step-ca web server.
|
||||
step-ca "$STEP_CA_CONFIG" \
|
||||
--password-file="$STEP_PASSWD_FILE" &
|
||||
until printf "" 2>>/dev/null >>/dev/tcp/127.0.0.1/8443; do
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
kill_step_ca() {
|
||||
# Stop the step-ca web server.
|
||||
killall step-ca >/dev/null 2>&1 || /bin/true
|
||||
}
|
||||
|
||||
install_step_ca() {
|
||||
# Install step-ca certificate authority to the system.
|
||||
step-cli certificate install "$STEP_DIR/certs/root_ca.crt"
|
||||
}
|
||||
|
||||
step_cert_request() {
|
||||
# Request a certificate from the step ca.
|
||||
step-cli ca certificate \
|
||||
--not-after=8800h \
|
||||
--provisioner="$STEP_CA_PROVISIONER" \
|
||||
--provisioner-password-file="$STEP_PASSWD_FILE" \
|
||||
$1 $2 $3
|
||||
chmod 666 /data/${1}.*.pem
|
||||
}
|
||||
|
||||
if [ ! -f $DATA_ROOT_CA ]; then
|
||||
setup_step_ca
|
||||
install_step_ca
|
||||
fi
|
||||
|
||||
# Generate a new 2048-bit RSA key for the Root CA.
|
||||
openssl genrsa -des3 -out /data/ca.key -passout pass:devca 2048
|
||||
# For all hosts separated by spaces in $DATA_CERT_HOSTS, perform a check
|
||||
# for their existence in /data and react accordingly.
|
||||
for host in $DATA_CERT_HOSTS; do
|
||||
if [ -f /data/${host}.cert.pem ] && [ -f /data/${host}.key.pem ]; then
|
||||
# Found an override. Move on to running the service after
|
||||
# printing a notification to the user.
|
||||
echo "Found '${host}.{cert,key}.pem' override, skipping..."
|
||||
echo -n "Note: If you need to regenerate certificates, run "
|
||||
echo '`rm -f data/*.{cert,key}.pem` before starting this service.'
|
||||
exec "$@"
|
||||
else
|
||||
# Otherwise, we had a missing cert or key, so remove both.
|
||||
rm -f /data/${host}.cert.pem
|
||||
rm -f /data/${host}.key.pem
|
||||
fi
|
||||
done
|
||||
|
||||
# Request and self-sign a new Root CA certificate, using
|
||||
# the RSA key. Output Root CA PEM-format certificate and key:
|
||||
# /data/ca.root.pem and /data/ca.key.pem
|
||||
openssl req -x509 -new -nodes -sha256 -days 1825 \
|
||||
-passin pass:devca \
|
||||
-subj "/C=US/ST=California/L=Authority/O=aurweb/CN=localhost" \
|
||||
-in /data/ca.key -out /data/ca.root.pem -keyout /data/ca.key.pem
|
||||
start_step_ca
|
||||
for host in $DATA_CERT_HOSTS; do
|
||||
step_cert_request $host /data/${host}.cert.pem /data/${host}.key.pem
|
||||
done
|
||||
kill_step_ca
|
||||
|
||||
# Generate a new 2048-bit RSA key for a localhost server.
|
||||
openssl genrsa -out /data/localhost.key 2048
|
||||
|
||||
# Generate a Certificate Signing Request (CSR) for the localhost server
|
||||
# using the RSA key we generated above.
|
||||
openssl req -new -key /data/localhost.key -passout pass:devca \
|
||||
-subj "/C=US/ST=California/L=Server/O=aurweb/CN=localhost" \
|
||||
-out /data/localhost.csr
|
||||
|
||||
# Get our CSR signed by our Root CA PEM-formatted certificate and key
|
||||
# to produce a fresh /data/localhost.cert.pem PEM-formatted certificate.
|
||||
openssl x509 -req -in /data/localhost.csr \
|
||||
-CA /data/ca.root.pem -CAkey /data/ca.key.pem \
|
||||
-CAcreateserial \
|
||||
-out /data/localhost.cert.pem \
|
||||
-days 825 -sha256 \
|
||||
-passin pass:devca \
|
||||
-extfile /docker/localhost.ext
|
||||
|
||||
# Convert RSA key to a PEM-formatted key: /data/localhost.key.pem
|
||||
openssl rsa -in /data/localhost.key -text > /data/localhost.key.pem
|
||||
|
||||
# At the end here, our notable certificates and keys are:
|
||||
# - /data/ca.root.pem
|
||||
# - /data/ca.key.pem
|
||||
# - /data/localhost.key.pem
|
||||
# - /data/localhost.cert.pem
|
||||
#
|
||||
# When running a server which uses the localhost certificate, a chain
|
||||
# should be used, starting with localhost.cert.pem:
|
||||
# - cat /data/localhost.cert.pem /data/ca.root.pem > localhost.chain.pem
|
||||
#
|
||||
# The Root CA (ca.root.pem) should be imported into browsers or
|
||||
# ca-certificates on machines wishing to verify localhost.
|
||||
#
|
||||
|
||||
chmod 666 /data/*
|
||||
# Set permissions to /data to rwx for everybody.
|
||||
chmod 777 /data
|
||||
|
||||
exec "$@"
|
||||
|
|
2
docker/health/ca.sh
Executable file
2
docker/health/ca.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
|
||||
exec printf "" 2>>/dev/null >>/dev/tcp/127.0.0.1/8443
|
|
@ -15,7 +15,7 @@ if [ -f "$CERT" ]; then
|
|||
cp -vf "$CERT" "$DEST_CERT"
|
||||
cp -vf "$KEY" "$DEST_KEY"
|
||||
else
|
||||
cat /data/localhost.cert.pem /data/ca.root.pem > "$DEST_CERT"
|
||||
cat /data/localhost.cert.pem /data/root_ca.crt > "$DEST_CERT"
|
||||
cp -vf /data/localhost.key.pem "$DEST_KEY"
|
||||
fi
|
||||
|
||||
|
|
|
@ -9,6 +9,6 @@ pacman -Syu --noconfirm --noprogressbar \
|
|||
mariadb mariadb-libs cgit-aurweb uwsgi uwsgi-plugin-cgi \
|
||||
php php-fpm memcached php-memcached python-pip pyalpm \
|
||||
python-srcinfo curl libeatmydata cronie python-poetry \
|
||||
python-poetry-core
|
||||
python-poetry-core step-cli step-ca
|
||||
|
||||
exec "$@"
|
||||
|
|
7
docker/scripts/run-ca.sh
Executable file
7
docker/scripts/run-ca.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
STEP_DIR="$(step-cli path)"
|
||||
STEP_PASSWD_FILE="$STEP_DIR/password.txt"
|
||||
STEP_CA_CONFIG="$STEP_DIR/config/ca.json"
|
||||
|
||||
# Start the step-ca https server.
|
||||
exec step-ca "$STEP_CA_CONFIG" --password-file="$STEP_PASSWD_FILE"
|
19
docker/scripts/update-step-config
Executable file
19
docker/scripts/update-step-config
Executable file
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env python3
|
||||
import json
|
||||
import sys
|
||||
|
||||
CA_CONFIG = sys.argv[1]
|
||||
|
||||
with open(CA_CONFIG) as f:
|
||||
data = json.load(f)
|
||||
|
||||
if "authority" not in data:
|
||||
data["authority"] = dict()
|
||||
if "claims" not in data["authority"]:
|
||||
data["authority"]["claims"] = dict()
|
||||
|
||||
# One year of certificate duration.
|
||||
data["authority"]["claims"] = {"maxTLSCertDuration": "8800h"}
|
||||
|
||||
with open(CA_CONFIG, "w") as f:
|
||||
json.dump(data, f)
|
Loading…
Add table
Add a link
Reference in a new issue