From b5d837414333c4d6a4e20636eb8e2ea51476a6ea Mon Sep 17 00:00:00 2001 From: Alex Lovell-Troy Date: Mon, 15 Apr 2024 08:52:21 -0400 Subject: [PATCH] Replace init and entrypoint with something more robust --- local-ca/Dockerfile | 25 +++++++++--- local-ca/entrypoint.sh | 91 ++++++++++++++++++++++++++++++++++++++++++ local-ca/init.sh | 8 ---- 3 files changed, 111 insertions(+), 13 deletions(-) create mode 100644 local-ca/entrypoint.sh delete mode 100644 local-ca/init.sh diff --git a/local-ca/Dockerfile b/local-ca/Dockerfile index 8333ed4..2c2ee55 100644 --- a/local-ca/Dockerfile +++ b/local-ca/Dockerfile @@ -1,8 +1,23 @@ FROM cgr.dev/chainguard/wolfi-base #install step dependencies -RUN apk add wget step step-ca -#need a mountpoint on /mnt, with files password1 and password2 within the base dir -ENV STEPPATH=/mnt/ -COPY --chmod=555 init.sh /bin/init.sh -ENTRYPOINT init.sh +RUN apk add --no-cache wget step step-ca bash +ENV CONFIGPATH="/home/step/config/ca.json" +ENV PWDPATH="/home/step/secrets/password" +ENV STEPPATH="/home/step" + +RUN mkdir /root-ca + +VOLUME ["/home/step", "/root-ca"] + +# The entrypoint script will generate the certificate and export the root cert to the /root-ca volume + +STOPSIGNAL SIGTERM +HEALTHCHECK CMD step ca health 2>/dev/null | grep "^ok" >/dev/null + +COPY entrypoint.sh /entrypoint.sh + +EXPOSE 9000/TCP + +ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] +CMD exec /usr/bin/step-ca --password-file $PWDPATH $CONFIGPATH diff --git a/local-ca/entrypoint.sh b/local-ca/entrypoint.sh new file mode 100644 index 0000000..b941551 --- /dev/null +++ b/local-ca/entrypoint.sh @@ -0,0 +1,91 @@ +#!/bin/bash +set -eo pipefail + +# Paraphrased from: +# https://github.com/influxdata/influxdata-docker/blob/0d341f18067c4652dfa8df7dcb24d69bf707363d/influxdb/2.0/entrypoint.sh +# (a repo with no LICENSE.md) + +export STEPPATH=$(step path) + +# List of env vars required for step ca init +declare -ra REQUIRED_INIT_VARS=(DOCKER_STEPCA_INIT_NAME DOCKER_STEPCA_INIT_DNS_NAMES) + +# Ensure all env vars required to run step ca init are set. +function init_if_possible () { + local missing_vars=0 + for var in "${REQUIRED_INIT_VARS[@]}"; do + if [ -z "${!var}" ]; then + missing_vars=1 + fi + done + if [ ${missing_vars} = 1 ]; then + >&2 echo "there is no ca.json config file; please run step ca init, or provide config parameters via DOCKER_STEPCA_INIT_ vars" + else + step_ca_init "${@}" + fi +} + +function generate_password () { + set +o pipefail + < /dev/urandom tr -dc A-Za-z0-9 | head -c40 + echo + set -o pipefail +} + +# Initialize a CA if not already initialized +function step_ca_init () { + DOCKER_STEPCA_INIT_PROVISIONER_NAME="${DOCKER_STEPCA_INIT_PROVISIONER_NAME:-admin}" + DOCKER_STEPCA_INIT_ADMIN_SUBJECT="${DOCKER_STEPCA_INIT_ADMIN_SUBJECT:-step}" + DOCKER_STEPCA_INIT_ADDRESS="${DOCKER_STEPCA_INIT_ADDRESS:-:9000}" + + local -a setup_args=( + --name "${DOCKER_STEPCA_INIT_NAME}" + --dns "${DOCKER_STEPCA_INIT_DNS_NAMES}" + --provisioner "${DOCKER_STEPCA_INIT_PROVISIONER_NAME}" + --password-file "${STEPPATH}/password" + --provisioner-password-file "${STEPPATH}/provisioner_password" + --address "${DOCKER_STEPCA_INIT_ADDRESS}" + ) + if [ -n "${DOCKER_STEPCA_INIT_PASSWORD_FILE}" ]; then + cat < "${DOCKER_STEPCA_INIT_PASSWORD_FILE}" > "${STEPPATH}/password" + cat < "${DOCKER_STEPCA_INIT_PASSWORD_FILE}" > "${STEPPATH}/provisioner_password" + elif [ -n "${DOCKER_STEPCA_INIT_PASSWORD}" ]; then + echo "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/password" + echo "${DOCKER_STEPCA_INIT_PASSWORD}" > "${STEPPATH}/provisioner_password" + else + generate_password > "${STEPPATH}/password" + generate_password > "${STEPPATH}/provisioner_password" + fi + if [ "${DOCKER_STEPCA_INIT_SSH}" == "true" ]; then + setup_args=("${setup_args[@]}" --ssh) + fi + if [ "${DOCKER_STEPCA_INIT_ACME}" == "true" ]; then + setup_args=("${setup_args[@]}" --acme) + fi + if [ "${DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT}" == "true" ]; then + setup_args=("${setup_args[@]}" --remote-management + --admin-subject "${DOCKER_STEPCA_INIT_ADMIN_SUBJECT}" + ) + fi + step ca init "${setup_args[@]}" + echo "" + if [ "${DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT}" == "true" ]; then + echo "👉 Your CA administrative username is: ${DOCKER_STEPCA_INIT_ADMIN_SUBJECT}" + fi + echo "👉 Your CA administrative password is: $(< $STEPPATH/provisioner_password )" + echo "🤫 This will only be displayed once." + shred -u $STEPPATH/provisioner_password + mv $STEPPATH/password $PWDPATH + cp /home/step/certs/root_ca.crt /root-ca/root_ca.crt + echo "🔒 Your CA is ready to go!" +} + +if [ -f /usr/sbin/pcscd ]; then + /usr/sbin/pcscd +fi + +if [ ! -f "${STEPPATH}/config/ca.json" ]; then + init_if_possible +fi + +exec "${@}" \ No newline at end of file diff --git a/local-ca/init.sh b/local-ca/init.sh deleted file mode 100644 index 5061673..0000000 --- a/local-ca/init.sh +++ /dev/null @@ -1,8 +0,0 @@ -if ! [ -f /mnt/password1 -a -f /mnt/config/ca.json ] -then - echo $(tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' /mnt/password1 - echo $(tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' /mnt/password2 - step ca init --name="SI" --deployment-type standalone --password-file=/mnt/password1 --provisioner-password-file=/mnt/password2 --dns="SI.ca" --address=":443" --provisioner="admin" --remote-management --acme -fi -step-ca --password-file=/mnt/password1 /mnt/config/ca.json -