subcommands
Signed-off-by: fbt <fbt@fleshless.org>
This commit is contained in:
parent
a919c17dee
commit
495175cd96
158
le
158
le
|
@ -1,159 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
err() {
|
subcommand=$1; shift
|
||||||
printf '%s\n' "$*" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
msg() {
|
source "sub/$subcommand" "$@"
|
||||||
printf '%s\n' "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
set_default() {
|
|
||||||
declare -n _vref=$1
|
|
||||||
|
|
||||||
if ! [[ "$_vref" ]]; then
|
|
||||||
_vref=$2
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_san_string() {
|
|
||||||
declare d
|
|
||||||
declare -a argv
|
|
||||||
|
|
||||||
argv=( "$@" )
|
|
||||||
|
|
||||||
printf '[SAN]\nsubjectAltName='
|
|
||||||
|
|
||||||
for d in "${argv[@]}"; do
|
|
||||||
printf 'DNS:%s' "$d"
|
|
||||||
if ! [[ "$d" == "${argv[-1]}" ]]; then
|
|
||||||
printf ','
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_renew_config() {
|
|
||||||
declare d
|
|
||||||
|
|
||||||
printf 'domains=(\n'
|
|
||||||
for d in "$@"; do
|
|
||||||
printf " %s\n" "$d"
|
|
||||||
done
|
|
||||||
printf ')\n'
|
|
||||||
}
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
while read -r line; do printf '%s\n' "$line"; done <<- EOF
|
|
||||||
Usage: le [options] <-d domain> [-d domain] ...
|
|
||||||
Options:
|
|
||||||
-c <dir> # Configuration directory. Default: \$HOME/.acme
|
|
||||||
-a <dir> # A dir to put challenges in. Default: /tmp/acme/challenges
|
|
||||||
-d <domain> # Domain to issue the certificate for.
|
|
||||||
# Can be specified multiple time for multi-domain certs.
|
|
||||||
-h # Show this message.
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
declare cfg_dir
|
|
||||||
declare -a domains
|
|
||||||
|
|
||||||
while (( $# )); do
|
|
||||||
case $1 in
|
|
||||||
-c)
|
|
||||||
cfg_dir=$2
|
|
||||||
shift;;
|
|
||||||
|
|
||||||
-a)
|
|
||||||
challenge_dir=$2
|
|
||||||
shift;;
|
|
||||||
|
|
||||||
-d)
|
|
||||||
domains+=( "$2" )
|
|
||||||
shift;;
|
|
||||||
|
|
||||||
-h)
|
|
||||||
usage
|
|
||||||
return 0;;
|
|
||||||
|
|
||||||
--)
|
|
||||||
shift
|
|
||||||
break;;
|
|
||||||
|
|
||||||
*) break;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
if ! (( ${#domains[@]} )); then
|
|
||||||
err "Use -d, luke"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
set_default cfg_dir "$HOME/.acme"
|
|
||||||
set_default challenge_dir '/tmp/acme/challenges'
|
|
||||||
|
|
||||||
if ! [[ -d "$cfg_dir" ]]; then
|
|
||||||
err "Config dir ($cfg_dir) not found, creating."
|
|
||||||
if ! mkdir -m700 "$cfg_dir"; then
|
|
||||||
err "Can't create config dir: $cfg_dir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [[ -f "$cfg_dir/account.key" ]]; then
|
|
||||||
err "Account key not found, generating a new one."
|
|
||||||
openssl genrsa 4096 > "$cfg_dir/account.key"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [[ -d "$cfg_dir/domains/${domains[0]}" ]]; then
|
|
||||||
mkdir -p "$cfg_dir/domains/${domains[0]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [[ -f "$cfg_dir/domains/${domains[0]}/privkey.pem" ]]; then
|
|
||||||
err "Generating a new key for ${domains[0]}."
|
|
||||||
openssl genrsa 4096 > "$cfg_dir/domains/${domains[0]}/privkey.pem"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [[ -d "$challenge_dir" ]]; then
|
|
||||||
err "Challenge dir does not exist: $challenge_dir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
err "Generating a certificate request for: ${domains[@]}."
|
|
||||||
if (( ${#domains[@]} > 1 )); then
|
|
||||||
openssl req -new -sha256 \
|
|
||||||
-key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
|
|
||||||
-subj "/" \
|
|
||||||
-reqexts SAN \
|
|
||||||
-config <(cat /etc/ssl/openssl.cnf <(gen_san_string "${domains[@]}")) > "$cfg_dir/domains/${domains[0]}/request.csr"
|
|
||||||
else
|
|
||||||
openssl req -new -sha256 \
|
|
||||||
-key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
|
|
||||||
-subj "/CN=${domains[0]}" > "$cfg_dir/domains/${domains[0]}/request.csr"
|
|
||||||
fi
|
|
||||||
|
|
||||||
err "Getting a signed certificate."
|
|
||||||
acme-tiny \
|
|
||||||
--account-key "$cfg_dir/account.key" \
|
|
||||||
--csr "$cfg_dir/domains/${domains[0]}/request.csr" \
|
|
||||||
--acme-dir "$challenge_dir" > "$cfg_dir/domains/${domains[0]}/certificate.pem"
|
|
||||||
|
|
||||||
if (( $? )); then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
gen_renew_config "${domains[@]}" > "$cfg_dir/domains/${domains[0]}/renew.cfg"
|
|
||||||
|
|
||||||
if ! [[ -f "$cfg_dir/chain.pem" ]]; then
|
|
||||||
err "Intermediate certificate not found, downloading."
|
|
||||||
curl "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem" > "$cfg_dir/letsencrypt.pem"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat "$cfg_dir/domains/${domains[0]}/certificate.pem" "$cfg_dir/letsencrypt.pem" > "$cfg_dir/domains/${domains[0]}/fullchain.pem"
|
|
||||||
|
|
||||||
err "Your certificate is available at $cfg_dir/domains/${domains[0]}/fullchain.pem"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
|
|
154
sub/issue
Executable file
154
sub/issue
Executable file
|
@ -0,0 +1,154 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
err() {
|
||||||
|
printf '%s\n' "$*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
msg() {
|
||||||
|
printf '%s\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
set_default() {
|
||||||
|
declare -n _vref=$1
|
||||||
|
|
||||||
|
if ! [[ "$_vref" ]]; then
|
||||||
|
_vref=$2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_san_string() {
|
||||||
|
declare d
|
||||||
|
declare -a argv
|
||||||
|
|
||||||
|
argv=( "$@" )
|
||||||
|
|
||||||
|
printf '[SAN]\nsubjectAltName='
|
||||||
|
|
||||||
|
for d in "${argv[@]}"; do
|
||||||
|
printf 'DNS:%s' "$d"
|
||||||
|
if ! [[ "$d" == "${argv[-1]}" ]]; then
|
||||||
|
printf ','
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_renew_config() {
|
||||||
|
declare d
|
||||||
|
|
||||||
|
printf 'domains=(\n'
|
||||||
|
for d in "$@"; do
|
||||||
|
printf " %s\n" "$d"
|
||||||
|
done
|
||||||
|
printf ')\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
while read -r line; do printf '%s\n' "$line"; done <<- EOF
|
||||||
|
Usage: le [options] <domain> [domain ...]
|
||||||
|
Options:
|
||||||
|
-c <dir> # Configuration directory. Default: \$HOME/.acme
|
||||||
|
-a <dir> # A dir to put challenges in. Default: /var/www/acme
|
||||||
|
-h # Show this message.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
declare cfg_dir
|
||||||
|
declare -a domains
|
||||||
|
|
||||||
|
while (( $# )); do
|
||||||
|
case $1 in
|
||||||
|
-c)
|
||||||
|
cfg_dir=$2
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-a)
|
||||||
|
challenge_dir=$2
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-h)
|
||||||
|
usage
|
||||||
|
return 0;;
|
||||||
|
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break;;
|
||||||
|
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
domains=( "$@" )
|
||||||
|
|
||||||
|
(( ${#domains[@]} )) || {
|
||||||
|
usage; return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
set_default cfg_dir "$HOME/.acme"
|
||||||
|
set_default challenge_dir '/var/www/acme'
|
||||||
|
|
||||||
|
if ! [[ -d "$cfg_dir" ]]; then
|
||||||
|
err "Config dir ($cfg_dir) not found, creating."
|
||||||
|
if ! mkdir -m700 "$cfg_dir"; then
|
||||||
|
err "Can't create config dir: $cfg_dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ -f "$cfg_dir/account.key" ]]; then
|
||||||
|
err "Account key not found, generating a new one."
|
||||||
|
openssl genrsa 4096 > "$cfg_dir/account.key"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ -d "$cfg_dir/domains/${domains[0]}" ]]; then
|
||||||
|
mkdir -p "$cfg_dir/domains/${domains[0]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ -f "$cfg_dir/domains/${domains[0]}/privkey.pem" ]]; then
|
||||||
|
err "Generating a new key for ${domains[0]}."
|
||||||
|
openssl genrsa 4096 > "$cfg_dir/domains/${domains[0]}/privkey.pem"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ -d "$challenge_dir" ]]; then
|
||||||
|
err "Challenge dir does not exist: $challenge_dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
err "Generating a certificate request for: ${domains[@]}."
|
||||||
|
if (( ${#domains[@]} > 1 )); then
|
||||||
|
openssl req -new -sha256 \
|
||||||
|
-key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
|
||||||
|
-subj "/" \
|
||||||
|
-reqexts SAN \
|
||||||
|
-config <(cat /etc/ssl/openssl.cnf <(gen_san_string "${domains[@]}")) > "$cfg_dir/domains/${domains[0]}/request.csr"
|
||||||
|
else
|
||||||
|
openssl req -new -sha256 \
|
||||||
|
-key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
|
||||||
|
-subj "/CN=${domains[0]}" > "$cfg_dir/domains/${domains[0]}/request.csr"
|
||||||
|
fi
|
||||||
|
|
||||||
|
err "Getting a signed certificate."
|
||||||
|
acme-tiny \
|
||||||
|
--account-key "$cfg_dir/account.key" \
|
||||||
|
--csr "$cfg_dir/domains/${domains[0]}/request.csr" \
|
||||||
|
--acme-dir "$challenge_dir" > "$cfg_dir/domains/${domains[0]}/certificate.pem"
|
||||||
|
|
||||||
|
if (( $? )); then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
gen_renew_config "${domains[@]}" > "$cfg_dir/domains/${domains[0]}/renew.cfg"
|
||||||
|
|
||||||
|
if ! [[ -f "$cfg_dir/chain.pem" ]]; then
|
||||||
|
err "Intermediate certificate not found, downloading."
|
||||||
|
curl "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem" > "$cfg_dir/letsencrypt.pem"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat "$cfg_dir/domains/${domains[0]}/certificate.pem" "$cfg_dir/letsencrypt.pem" > "$cfg_dir/domains/${domains[0]}/fullchain.pem"
|
||||||
|
|
||||||
|
err "Your certificate is available at $cfg_dir/domains/${domains[0]}/fullchain.pem"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
Loading…
Reference in New Issue
Block a user