Last active
February 28, 2025 14:17
-
-
Save sames/accffde38c8eed5a6febb438a620f46c to your computer and use it in GitHub Desktop.
Helper Script to create a new Certificate Authority and Certificates for your local lan.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Certhelper - A tool for creating certificates with OpenSSL | |
# | |
# Usage: | |
# certhelper.sh -h | --help - Display this help | |
# certhelper.sh -ca [name] - Create a new Certificate Authority (default: rootca) | |
# certhelper.sh -cert <domain> [ca] - Create a new certificate for <domain> using specified CA | |
# certhelper.sh -i <ca-name|domain> - Install a certificate on the system (Linux only) | |
# certhelper.sh -list - List all existing CAs | |
# certhelper.sh -r <ca-name|domain> - Renew a certificate or CA | |
# certhelper.sh -nopw - Create keys without password protection | |
# certhelper.sh -rmpw <ca|domain> - Remove password from an existing key | |
# Default values for environment variables | |
DEFAULT_COUNTRY="DE" | |
DEFAULT_STATE="Nordrhein-Westfalen" | |
DEFAULT_LOCALITY="Leopoldshoehe" | |
DEFAULT_ORGANIZATION="Home Network" | |
DEFAULT_OU="IT Department" | |
DEFAULT_CA_CN="Local Root CA" | |
DEFAULT_CA_DAYS="3650" # 10 years | |
DEFAULT_CERT_DAYS="730" # 2 years | |
# Directories | |
CA_DIR="./ca" | |
CERTS_DIR="./certs" | |
# Flag for password protection | |
USE_PASSWORD=true | |
# Create the necessary directories | |
create_dirs() { | |
mkdir -p "$CA_DIR" | |
mkdir -p "$CERTS_DIR" | |
} | |
# Display help | |
show_help() { | |
echo "Certhelper - A tool for creating certificates with OpenSSL" | |
echo "" | |
echo "Usage:" | |
echo " $(basename "$0") -h | --help - Display this help" | |
echo " $(basename "$0") -ca [name] - Create a new Certificate Authority (default: rootca)" | |
echo " $(basename "$0") -cert <domain> [ca] - Create a new certificate for <domain> using specified CA" | |
echo " $(basename "$0") -i <ca-name|domain> - Install a certificate on the system (Linux only)" | |
echo " $(basename "$0") -list - List all existing CAs" | |
echo " $(basename "$0") -r <ca-name|domain> - Renew a certificate or CA" | |
echo " $(basename "$0") -nopw - Create keys without password protection" | |
echo " $(basename "$0") -rmpw <ca|domain> - Remove password from an existing key" | |
echo "" | |
echo "Environment variables:" | |
echo " CERT_COUNTRY - Country code (Default: $DEFAULT_COUNTRY)" | |
echo " CERT_STATE - State/Province (Default: $DEFAULT_STATE)" | |
echo " CERT_LOCALITY - City (Default: $DEFAULT_LOCALITY)" | |
echo " CERT_ORG - Organization (Default: $DEFAULT_ORGANIZATION)" | |
echo " CERT_OU - Organizational Unit (Default: $DEFAULT_OU)" | |
echo " CA_CN - Common Name for CA (Default: $DEFAULT_CA_CN)" | |
echo " CA_DAYS - CA certificate validity in days (Default: $DEFAULT_CA_DAYS)" | |
echo " CERT_DAYS - Domain certificate validity in days (Default: $DEFAULT_CERT_DAYS)" | |
echo "" | |
echo "Examples:" | |
echo " $(basename "$0") -ca mycompany" | |
echo " $(basename "$0") -cert nas.lan homelab" | |
echo " $(basename "$0") -i mycompany" | |
echo " $(basename "$0") -r nas.lan" | |
echo " $(basename "$0") -nopw -ca mycompany # Create CA without password protection" | |
echo "" | |
echo "Security Note:" | |
echo " By default, private keys are protected with a password. Use -nopw to disable password protection." | |
echo " Password-protected keys are more secure but may require manual intervention when used with services." | |
echo "" | |
echo "How to install the CA certificate on different platforms:" | |
echo "" | |
echo "Linux:" | |
echo " 1. Use the -i ca command which will install the CA into the system trust store:" | |
echo " $(basename "$0") -i ca" | |
echo " 2. Alternatively, manually copy the CA certificate to the system trust store:" | |
echo " sudo cp ca/ca.crt /usr/local/share/ca-certificates/local-ca.crt" | |
echo " sudo update-ca-certificates" | |
echo "" | |
echo "macOS:" | |
echo " 1. Open the ca.crt file with Keychain Access" | |
echo " 2. Add it to the System keychain" | |
echo " 3. Double-click the imported certificate" | |
echo " 4. Expand the 'Trust' section" | |
echo " 5. Change 'When using this certificate' to 'Always Trust'" | |
echo "" | |
echo "Windows:" | |
echo " 1. Double-click the ca.crt file" | |
echo " 2. Click 'Install Certificate'" | |
echo " 3. Select 'Local Machine' and click Next" | |
echo " 4. Select 'Place all certificates in the following store'" | |
echo " 5. Click 'Browse' and select 'Trusted Root Certification Authorities'" | |
echo " 6. Click 'Next' and then 'Finish'" | |
echo " 7. Alternatively, run this PowerShell command as Administrator:" | |
echo " Import-Certificate -FilePath ca\\ca.crt -CertStoreLocation Cert:\\LocalMachine\\Root" | |
} | |
# List all Certificate Authorities | |
list_cas() { | |
create_dirs | |
echo "Available Certificate Authorities:" | |
if [ -d "$CA_DIR" ]; then | |
local cas=$(find "$CA_DIR" -name "*.crt" | sed -e 's|.*/||' -e 's|\.crt$||') | |
if [ -z "$cas" ]; then | |
echo " No Certificate Authorities found." | |
else | |
for ca in $cas; do | |
local subject=$(openssl x509 -noout -subject -in "$CA_DIR/$ca.crt" 2>/dev/null | sed 's/subject= //') | |
echo " - $ca: $subject" | |
done | |
fi | |
else | |
echo " No Certificate Authorities found." | |
fi | |
} | |
# Create a Certificate Authority | |
create_ca() { | |
local ca_name="${1:-rootca}" | |
# Use environment variables or default values | |
local country="${CERT_COUNTRY:-$DEFAULT_COUNTRY}" | |
local state="${CERT_STATE:-$DEFAULT_STATE}" | |
local locality="${CERT_LOCALITY:-$DEFAULT_LOCALITY}" | |
local organization="${CERT_ORG:-$DEFAULT_ORGANIZATION}" | |
local ou="${CERT_OU:-$DEFAULT_OU}" | |
local cn="${CA_CN:-$DEFAULT_CA_CN}" | |
local days="${CA_DAYS:-$DEFAULT_CA_DAYS}" | |
create_dirs | |
# Check if CA already exists | |
if [ -f "$CA_DIR/$ca_name.key" ] || [ -f "$CA_DIR/$ca_name.crt" ]; then | |
echo "Warning: A Certificate Authority with name '$ca_name' already exists." | |
read -p "Do you want to overwrite it? (y/N): " confirm | |
if [[ "$confirm" != [yY] && "$confirm" != [yY][eE][sS] ]]; then | |
echo "Operation cancelled." | |
exit 0 | |
fi | |
fi | |
echo "Creating Certificate Authority '$ca_name'..." | |
# Create the private key for the CA | |
if [ "$USE_PASSWORD" = true ]; then | |
echo "Creating password-protected CA private key..." | |
echo "You will be prompted to enter a password for the CA private key." | |
echo "This password will be required whenever you sign certificates with this CA." | |
openssl genrsa -des3 -out "$CA_DIR/$ca_name.key" 4096 | |
else | |
echo "Creating CA private key without password protection..." | |
openssl genrsa -out "$CA_DIR/$ca_name.key" 4096 | |
fi | |
# Create configuration file for CA | |
cat > "$CA_DIR/$ca_name.cnf" << EOF | |
[req] | |
distinguished_name = req_distinguished_name | |
x509_extensions = v3_ca | |
prompt = no | |
[req_distinguished_name] | |
C = $country | |
ST = $state | |
L = $locality | |
O = $organization | |
OU = $ou | |
CN = $cn ($ca_name) | |
[v3_ca] | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid:always,issuer | |
basicConstraints = critical, CA:true | |
keyUsage = critical, digitalSignature, cRLSign, keyCertSign | |
EOF | |
# Create the CA certificate | |
openssl req -x509 -new -nodes -key "$CA_DIR/$ca_name.key" -sha256 -days "$days" \ | |
-out "$CA_DIR/$ca_name.crt" -config "$CA_DIR/$ca_name.cnf" | |
# Create serial number for future certificates | |
echo "01" > "$CA_DIR/$ca_name.srl" | |
echo "Certificate Authority '$ca_name' has been created:" | |
echo " - Private key: $CA_DIR/$ca_name.key" | |
echo " - Certificate: $CA_DIR/$ca_name.crt" | |
echo "" | |
echo "To install this CA certificate on your system, run:" | |
echo " $(basename "$0") -i $ca_name" | |
} | |
# Create a certificate | |
create_cert() { | |
if [ -z "$1" ]; then | |
echo "Error: Domain name is required" | |
echo "Usage: $(basename "$0") -cert <domain> [ca-name]" | |
exit 1 | |
fi | |
local domain="$1" | |
local ca_name="${2:-rootca}" | |
# Check if the CA exists | |
if [ ! -f "$CA_DIR/$ca_name.key" ] || [ ! -f "$CA_DIR/$ca_name.crt" ]; then | |
echo "Error: Certificate Authority '$ca_name' not found." | |
echo "Available CAs:" | |
list_cas | |
echo "" | |
echo "Create a CA first with: $(basename "$0") -ca [$ca_name]" | |
exit 1 | |
fi | |
# Use environment variables or default values | |
local country="${CERT_COUNTRY:-$DEFAULT_COUNTRY}" | |
local state="${CERT_STATE:-$DEFAULT_STATE}" | |
local locality="${CERT_LOCALITY:-$DEFAULT_LOCALITY}" | |
local organization="${CERT_ORG:-$DEFAULT_ORGANIZATION}" | |
local ou="${CERT_OU:-$DEFAULT_OU}" | |
local days="${CERT_DAYS:-$DEFAULT_CERT_DAYS}" | |
create_dirs | |
echo "Creating certificate for $domain..." | |
# Create the private key for the certificate | |
if [ "$USE_PASSWORD" = true ]; then | |
echo "Creating password-protected certificate private key..." | |
echo "You will be prompted to enter a password for the certificate private key." | |
openssl genrsa -des3 -out "$CERTS_DIR/$domain.key" 2048 | |
else | |
echo "Creating certificate private key without password protection..." | |
openssl genrsa -out "$CERTS_DIR/$domain.key" 2048 | |
fi | |
# Create a CSR configuration file | |
cat > "$CERTS_DIR/$domain.cnf" << EOF | |
[req] | |
distinguished_name = req_distinguished_name | |
req_extensions = v3_req | |
prompt = no | |
[req_distinguished_name] | |
C = $country | |
ST = $state | |
L = $locality | |
O = $organization | |
OU = $ou | |
CN = $domain | |
[v3_req] | |
basicConstraints = CA:FALSE | |
keyUsage = nonRepudiation, digitalSignature, keyEncipherment | |
subjectAltName = @alt_names | |
[alt_names] | |
DNS.1 = $domain | |
DNS.2 = *.$domain | |
EOF | |
# Create the Certificate Signing Request (CSR) | |
openssl req -new -key "$CERTS_DIR/$domain.key" -out "$CERTS_DIR/$domain.csr" \ | |
-config "$CERTS_DIR/$domain.cnf" | |
# Create the certificate extension file | |
cat > "$CERTS_DIR/$domain.ext" << EOF | |
authorityKeyIdentifier=keyid,issuer | |
basicConstraints=CA:FALSE | |
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment | |
subjectAltName = @alt_names | |
[alt_names] | |
DNS.1 = $domain | |
DNS.2 = *.$domain | |
EOF | |
# Sign the CSR with the CA | |
openssl x509 -req -in "$CERTS_DIR/$domain.csr" \ | |
-CA "$CA_DIR/$ca_name.crt" -CAkey "$CA_DIR/$ca_name.key" \ | |
-out "$CERTS_DIR/$domain.crt" \ | |
-extfile "$CERTS_DIR/$domain.ext" \ | |
-days "$days" -sha256 | |
# Copy the certificates to the current directory for easy access | |
cp "$CERTS_DIR/$domain.key" "./$domain.key" | |
cp "$CERTS_DIR/$domain.crt" "./$domain.crt" | |
echo "Certificate has been created:" | |
echo " - Private key: $domain.key" | |
echo " - Certificate: $domain.crt" | |
} | |
# Install a certificate (Linux only) | |
install_cert() { | |
if [ -z "$1" ]; then | |
echo "Error: Certificate type is required" | |
echo "Usage: $(basename "$0") -i <ca-name|domain>" | |
exit 1 | |
fi | |
# Check if we're on Linux | |
if [ "$(uname)" != "Linux" ]; then | |
echo "Error: The -i option is only supported on Linux." | |
echo "For macOS or Windows, please follow the manual installation instructions:" | |
echo " $(basename "$0") -h" | |
exit 1 | |
fi | |
# Check if we have the necessary permissions and tools | |
if ! command -v update-ca-certificates > /dev/null; then | |
echo "Error: update-ca-certificates command not found." | |
echo "Please install the ca-certificates package:" | |
echo " sudo apt-get install ca-certificates # For Debian/Ubuntu" | |
echo " sudo yum install ca-certificates # For RHEL/CentOS" | |
exit 1 | |
fi | |
if [ ! -w "/usr/local/share/ca-certificates" ]; then | |
echo "Error: You need root permissions to install certificates." | |
echo "Please run this command with sudo:" | |
echo " sudo $(basename "$0") -i $1" | |
exit 1 | |
fi | |
local cert_type="$1" | |
# First check if it's a CA | |
if [ -f "$CA_DIR/$cert_type.crt" ]; then | |
# It's a CA | |
echo "Installing CA certificate '$cert_type' into system trust store..." | |
cp "$CA_DIR/$cert_type.crt" "/usr/local/share/ca-certificates/$cert_type.crt" | |
update-ca-certificates | |
echo "CA certificate '$cert_type' has been installed successfully." | |
else | |
# Check if it's a domain certificate | |
if [ ! -f "$CERTS_DIR/$cert_type.crt" ]; then | |
echo "Error: Certificate for $cert_type not found." | |
echo "Available certificates:" | |
find "$CERTS_DIR" -name "*.crt" | sed -e 's|.*/||' -e 's|\.crt$||' | sort | |
echo "" | |
echo "Create the certificate first with: $(basename "$0") -cert $cert_type" | |
exit 1 | |
fi | |
echo "Copying domain certificate to /etc/ssl/certs..." | |
cp "$CERTS_DIR/$cert_type.crt" "/etc/ssl/certs/$cert_type.pem" | |
echo "Certificate has been copied. Note that applications may need additional configuration." | |
fi | |
} | |
# Renew a certificate or CA | |
renew_cert() { | |
if [ -z "$1" ]; then | |
echo "Error: Certificate or CA name is required" | |
echo "Usage: $(basename "$0") -r <ca-name|domain>" | |
exit 1 | |
fi | |
local name="$1" | |
# Check if it's a CA certificate | |
if [ -f "$CA_DIR/$name.key" ] && [ -f "$CA_DIR/$name.crt" ]; then | |
# Get the current CA expiration date | |
local expiry=$(openssl x509 -enddate -noout -in "$CA_DIR/$name.crt" | cut -d= -f 2) | |
local subject=$(openssl x509 -subject -noout -in "$CA_DIR/$name.crt" | sed 's/subject= //') | |
echo "Found Certificate Authority: $name" | |
echo "Subject: $subject" | |
echo "Current expiration date: $expiry" | |
echo "" | |
echo "WARNING: Renewing a CA certificate will require all certificates signed by this CA" | |
echo "to be re-issued. This operation cannot be undone." | |
echo "" | |
read -p "Do you want to renew this CA certificate? (y/N): " confirm | |
if [[ "$confirm" != [yY] && "$confirm" != [yY][eE][sS] ]]; then | |
echo "Operation cancelled." | |
exit 0 | |
fi | |
# Get the current configuration | |
local days="${CA_DAYS:-$DEFAULT_CA_DAYS}" | |
# Backup the old CA files | |
local timestamp=$(date +%Y%m%d%H%M%S) | |
mkdir -p "$CA_DIR/backup" | |
cp "$CA_DIR/$name.key" "$CA_DIR/backup/$name.key.$timestamp" | |
cp "$CA_DIR/$name.crt" "$CA_DIR/backup/$name.crt.$timestamp" | |
cp "$CA_DIR/$name.cnf" "$CA_DIR/backup/$name.cnf.$timestamp" 2>/dev/null || true | |
echo "Creating renewed CA certificate..." | |
# Check if the key is password-protected | |
if openssl rsa -in "$CA_DIR/$name.key" -check -noout 2>/dev/null; then | |
echo "The CA private key is not password-protected." | |
else | |
echo "The CA private key is password-protected." | |
echo "You will be prompted to enter the password for the CA private key." | |
fi | |
# Create a new CA certificate using the existing key | |
if [ -f "$CA_DIR/$name.cnf" ]; then | |
# Use the existing configuration | |
openssl req -x509 -new -nodes -key "$CA_DIR/$name.key" -sha256 -days "$days" \ | |
-out "$CA_DIR/$name.crt" -config "$CA_DIR/$name.cnf" | |
else | |
# Get environment variables or default values since we don't have the config | |
local country="${CERT_COUNTRY:-$DEFAULT_COUNTRY}" | |
local state="${CERT_STATE:-$DEFAULT_STATE}" | |
local locality="${CERT_LOCALITY:-$DEFAULT_LOCALITY}" | |
local organization="${CERT_ORG:-$DEFAULT_ORGANIZATION}" | |
local ou="${CERT_OU:-$DEFAULT_OU}" | |
local cn="${CA_CN:-$DEFAULT_CA_CN}" | |
# Create a new config file | |
cat > "$CA_DIR/$name.cnf" << EOF | |
[req] | |
distinguished_name = req_distinguished_name | |
x509_extensions = v3_ca | |
prompt = no | |
[req_distinguished_name] | |
C = $country | |
ST = $state | |
L = $locality | |
O = $organization | |
OU = $ou | |
CN = $cn ($name) | |
[v3_ca] | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid:always,issuer | |
basicConstraints = critical, CA:true | |
keyUsage = critical, digitalSignature, cRLSign, keyCertSign | |
EOF | |
# Create the renewed CA certificate | |
openssl req -x509 -new -nodes -key "$CA_DIR/$name.key" -sha256 -days "$days" \ | |
-out "$CA_DIR/$name.crt" -config "$CA_DIR/$name.cnf" | |
fi | |
echo "Certificate Authority '$name' has been renewed:" | |
echo " - Private key: $CA_DIR/$name.key (unchanged)" | |
echo " - Certificate: $CA_DIR/$name.crt (renewed)" | |
echo " - Old certificate backed up: $CA_DIR/backup/$name.crt.$timestamp" | |
echo "" | |
echo "Don't forget to:" | |
echo "1. Re-install this CA certificate on your systems" | |
echo "2. Re-issue all certificates that were signed by this CA" | |
elif [ -f "$CERTS_DIR/$name.key" ] && [ -f "$CERTS_DIR/$name.crt" ]; then | |
# It's a domain certificate | |
# Get information about the certificate | |
local expiry=$(openssl x509 -enddate -noout -in "$CERTS_DIR/$name.crt" | cut -d= -f 2) | |
local subject=$(openssl x509 -subject -noout -in "$CERTS_DIR/$name.crt" | sed 's/subject= //') | |
local issuer=$(openssl x509 -issuer -noout -in "$CERTS_DIR/$name.crt" | sed 's/issuer= //') | |
# Try to determine which CA signed this certificate | |
local ca_name="" | |
for ca in $(find "$CA_DIR" -name "*.crt" | sed -e 's|.*/||' -e 's|\.crt$||'); do | |
local ca_subject=$(openssl x509 -subject -noout -in "$CA_DIR/$ca.crt" | sed 's/subject= //') | |
if [ "$ca_subject" = "$issuer" ]; then | |
ca_name="$ca" | |
break | |
fi | |
done | |
if [ -z "$ca_name" ]; then | |
# If we couldn't find the CA by subject, try to find it by checking the signature | |
for ca in $(find "$CA_DIR" -name "*.crt" | sed -e 's|.*/||' -e 's|\.crt$||'); do | |
if openssl verify -CAfile "$CA_DIR/$ca.crt" "$CERTS_DIR/$name.crt" > /dev/null 2>&1; then | |
ca_name="$ca" | |
break | |
fi | |
done | |
fi | |
if [ -z "$ca_name" ]; then | |
echo "Error: Could not determine which CA signed this certificate." | |
echo "Available CAs:" | |
list_cas | |
echo "" | |
read -p "Enter the CA name that signed this certificate: " ca_name | |
if [ ! -f "$CA_DIR/$ca_name.key" ] || [ ! -f "$CA_DIR/$ca_name.crt" ]; then | |
echo "Error: CA '$ca_name' not found." | |
exit 1 | |
fi | |
fi | |
echo "Found certificate: $name" | |
echo "Subject: $subject" | |
echo "Issuer: $issuer" | |
echo "Current expiration date: $expiry" | |
echo "Signed by CA: $ca_name" | |
echo "" | |
read -p "Do you want to renew this certificate? (y/N): " confirm | |
if [[ "$confirm" != [yY] && "$confirm" != [yY][eE][sS] ]]; then | |
echo "Operation cancelled." | |
exit 0 | |
fi | |
# Backup the old certificate | |
local timestamp=$(date +%Y%m%d%H%M%S) | |
mkdir -p "$CERTS_DIR/backup" | |
cp "$CERTS_DIR/$name.key" "$CERTS_DIR/backup/$name.key.$timestamp" 2>/dev/null || true | |
cp "$CERTS_DIR/$name.crt" "$CERTS_DIR/backup/$name.crt.$timestamp" 2>/dev/null || true | |
cp "$CERTS_DIR/$name.csr" "$CERTS_DIR/backup/$name.csr.$timestamp" 2>/dev/null || true | |
cp "$CERTS_DIR/$name.cnf" "$CERTS_DIR/backup/$name.cnf.$timestamp" 2>/dev/null || true | |
cp "$CERTS_DIR/$name.ext" "$CERTS_DIR/backup/$name.ext.$timestamp" 2>/dev/null || true | |
# Check if the certificate key is password-protected | |
if openssl rsa -in "$CERTS_DIR/$name.key" -check -noout 2>/dev/null; then | |
echo "The certificate private key is not password-protected." | |
else | |
echo "The certificate private key is password-protected." | |
echo "You will be prompted to enter the password for the certificate private key." | |
fi | |
# Check if the CA key is password-protected | |
if openssl rsa -in "$CA_DIR/$ca_name.key" -check -noout 2>/dev/null; then | |
echo "The CA private key is not password-protected." | |
else | |
echo "The CA private key is password-protected." | |
echo "You will be prompted to enter the password for the CA private key." | |
fi | |
# Use existing configuration if possible | |
if [ -f "$CERTS_DIR/$name.cnf" ] && [ -f "$CERTS_DIR/$name.ext" ]; then | |
echo "Renewing certificate using existing configuration..." | |
# Create a new CSR using the existing key and config | |
openssl req -new -key "$CERTS_DIR/$name.key" -out "$CERTS_DIR/$name.csr" \ | |
-config "$CERTS_DIR/$name.cnf" | |
# Sign the new CSR with the CA | |
local days="${CERT_DAYS:-$DEFAULT_CERT_DAYS}" | |
openssl x509 -req -in "$CERTS_DIR/$name.csr" \ | |
-CA "$CA_DIR/$ca_name.crt" -CAkey "$CA_DIR/$ca_name.key" \ | |
-out "$CERTS_DIR/$name.crt" \ | |
-extfile "$CERTS_DIR/$name.ext" \ | |
-days "$days" -sha256 | |
# Copy the renewed certificate to the current directory | |
cp "$CERTS_DIR/$name.crt" "./$name.crt" | |
echo "Certificate for '$name' has been renewed:" | |
echo " - Private key: $name.key (unchanged)" | |
echo " - Certificate: $name.crt (renewed)" | |
echo " - Old certificate backed up: $CERTS_DIR/backup/$name.crt.$timestamp" | |
else | |
echo "Error: Cannot find required configuration files for renewal." | |
echo "You may need to re-create the certificate from scratch:" | |
echo " $(basename "$0") -cert $name $ca_name" | |
exit 1 | |
fi | |
else | |
echo "Error: Certificate or CA '$name' not found." | |
echo "" | |
echo "Available CAs:" | |
list_cas | |
echo "" | |
echo "Available certificates:" | |
find "$CERTS_DIR" -name "*.crt" | sed -e 's|.*/||' -e 's|\.crt$||' | sort | |
exit 1 | |
fi | |
} | |
# Remove password from an existing key | |
remove_password() { | |
if [ -z "$1" ]; then | |
echo "Error: Certificate or CA name is required" | |
echo "Usage: $(basename "$0") -rmpw <ca-name|domain>" | |
exit 1 | |
fi | |
local name="$1" | |
local key_path="" | |
local backup_dir="" | |
# Check if it's a CA key | |
if [ -f "$CA_DIR/$name.key" ]; then | |
key_path="$CA_DIR/$name.key" | |
backup_dir="$CA_DIR/backup" | |
echo "Found CA key: $key_path" | |
# Check if it's a certificate key | |
elif [ -f "$CERTS_DIR/$name.key" ]; then | |
key_path="$CERTS_DIR/$name.key" | |
backup_dir="$CERTS_DIR/backup" | |
echo "Found certificate key: $key_path" | |
else | |
echo "Error: Key for '$name' not found." | |
echo "" | |
echo "Available CAs:" | |
list_cas | |
echo "" | |
echo "Available certificates:" | |
find "$CERTS_DIR" -name "*.key" | sed -e 's|.*/||' -e 's|\.key$||' | sort | |
exit 1 | |
fi | |
# Check if the key is already unprotected | |
if openssl rsa -in "$key_path" -check -noout 2>/dev/null; then | |
echo "The key is already not password-protected." | |
exit 0 | |
fi | |
echo "This key is password-protected." | |
echo "You will be prompted to enter the current password." | |
echo "" | |
echo "WARNING: Removing the password from a key reduces its security." | |
echo "Anyone with access to the key file will be able to use it without a password." | |
echo "" | |
read -p "Do you want to continue? (y/N): " confirm | |
if [[ "$confirm" != [yY] && "$confirm" != [yY][eE][sS] ]]; then | |
echo "Operation cancelled." | |
exit 0 | |
fi | |
# Backup the original key | |
local timestamp=$(date +%Y%m%d%H%M%S) | |
mkdir -p "$backup_dir" | |
cp "$key_path" "$backup_dir/$(basename "$key_path").$timestamp" | |
# Create a temporary key file | |
local temp_key="${key_path}.temp" | |
# Remove the password | |
openssl rsa -in "$key_path" -out "$temp_key" | |
# Replace the original key with the unprotected one | |
mv "$temp_key" "$key_path" | |
echo "Password has been removed from the key." | |
echo "Original key backed up to: $backup_dir/$(basename "$key_path").$timestamp" | |
} | |
# Main program | |
case "$1" in | |
-h|--help) | |
show_help | |
;; | |
-nopw) | |
USE_PASSWORD=false | |
shift | |
if [ -z "$1" ]; then | |
echo "Error: -nopw must be followed by another command" | |
echo "Example: $(basename "$0") -nopw -ca mycompany" | |
exit 1 | |
fi | |
case "$1" in | |
-ca) | |
create_ca "$2" | |
;; | |
-cert) | |
create_cert "$2" "$3" | |
;; | |
-r) | |
renew_cert "$2" | |
;; | |
-rmpw) | |
remove_password "$2" | |
;; | |
*) | |
echo "Error: -nopw can only be used with -ca, -cert, or -r" | |
exit 1 | |
;; | |
esac | |
;; | |
-ca) | |
create_ca "$2" | |
;; | |
-cert) | |
create_cert "$2" "$3" | |
;; | |
-i) | |
install_cert "$2" | |
;; | |
-list) | |
list_cas | |
;; | |
-r) | |
renew_cert "$2" | |
;; | |
-rmpw) | |
remove_password "$2" | |
;; | |
*) | |
echo "Unknown parameter: $1" | |
echo "Use -h or --help for help." | |
exit 1 | |
;; | |
esac | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's a summary of the
certhelper.sh
script and its functions:Files and Directories
Main directories:
./ca/
- Storage location for all Certificate Authority (CA) files./certs/
- Storage location for all domain certificates./ca/backup/
- Backups of renewed CA certificates./certs/backup/
- Backups of renewed domain certificatesCA files (for each CA with name
<name>
):ca/<name>.key
- Private key of the CAca/<name>.crt
- Public certificate of the CAca/<name>.cnf
- OpenSSL configuration for the CAca/<name>.srl
- Serial number for signed certificatesDomain certificate files (for each domain
<domain>
):certs/<domain>.key
- Private keycerts/<domain>.crt
- Public certificatecerts/<domain>.csr
- Certificate Signing Requestcerts/<domain>.cnf
- OpenSSL configuration for this domaincerts/<domain>.ext
- Extension file for the certificate.key
and.crt
in the current directory for easy accessSystem installation locations:
/usr/local/share/ca-certificates/<name>.crt
/etc/ssl/certs/<domain>.pem
Using the Script
Create a CA:
Creates a new CA named "mycompany" (or "rootca" as default if no name is specified)
Create a certificate:
Creates a certificate for "nas.lan", signed by the CA "mycompany"
Install a CA on the system (Linux only):
Installs the CA in the system trust store and updates CA certificates
List CAs:
Shows all available CAs with their subjects
Renew a certificate or CA:
or
Renews either a domain certificate or a CA with backup of the old files
Show help:
Shows detailed help and installation instructions for different operating systems
Installation Notes by Operating System
Linux:
-i
option copies CA certificates to/usr/local/share/ca-certificates/
and runsupdate-ca-certificates
/etc/ssl/certs/
macOS:
Windows:
Import-Certificate -FilePath ca\mycompany.crt -CertStoreLocation Cert:\LocalMachine\Root
The script organizes all certificates and CAs neatly and allows for using multiple CAs for different purposes. It facilitates management through functions like renewal, backup, and verification of whether files already exist.