#!/bin/bash

# Copyright (c) Veeam Software Group GmbH

set -eE -u -o pipefail

SCRIPT_DIR=$(dirname "$(realpath "${BASH_SOURCE[0]}")"); readonly SCRIPT_DIR;
source "$SCRIPT_DIR/lib/error-handle.bash"
source "$SCRIPT_DIR/lib/optparser.bash"
source "$SCRIPT_DIR/lib/verbose.bash"
source "$SCRIPT_DIR/lib/common.bash"

setlocale en_US.utf8 || :
# shellcheck disable=SC2034
declare -A op=()
declare -A ARGS=()

optparser-init op \
    --desc "Generate X.509 certificate for Nginx."
optparser-addopt op --name "certpath" --narg 1 \
    --help "path to certificate"
optparser-addopt op -s "-f" -l "--force" \
    --help "overwrite existing certificates"
optparser-addopt op -s "-m" -l "--mode" --narg 1 --default 600 \
    --help "set permission mode (as in chmod)"
optparser-addopt op -s "-o" -l "--owner" --narg 1 \
    --help "set ownership"
optparser-addopt op -s "-g" -l "--group" --narg 1 \
    --help "set group ownership"
optparser-addopt op -s "-d" -l "--days" --narg 1 --default 3650 \
    --help "number of days certificate is valid for"
optparser-addopt op -s "-v" -l "--verbose" \
    --help "provide more detailed output"
optparser-addopt op -s "-h" -l "--help" \
    --help "show this help message and exit"
optparser-ignore-required op help
optparser-parse op ARGS "$@" || exit 1
[[ -n ${ARGS[help]:-} ]] && { optparser-help op; exit 0; }
[[ -n ${ARGS[verbose]:-} ]] && { verbose-enable; }
[[ ${ARGS[days]} =~ ^[0-9]+$ ]] || die "days must be a positive integer"
(( ARGS[days] > 0 )) || die "days must be a positive integer"

trap-init

if [[ -z ${ARGS[force]:-} && -f ${ARGS[certpath]:-} ]]; then
    die "${ARGS[certpath]:-}: file exists"
fi

fqdn=$(hostname -f)
keypath=${ARGS[certpath]%.crt}.key
stderr=2
is-verbose || mktempfd stderr
r=0
openssl req -newkey rsa:4096 \
            -x509 \
            -sha256 \
            -days "${ARGS[days]}" \
            -nodes \
            -out "${ARGS[certpath]}" \
            -keyout "$keypath" \
            -subj "/CN=$fqdn" \
    2>&"$stderr" || r=$?

if (( r )); then
    is-verbose || cat /proc/self/fd/"$stderr" >&2
    exit $r
fi

verbose-echo "crt: ${ARGS[certpath]}"
verbose-echo "key: $keypath"

# shellcheck disable=SC2046
chown $(verbose-arg -v) "${ARGS[owner]:-}:${ARGS[group]:-}" "${ARGS[certpath]}" "$keypath"
# shellcheck disable=SC2046
chmod $(verbose-arg -v) "${ARGS[mode]}" "${ARGS[certpath]}" "$keypath"
