You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

224 lines
5.9 KiB

#!/bin/ash
# ---------------------------------------------------------------------------
# getsslD - Obtain SSL certificates from the letsencrypt.org ACME server.
# Runs in a Docker conatainer.
# Based on the work of getssl by srvrco https://github.com/srvrco/getssl
# and acme.sh by Neil Pang http://Neilpang/acme.sh
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License at <http://www.gnu.org/licenses/> for
# more details.
PROGNAME=getsslD
VERSION="0.2"
# Default values, accepts environment variables if set, otherwise default are used
WORKING_DIR=${WORKING_DIR:="/ssl}"
ACCOUNT_KEY_LOCATION=${ACCOUNT_KEY_LOCATION:="$WORKING_DIR/account.key"}
ACCOUNT_KEY_LENGTH=${ACCOUNT_KEY_LENGTH:="4096"}
ACCOUNT_KEY_TYPE=${ACCOUNT_KEY_TYPE:="rsa"}
#####
# Functions
#####
create_key() {
# Create an openSSL key
local key_loc=${1}
local key_len=${2}
local key_type=${3}
local valid_key_type
# Check for existing key
if [[ -s "${key_loc}" ]]; then
printf 'Key exists at %s skipping generation.\n' "${key_loc}"
return 0
elif [[ ! -d $(dirname "${key_loc}") ]]; then
print_error "Directory for storing ${key_loc} does not exist."
return 1
else
printf 'Creating %s bit %s account key in %s...' "${key_len}" "${key_type}" "${key_loc}"
fi
# Determine key type by length
# Valid Let's Encrypt RSA key lengths 2048-8192
# Valid Let's Encrypt ECC key lengths 256, 384, 521
if [[ "${key_len}" -ge 2048 ]] && [[ "${key_len}" -le 8192 ]] && [[ "${key_type}" == "rsa" ]]; then
valid_key_type="RSA"
fi
if [[ "${key_type}" == "ecc" ]]; then
if [[ "${key_len}" -eq 256 ]] ; then
valid_key_type="prime256v1"
elif [[ "${key_len}" -eq 384 ]]; then
valid_key_type="secp384r1"
elif [[ "${key_len}" -eq 521 ]]; then
valid_key_type="secp521r1"
fi
fi
if [[ -z ${valid_key_type+x} ]]; then
print_error "Invalid key length. Please check your configuration."
return 1
fi
case "$valid_key_type" in
RSA)
openssl genrsa -out "${key_loc}" "${key_len}" >& /dev/null
printf '%s\n' "Done."
return 0
;;
prime256v1|secp384r1|secp521r1)
openssl ecparam -genkey -out "${key_loc}" -name "${valid_key_type}" >& /dev/null
printf '%s\n' "Done."
return 0
;;
esac
# Error inside case statement openssl generation
print_error "Error creating OpenSSL key, deleting key..."
rm "${key_loc}"
print_error "Done.\n"
return 1
}
get_date() {
# get current date and time in UTC YYYY-MM-DDTHH:MM:SSZ
echo $(date -u +"%Y-%m-%dT%H:%M:%SZ")
}
help_message_top() {
# Print help message
cat <<- _EOF_
Usage: "${PROGNAME}" [option] [COMMAND] [ARGS...]
Obtain SSL certificates from the letsencrypt.org ACME server.
Commands:
account Create or modify Lets Encrypt account.
Options to long options apply to short options also.
Options:
-r, --rsa Use RSA algorith for key generation
-e, --ecc Use elliptic curve algorithm for key or cert generation
_EOF_
return 0
}
prep_workdir() {
# Prepare working directory for key/cert functions
if [[ ! -d "${WORKING_DIR}" ]]; then
printf '%s' "Creating getsslD certificate storage directory - ${WORKING_DIR}..."
if ! mkdir -p "${WORKING_DIR}" >& /dev/null; then
print_error "Could not create ${WORKING_DIR}. Check volumes.\n"
exit 1
else
printf '%s\n' "Done."
fi
fi
return 0
}
print_error() {
# Output error messages to STDERR
local error=$1
printf '!! %s\n' "${1}" 1>&2
return 0
}
arg_parser() {
# Check CLI arguments and process
local key_type
local key_length
while [[ -n ${1} ]]; do
case ${1} in
-r | --rsa)
shift
key_type="rsa"
;;
-e | --ecc)
shift
key_type="ecc"
;;
-h | --help)
help_message_top
exit 0
;;
-v | --version)
printf '%s version %s\n' ${PROGNAME} ${VERSION}
exit 0
;;
account)
# Remove account command
shift
case $1 in
key)
# Remove key subcommand
shift
# If no key type specified on the command line
# https://stackoverflow.com/a/13864829
if [[ -z "${key_type+x}" ]]; then
# No key types specified use default of RSA or environment variable
key_type="${ACCOUNT_KEY_TYPE:=rsa}"
printf 'No key type specified, using default of %s\n' "${key_type}"
fi
# We have a key type need length
# If no key length specified on the command line
if [[ -z "${1}" ]]; then
# No length specified, use default of 4096 or environment variable
key_length="${ACCOUNT_KEY_LENGTH:=4096}"
printf 'No key length specified, using default of %s\n' "${key_length}"
else
key_length="${1}"
fi
create_key "${ACCOUNT_KEY_LOCATION}" "${key_length}" "${key_type}"
exit 0
;;
esac # End account subcommands
;;
*)
printf 'Invalid command\n\n'
help_message_top
exit 1
;;
esac # End options
done
}
#####
# Main logic
#####
main() {
# read any variables from config in working directory
if [[ -s "$WORKING_DIR/getsslD.cfg" ]]; then
printf '%s\n'"Reading config from from $WORKING_DIR/getsslD.cfg"
. "$WORKING_DIR/getsslD.cfg"
fi
arg_parser $*
}
# Only run main if we are not testing.
if [[ "${GETSSLD_TEST}" != true ]]; then
main $@
fi