From cf391086e5194326a13793972911ff5c2ae8cdcd Mon Sep 17 00:00:00 2001 From: Joerg Heinemann Date: Fri, 1 May 2026 23:07:30 +0200 Subject: [PATCH] Step ca update (#14058) * Patch for step-ca.sh Patch for making $STD happy (/usr/bin/step is a symlink to /usr/bin/step-cli) * Refactor step-ca installation script Refactor step-ca installation script to improve configuration and template handling. - Carve out step-ca-admin.sh - Patch for making $STD happy (/usr/bin/step is a symlink to /usr/bin/step-cli) - Define enhanced x509 CA and Certificate Templates - Configure CA Provisioners, DB and CRL settings - Generate Root CA Certificate and Key - Validity: 219168h (~25 Years) - maxPathLen: 1 (Root -> Intermediate -> Leaf) => Only one Intermediate CA allowed below Root CA - Active revocation on Intermediate CA and Leaf Certificates by the usage of build-in Certificate Revocation List (CRL) - Generate Intermediate CA Certificate Bundle and Key - Validity: 175368h (~20 Years) - maxPathLen: 0 (Root -> Intermediate -> Leaf) => Intermediate CA is only allowed to issue Leaf Certificates - Active revocation on Leaf Certificates by the usage of build-in Certificate Revocation List (CRL) - Bundle: Certificate Chain (including Root CA Certificate) * Update source URL in step-ca.sh script --- ct/step-ca.sh | 6 + install/step-ca-install.sh | 499 ++++++++++++++++--------------------- 2 files changed, 226 insertions(+), 279 deletions(-) diff --git a/ct/step-ca.sh b/ct/step-ca.sh index 33649b9a7..082222282 100644 --- a/ct/step-ca.sh +++ b/ct/step-ca.sh @@ -30,6 +30,12 @@ function update_script() { msg_info "Updating step-ca and step-cli" $STD apt update $STD apt upgrade -y step-ca step-cli + + # Patch for making $STD happy (/usr/bin/step is a symlink to /usr/bin/step-cli) + STEPBIN="$(which step)" + rm -f "$STEPBIN" + cp -f "$(which step-cli)" "$STEPBIN" + $STD systemctl restart step-ca msg_ok "Updated step-ca and step-cli" diff --git a/install/step-ca-install.sh b/install/step-ca-install.sh index 6485b1211..9f0c3073b 100644 --- a/install/step-ca-install.sh +++ b/install/step-ca-install.sh @@ -23,21 +23,34 @@ setup_deb822_repo \ msg_info "Installing step-ca and step-cli" $STD apt install -y step-ca step-cli -STEPHOME="/root/.step" -export STEPPATH=/etc/step-ca +STEPPATH="/etc/step-ca" +STEPHOME="/etc/step" + +export STEPPATH=$STEPPATH +echo "export STEPPATH=${STEPPATH}" >> /etc/profile export STEPHOME=$STEPHOME +echo "export STEPHOME=${STEPHOME}" >> /etc/profile -sed -i '1i export STEPPATH=/etc/step-ca' /etc/profile -sed -i '1i export STEPHOME=/root/.step' /etc/profile +mkdir -p "$STEPHOME" -setcap CAP_NET_BIND_SERVICE=+eip $(which step-ca) +# Patch for making $STD happy (/usr/bin/step is a symlink to /usr/bin/step-cli) +STEPBIN="$(which step)" +rm -f "$STEPBIN" +cp -f "$(which step-cli)" "$STEPBIN" -$STD useradd --user-group --system --home $(step path) --shell /bin/false step +# Low port-binding capabilities (ports < 1024) +# - Default step-ca listener port: 443 +setcap CAP_NET_BIND_SERVICE=+eip "$(which step-ca)" + +# Service User used by systemd step-ca.service +$STD useradd --user-group --system --home "$(step path)" --shell /bin/false step msg_ok "Installed step-ca and step-cli" DomainName="$(hostname -d)" PKIName="$(prompt_input "Enter PKIName" "MyHomePKI" 30)" +PKICountry="$(prompt_input "Enter PKICountry" "DE" 30)" +PKIOrganizationalUnit="$(prompt_input "Enter PKIOrganizationalUnit" "MyHomeLab" 30)" PKIProvisioner="$(prompt_input "Enter PKIProvisioner" "pki@$DomainName" 30)" AcmeProvisioner="$(prompt_input "Enter AcmeProvisioner" "acme@$DomainName" 30)" X509MinDur="$(prompt_input "Enter X509MinDur" "48h" 30)" @@ -45,11 +58,15 @@ X509MaxDur="$(prompt_input "Enter X509MaxDur" "87600h" 30)" X509DefaultDur="$(prompt_input "Enter X509DefaultDur" "168h" 30)" msg_info "Initializing step-ca" + +# Initialize step-ca DeploymentType="standalone" FQDN="$(hostname -f)" IP="${LOCAL_IP}" LISTENER=":443" +LISTENER_INSECURE=":80" +# Set different signing CA and Provisioner Passwords EncryptionPwdDir="$(step path)/encryption" PwdFile="$EncryptionPwdDir/ca.pwd" ProvisionerPwdFile="$EncryptionPwdDir/provisioner.pwd" @@ -57,19 +74,208 @@ mkdir -p "$EncryptionPwdDir" gpg -q --gen-random --armor 2 32 >"$PwdFile" gpg -q --gen-random --armor 2 32 >"$ProvisionerPwdFile" -$STD step ca init --deployment-type="$DeploymentType" --ssh --name="$PKIName" --dns="$FQDN" --dns="$IP" --address="$LISTENER" --provisioner="$PKIProvisioner" --password-file="$PwdFile" --provisioner-password-file="$ProvisionerPwdFile" - +# Used by systemd step-ca.service ln -s "$PwdFile" "$(step path)/password.txt" -chown -R step:step $(step path) -chmod -R 700 $(step path) -$STD step ca provisioner add "$AcmeProvisioner" --type ACME --admin-name "$AcmeProvisioner" -$STD step ca provisioner update "$PKIProvisioner" --x509-min-dur="$X509MinDur" --x509-max-dur="$X509MaxDur" --x509-default-dur="$X509DefaultDur" --allow-renewal-after-expiry -$STD step ca provisioner update "$AcmeProvisioner" --x509-min-dur="$X509MinDur" --x509-max-dur="$X509MaxDur" --x509-default-dur="$X509DefaultDur" --allow-renewal-after-expiry -$STD step certificate install --all $(step path)/certs/root_ca.crt + +# Usage of: +# - SSH feature of step-ca +# - BadgerDB (badgerv2) => Default DB backend of step-ca +# - badgerFileLoadingMode: FileIO (instead of MemoryMap) for LXC with low RAM +$STD step ca init \ + --deployment-type="$DeploymentType" \ + --ssh \ + --name="$PKIName" \ + --dns="$FQDN" \ + --dns="$IP" \ + --address="$LISTENER" \ + --provisioner="$PKIProvisioner" \ + --password-file="$PwdFile" \ + --provisioner-password-file="$ProvisionerPwdFile" + +# Define enhanced x509 CA and Certificate Templates +mkdir -p "$(step path)/templates/ca" +mkdir -p "$(step path)/templates/x509" + +CARootTemplate="$(step path)/templates/ca/root.tpl" +CAIntermediateTemplate="$(step path)/templates/ca/intermediate.tpl" +X509LeafTemplate="$(step path)/templates/x509/leaf.tpl" +X509LeafTemplateData="$(step path)/templates/x509/leaf_data.tpl" + +cat <<'EOF' >"$CARootTemplate" +{ + "subject": { + "country": {{ toJson .Insecure.User.country }}, + "organization": {{ toJson .Insecure.User.organization }}, + "organizationalUnit": {{ toJson .Insecure.User.organizationalUnit }}, + "commonName": {{ toJson .Subject.CommonName }} + }, + "issuer": {{ toJson .Subject }}, + "keyUsage": ["certSign", "crlSign"], + "basicConstraints": { + "isCA": true, + "maxPathLen": 1 + }, + "issuingCertificateURL": [{{ toJson .Insecure.User.issuingCertificateURL }}], + "crlDistributionPoints": [{{ toJson .Insecure.User.crlDistributionPoints }}] +} +EOF + +cat <<'EOF' >"$CAIntermediateTemplate" +{ + "subject": { + "country": {{ toJson .Insecure.User.country }}, + "organization": {{ toJson .Insecure.User.organization }}, + "organizationalUnit": {{ toJson .Insecure.User.organizationalUnit }}, + "commonName": {{ toJson .Subject.CommonName }} + }, + "keyUsage": ["certSign", "crlSign"], + "basicConstraints": { + "isCA": true, + "maxPathLen": 0 + }, + "issuingCertificateURL": [{{ toJson .Insecure.User.issuingCertificateURL }}], + "crlDistributionPoints": [{{ toJson .Insecure.User.crlDistributionPoints }}] +} +EOF + +cat <<'EOF' >"$X509LeafTemplate" +{ + "subject": { +{{- if .Insecure.User.Country }} + "country": {{ toJson .Insecure.User.country }}, +{{- else }} + "country": {{ toJson .country }}, +{{- end }} +{{- if .Insecure.User.organization }} + "organization": {{ toJson .Insecure.User.organization }}, +{{- else }} + "organization": {{ toJson .organization }}, +{{- end }} +{{- if .Insecure.User.organizationalUnit }} + "organizationalUnit": {{ toJson .Insecure.User.organizationalUnit }}, +{{- else }} + "organizationalUnit": {{ toJson .organizationalUnit }}, +{{- end }} + "commonName": {{ toJson .Subject.CommonName }} + }, + "sans": {{ toJson .SANs }}, +{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }} + "keyUsage": ["keyEncipherment", "digitalSignature"], +{{- else }} + "keyUsage": ["digitalSignature"], +{{- end }} + "extKeyUsage": ["serverAuth", "clientAuth"], +{{- if .Insecure.User.issuingCertificateURL }} + "issuingCertificateURL": [{{ toJson .Insecure.User.issuingCertificateURL }}], +{{- else }} + "issuingCertificateURL": [{{ toJson .issuingCertificateURL }}], +{{- end }} +{{- if .Insecure.User.crlDistributionPoints }} + "crlDistributionPoints": [{{ toJson .Insecure.User.crlDistributionPoints }}] +{{- else }} + "crlDistributionPoints": [{{ toJson .crlDistributionPoints }}] +{{- end }} +} +EOF + +cat <"$X509LeafTemplateData" +{ + "country": "${PKICountry}", + "organization": "${PKIName}", + "organizationalUnit": "${PKIOrganizationalUnit}", + "issuingCertificateURL": ["https://${FQDN}${LISTENER}/intermediates.pem"], + "crlDistributionPoints": ["https://${FQDN}${LISTENER}/crl"] +} +EOF + +# Configure CA Provisioners, DB and CRL settings +$STD step ca provisioner add "$AcmeProvisioner" \ + --type ACME \ + --admin-name "$AcmeProvisioner" + +$STD step ca provisioner update "$PKIProvisioner" \ + --x509-min-dur="$X509MinDur" \ + --x509-max-dur="$X509MaxDur" \ + --x509-default-dur="$X509DefaultDur" \ + --x509-template="$X509LeafTemplate" \ + --x509-template-data="$X509LeafTemplateData" \ + --allow-renewal-after-expiry + +$STD step ca provisioner update "$AcmeProvisioner" \ + --x509-min-dur="$X509MinDur" \ + --x509-max-dur="$X509MaxDur" \ + --x509-default-dur="$X509DefaultDur" \ + --x509-template="$X509LeafTemplate" \ + --x509-template-data="$X509LeafTemplateData" \ + --allow-renewal-after-expiry + +CAConfig="$(step path)/config/ca.json" +jq --arg a "${PKICountry}" '.country = $a' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq --arg a "${PKIName}" '.organization = $a' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq --arg a "${PKIOrganizationalUnit}" '.organizationalUnit = $a' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq --arg a "${PKIName} Online CA" '.commonName = $a' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq '.db.badgerFileLoadingMode = "FileIO"' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq '.crl.enabled = true' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq '.crl.generateOnRevoke = true' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq '.crl.cacheDuration = "24h0m0s"' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq '.crl.renewPeriod = "16h0m0s"' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq --arg a "https://${FQDN}${LISTENER}/crl" '.crl.idpURL = $a' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" +jq --arg a "$LISTENER_INSECURE" '.insecureAddress = $a' "${CAConfig}" > "${CAConfig}_tmp" && mv "${CAConfig}_tmp" "${CAConfig}" + +# Generate Root CA Certificate and Key +# - Validity: 219168h (~25 Years) +# - maxPathLen: 1 (Root -> Intermediate -> Leaf) => Only one Intermediate CA allowed below Root CA +# - Active revocation on Intermediate CA and Leaf Certificates by the usage of build-in Certificate Revocation List (CRL) +FLAGS=(--force + --template="${CARootTemplate}" + --not-after="219168h" + --password-file="${PwdFile}" + --set country="${PKICountry}" + --set organization="${PKIName}" + --set organizationalUnit="${PKIOrganizationalUnit}" + --set issuingCertificateURL="https://${FQDN}${LISTENER}/roots.pem" + --set crlDistributionPoints="https://${FQDN}${LISTENER}/crl") + +$STD step certificate create "${PKIName} Root CA" \ + "$(step path)/certs/root_ca.crt" \ + "$(step path)/secrets/root_ca_key" \ + "${FLAGS[@]}" + +# Generate Intermediate CA Certificate Bundle and Key +# - Validity: 175368h (~20 Years) +# - maxPathLen: 0 (Root -> Intermediate -> Leaf) => Intermediate CA is only allowed to issue Leaf Certificates +# - Active revocation on Leaf Certificates by the usage of build-in Certificate Revocation List (CRL) +# - Bundle: Certificate Chain (including Root CA Certificate) +FLAGS=(--force + --template="${CAIntermediateTemplate}" + --ca="$(step path)/certs/root_ca.crt" + --ca-key="$(step path)/secrets/root_ca_key" + --not-after="175368h" + --ca-password-file="${PwdFile}" + --password-file="${PwdFile}" + --bundle + --set country="${PKICountry}" + --set organization="${PKIName}" + --set organizationalUnit="${PKIOrganizationalUnit}" + --set issuingCertificateURL="https://${FQDN}${LISTENER}/roots.pem" + --set crlDistributionPoints="https://${FQDN}${LISTENER}/crl") + +$STD step certificate create "${PKIName} Intermediate CA" \ + "$(step path)/certs/intermediate_ca.crt" \ + "$(step path)/secrets/intermediate_ca_key" \ + "${FLAGS[@]}" + +# Install Root CA Certificate to System Trust Store +$STD step certificate install --all "$(step path)/certs/root_ca.crt" $STD update-ca-certificates + +chown -R step:step "$(step path)" +chmod -R 700 "$(step path)" msg_ok "Initialized step-ca" msg_info "Start step-ca as a Daemon" + +# https://smallstep.com/docs/step-ca/certificate-authority-server-production/#running-step-ca-as-a-daemon cat <<'EOF' >/etc/systemd/system/step-ca.service [Unit] Description=step-ca service @@ -130,271 +336,6 @@ msg_ok "Started step-ca as a Daemon" fetch_and_deploy_gh_release "step-badger" "lukasz-lobocki/step-badger" "prebuild" "latest" "/opt/step-badger" "step-badger_Linux_x86_64.tar.gz" ln -s /opt/step-badger/step-badger /usr/local/bin/step-badger -msg_info "Install step-ca Admin script" -mkdir -p "$STEPHOME" -cat <<'ADDON_EOF' >"$STEPHOME/step-ca-admin.sh" -#!/usr/bin/env bash - -# Copyright (c) 2021-2026 community-scripts ORG -# Author: Joerg Heinemann (heinemannj) -# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE - -function header_info() { - clear - cat <<"EOF" - __ ___ __ _ - _____/ /____ ____ _________ _ / | ____/ /___ ___ (_)___ - / ___/ __/ _ \/ __ \______/ ___/ __ `/ / /| |/ __ / __ `__ \/ / __ \ - (__ ) /_/ __/ /_/ /_____/ /__/ /_/ / / ___ / /_/ / / / / / / / / / / -/____/\__/\___/ .___/ \___/\__,_/ /_/ |_\__,_/_/ /_/ /_/_/_/ /_/ - /_/ - -EOF -} - -function die() { - echo -e "\n${BL}[ERROR]${GN} ${RD}${1}${CL}\n" - exit -} - -function success() { - echo -e "${BL}[SUCCESS]${GN} ${1}${CL}\n" - exit -} - -function whiptail_menu() { - MENU_ARRAY=() - MSG_MAX_LENGTH=0 - while read -r TAG ITEM; do - OFFSET=2 - ((${#ITEM} + OFFSET > MSG_MAX_LENGTH)) && MSG_MAX_LENGTH=${#ITEM}+OFFSET - MENU_ARRAY+=("$TAG" "$ITEM " "OFF") - done < <(echo "$1") -} - -function x509_list() { - CERT_LIST="" - cp --recursive --force "$(step path)/db/"* "$STEPHOME/db-copy/" - cp --recursive --force "$(step path)/certs/"* "$STEPHOME/certs/ca/" - if [[ $(step-badger x509Certs "${STEPHOME}/db-copy" 2>/dev/null) ]]; then - CERT_LIST=$(step-badger x509Certs ${STEPHOME}/db-copy 2>/dev/null) - fi -} - -function ssh_list() { - CERT_LIST="" - cp --recursive --force "$(step path)/db/"* "$STEPHOME/db-copy/" - cp --recursive --force "$(step path)/certs/"* "$STEPHOME/certs/ca/" - if [[ $(step-badger sshCerts "${STEPHOME}/db-copy" 2>/dev/null) ]]; then - CERT_LIST=$(step-badgersshCerts ${STEPHOME}/db-copy 2>/dev/null) - fi -} - -function x509_serial_to_cn() { - x509_list - CN="$(echo "${CERT_LIST}" | grep "${SERIAL_NUMBER}" | awk '{print $2}' | sed 's/CN=//g')" - CRT="$STEPHOME/certs/x509/$CN.crt" - KEY="$STEPHOME/certs/x509/$CN.key" - if ! [[ -f ${CRT} ]]; then - die "Certificate ${CRT} not found!" - elif ! [[ -f ${KEY} ]]; then - die "Private Key ${KEY} not found!" - fi -} - -function x509_revoke() { - # shellcheck disable=SC2206 - SERIAL_NUMBER_ARRAY=(${CERT_SERIAL_NUMBERS}) - for SERIAL_NUMBER in "${SERIAL_NUMBER_ARRAY[@]}"; do - echo -e "${BL}[Info]${GN} Revoke x509 Certificate with Serial Number ${BL}${SERIAL_NUMBER}${GN}:${CL}" - echo - TOKEN=$(step ca token --provisioner="$PROVISIONER" --provisioner-password-file="$PROVISIONER_PASSWORD" --revoke "${SERIAL_NUMBER}") - step ca revoke --token "$TOKEN" "${SERIAL_NUMBER}" || die "Failed to revoke certificate!" - echo - done - success "Finished." -} - -function x509_renew() { - # shellcheck disable=SC2206 - SERIAL_NUMBER_ARRAY=(${CERT_SERIAL_NUMBERS}) - for SERIAL_NUMBER in "${SERIAL_NUMBER_ARRAY[@]}"; do - echo -e "${BL}[Info]${GN} Renew x509 Certificate with Serial Number ${BL}${SERIAL_NUMBER}${GN}:${CL}" - echo - x509_serial_to_cn - step ca renew "${CRT}" "${KEY}" --force || die "Failed to renew certificate!" - echo - done - success "Finished." -} - -function x509_inspect() { - # shellcheck disable=SC2206 - SERIAL_NUMBER_ARRAY=(${CERT_SERIAL_NUMBERS}) - for SERIAL_NUMBER in "${SERIAL_NUMBER_ARRAY[@]}"; do - echo -e "${BL}[Info]${GN} Inspect x509 Certificate with Serial Number ${BL}${SERIAL_NUMBER}${GN}:${CL}\n" - x509_serial_to_cn - step certificate inspect "${CRT}" || die "Failed to inspect certificate!" - if ! [[ $(step certificate inspect "${CRT}" | grep "${SERIAL_NUMBER}") ]]; then - die "Serial Number ${SERIAL_NUMBER} mismatch!" - fi - echo -e "\n${BL}[Info]${GN} Public Key:${CL}\n" - cat "${CRT}" - echo -e "\n${BL}[Info]${GN} Private Key:${CL}\n" - cat "${KEY}" - echo - done - success "Finished." -} - -function x509_request() { - FQDN="" - SAN="" - - while true; do - FQDN=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Certificate Signing Request (CSR)" --inputbox '\nFQDN (e.g. MyLXC.example.com)' 10 50 "$FQDN" 3>&1 1>&2 2>&3) - IP=$(dig +short "$FQDN") - if [[ -z "$IP" ]]; then - die "Resolution failed for $FQDN!" - fi - HOST=$(echo "$FQDN" | awk -F'.' '{print $1}') - IP=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Certificate Signing Request (CSR)" --inputbox '\nIP Address (e.g. x.x.x.x)' 10 50 "$IP" 3>&1 1>&2 2>&3) - HOST=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Certificate Signing Request (CSR)" --inputbox '\nHostname (e.g. MyHostName)' 10 50 "$HOST" 3>&1 1>&2 2>&3) - SAN=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Certificate Signing Request (CSR)" --inputbox '\nSubject Alternative Name(s) (SAN) (e.g. myapp-1.example.com, myapp-2.example.com)' 10 50 "$SAN" 3>&1 1>&2 2>&3) - VALID_TO=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Certificate Signing Request (CSR)" --inputbox '\nValidity (e.g. 2034-01-31T00:00:00Z)' 10 50 "2034-01-31T00:00:00Z" 3>&1 1>&2 2>&3) - - # shellcheck disable=SC2034 - if whiptail_yesno=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Certificate Signing Request (CSR)" --yesno "Continue with below?\n - FQDN: $FQDN - Hostname: $HOST - IP Address: $IP - Subject Alternative Name(s) (SAN): $SAN - Validity: $VALID_TO" --no-button "Change" --yes-button "Continue" 15 70 3>&1 1>&2 2>&3); then - break - fi - done - - echo -e "${BL}[Info]${GN} Request x509 Certificate with subject ${BL}${FQDN}${GN}:${CL}" - echo - CRT="$STEPHOME/certs/x509/$FQDN.crt" - KEY="$STEPHOME/certs/x509/$FQDN.key" - - SAN="$FQDN, $HOST, $IP, $SAN" - - IFS=', ' read -r -a array <<< "$SAN" - for element in "${array[@]}" - do - SAN_ARRAY+=(--san "$element") - done - - step ca certificate "$FQDN" "$CRT" "$KEY" \ - --provisioner="$PROVISIONER" \ - --provisioner-password-file="$PROVISIONER_PASSWORD" \ - --not-after="$VALID_TO" \ - "${SAN_ARRAY[@]}" \ - || die "Failed to request certificate!" - - echo -e "\n${BL}[Info]${GN} Inspect Certificate:${CL}\n" - step certificate inspect "${CRT}" || die "Failed to inspect certificate!" - echo -e "\n${BL}[Info]${GN} Public Key:${CL}\n" - cat "${CRT}" - echo -e "\n${BL}[Info]${GN} Private Key:${CL}\n" - cat "${KEY}" - echo - success "Finished." -} - -set -eEuo pipefail -# shellcheck disable=SC2034 -# shellcheck disable=SC2116 -# shellcheck disable=SC2028 -YW=$(echo "\033[33m") -# shellcheck disable=SC2116 -# shellcheck disable=SC2028 -BL=$(echo "\033[36m") -# shellcheck disable=SC2116 -# shellcheck disable=SC2028 -RD=$(echo "\033[01;31m") -# shellcheck disable=SC2034 -CM='\xE2\x9C\x94\033' -# shellcheck disable=SC2116 -# shellcheck disable=SC2028 -GN=$(echo "\033[1;92m") -# shellcheck disable=SC2116 -# shellcheck disable=SC2028 -CL=$(echo "\033[m") - -# Telemetry -# shellcheck disable=SC1090 -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true -declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "step-ca-admin" "step-ca" - -header_info - -mkdir --parents "$STEPHOME/db-copy/" -mkdir --parents "$STEPHOME/certs/ca/_archive/" -mkdir --parents "$STEPHOME/certs/ssh/_archive/" -mkdir --parents "$STEPHOME/certs/x509/_archive/" - -PROVISIONER=$(jq '.authority.provisioners.[] | select(.type=="JWK") | .name' "$(step path)"/config/ca.json) -PROVISIONER="${PROVISIONER#\"}" -PROVISIONER="${PROVISIONER%\"}" -PROVISIONER_PASSWORD=$(step path)/encryption/provisioner.pwd - -whiptail --backtitle "Proxmox VE Helper Scripts" --title "step-ca Admin" --yesno "This will maintain step-ca issued x509 and ssh Certificates. Proceed?" 10 58 - -MENU_ARRAY=("x509" "Maintain x509 Certificates." "ON") -MENU_ARRAY+=("ssh" "Maintain ssh Certificates." "OFF") -CERT_TYPE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "step-ca Admin" --radiolist "\nSelect Certificate Type:" 16 48 6 "${MENU_ARRAY[@]}" 3>&1 1>&2 2>&3 | tr -d '"') - -[[ -z ${CERT_TYPE} ]] && die "No Certificate Type selected!" - -case ${CERT_TYPE} in -("x509") - x509_list - CERT_LIST=$(echo "$CERT_LIST" | awk 'NR>1 {print $1 " " $2 "|" $3 "|" $4 "|" $5}') - if [[ $CERT_LIST ]]; then - whiptail_menu "$CERT_LIST" - else - MENU_ARRAY=() - MSG_MAX_LENGTH=2 - fi - MENU_ARRAY+=("" "Create a new Certificate" "OFF") - CERT_SERIAL_NUMBERS=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Certificates on $(hostname)" --checklist "\nSelect Certificate(s) to maintain:\n" 16 $((MSG_MAX_LENGTH + 55)) 6 "${MENU_ARRAY[@]}" 3>&1 1>&2 2>&3 | tr -d '"') - - [[ -z ${CERT_SERIAL_NUMBERS} ]] && x509_request - - MENU_ARRAY=("Renew" "Renew x509 Certificates." "ON") - MENU_ARRAY+=("Revoke" "Revoke x509 Certificates." "OFF") - MENU_ARRAY+=("Inspect" "Inspect x509 Certificates." "OFF") - CERT_MAINTENANCE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "step-ca Admin" --radiolist "\nSelect Maintenance Type:" 16 48 6 "${MENU_ARRAY[@]}" 3>&1 1>&2 2>&3 | tr -d '"') - - case ${CERT_MAINTENANCE} in - ("Renew") - x509_renew "${CERT_SERIAL_NUMBERS[@]}" - ;; - ("Revoke") - x509_revoke "${CERT_SERIAL_NUMBERS[@]}" - ;; - ("Inspect") - x509_inspect "${CERT_SERIAL_NUMBERS[@]}" - ;; - *) - die "Unsupported CERT_MAINTENANCE Option!" - ;; - esac - ;; -("ssh") - die "Maintain ssh Certificates - To be implemented in future" - ;; -*) - die "Unsupported CERT_TYPE Option!" - ;; -esac -ADDON_EOF -chmod 700 "$STEPHOME/step-ca-admin.sh" -msg_ok "Installed step-ca Admin script" - motd_ssh customize cleanup_lxc