Combine scripts

This commit is contained in:
2020-08-01 20:44:22 -04:00
parent 1f063f2501
commit c7eb44ae5f
3 changed files with 18 additions and 313 deletions

View File

@@ -1,16 +1,12 @@
# WIP # WIP
This project contains two files: `acme-cpanel.sh` reads in a list of domains from one or more files. These files may only contain domains and empty lines (see `domains.txt` for example format).
`acme-cpanel-webroot.sh` (for webroot challenges) "*www.*" subdomains will be added automatically (do not add them to the domains file list).
`acme-cpanel-dns.sh` (for dns challenges, legacy script)
Both of these scripts read in a list of domains from one or more files. These files may only contain domains and empty lines (see `domains.txt`).
## Notes ## Notes
`acme-cpanel-webroot.sh` may require the following additions to .htaccess so that challenges are not automatically redirected to https: The `--method webroot` may require the following additions to .htaccess so that challenges are not automatically redirected to https:
```text ```text
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
@@ -23,32 +19,33 @@ Command-line (Linux):
* Move script to user home directory on the server: `scp ./* username@ip:port:~` * Move script to user home directory on the server: `scp ./* username@ip:port:~`
* Login to server: `ssh user@ip -p port` * Login to server: `ssh user@ip -p port`
* Make script executable: `chmod +x $HOME/acme-cpanel-webroot.s` * Make script executable: `chmod +x $HOME/acme-cpanel.sh`
* Run script (ex. `$HOME/acme-cpanel-webroot.sh -s multisites`) * Run script (ex. `$HOME/acme-cpanel.sh -s multisites`)
* Follow prompts to enter credentials, issue certificates, and deploy them * Follow prompts to enter credentials, issue certificates, and deploy them
* Double-check that the acme cron job is enabled: `crontab -l` * Double-check that the acme cron job is enabled: `crontab -l`
cPanel: cPanel:
* Use File Manager to upload files to the home directory (/home/username/) * Use File Manager to upload files to the home directory (/home/username/)
* You may need to make file executable in Terminal: `chmod +x $HOME/acme-cpanel-webroot.sh` * You may need to make file executable in Terminal: `chmod +x $HOME/acme-cpanel.sh`
* Use Terminal to run the script (ex. `$HOME/acme-cpanel-webroot.sh -s multisites`) * Use Terminal to run the script (ex. `$HOME/acme-cpanel.sh -s multisites`)
* Follow prompts to enter credentials, issue certificates, and deploy them * Follow prompts to enter credentials, issue certificates, and deploy them
* Use Cron Jobs app to double-check that the acme cron job is present * Use Cron Jobs app to double-check that the acme cron job is present
## Usage ## Usage
### `./acme-cpanel-webroot.sh [OPTIONS] [FILES...]` ### `./acme-cpanel.sh [OPTIONS] [FILES...]`
#### Options #### Options
```text ```text
--method, -m webroot,dns
Choose the authentication method (default: dns)
--email, -e EMAIL --email, -e EMAIL
E-mail not be notified of certificate renewal failures E-mail not be notified of certificate renewal failures
--keep-grouping, -k --group-by-file, -g
Issue multidomain certificates based on grouping by input file Issue multidomain certificates for all domains with the same webroot, grouped by input file
The first domain in each file will be used to determine the shared webroot The first domain in each file will be used to determine the shared webroot
Default: issue certificates by independent domain
--sites-dir, -s DIR --sites-dir, -s DIR
Load domain list files from this directory Load domain list files from this directory
--force, -f --force, -f
@@ -59,18 +56,14 @@ cPanel:
#### Examples #### Examples
`./acme-cpanel-webroot.sh --force` `./acme-cpanel.sh --force`
Load sites from domains.txt, issue and deploy certificates Load sites from domains.txt, issue and deploy certificates using the webroot method
`./acme-cpanel-webroot.sh --force -s multisites` `./acme-cpanel.sh --method dns --force -s multisites`
Load sites from multisites directory, issue and deploy certificates Load sites from multisites directory, issue and deploy certificates using the dns method
`./acme-cpanel-webroot.sh --force -k multisites/flatwhitedesign.pw multisites/greengingerdesign.pw` `./acme-cpanel.sh --force -g multisites/flatwhitedesign.pw multisites/greengingerdesign.pw`
Load sites from multisites directory, issue and deploy multidomain certificates based on the grouping in the file. Load sites from multisites directory, issue and deploy multidomain certificates with same webroot based on the grouping in the file using the webroot method
### `./acme_cpanel_dns.sh`
This is a legacy script that takes no arguments. By default it will read all domain lists in a top-level "multisites" directory.

View File

@@ -1,87 +0,0 @@
#!/usr/bin/env bash
# This program will install and configure acme, request SSL certificates from Let's Encrypt, and enable them using the cPanel API
# Comment the following line to skip issuing a test certificate
test="true"
unset err
get_acme() {
curl https://get.acme.sh | sh
curl -o "$HOME/.acme.sh/dnsapi/dns_cpaneldns.sh" https://raw.githubusercontent.com/cryobry/dns_cpaneldns/master/dns_cpaneldns.sh
"$HOME/.acme.sh/acme.sh" --upgrade --auto-upgrade
}
run_config() {
if [[ -f "$HOME/.acme.sh/account.conf" ]]; then
if grep -q "CPANELDNS_AUTH_PASSWORD" "$HOME/.acme.sh/account.conf"; then
echo "cPanel credentials already present, skipping configuration..."
echo "To rerun the configuration, first run 'rm \$HOME/.acme.sh/account.conf'"
return 0
else
# Set contact e-mail for ACME failure
read -rp 'Enter the e-mail address to contact in case of acme failure: ' EMAIL
echo
"$HOME/.acme.sh/acme.sh" --update-account --accountemail "$EMAIL"
# Read in Namecheap API variables from user for acme
read -rp 'Enter your cPanel username: ' CPANELDNS_AUTH_ID
echo
export CPANELDNS_AUTH_ID
read -rp 'Enter your cPanel password: ' CPANELDNS_AUTH_PASSWORD
echo
export CPANELDNS_AUTH_PASSWORD
read -rp 'Enter your cPanel address and port number (example: "https://www.example.com:2083/"): ' CPANELDNS_API
echo
export CPANELDNS_API
fi
else
touch "$HOME/.acme.sh/account.conf"
run_config
fi
}
# Issue certificates
issue_cert() {
local multisite_file
for multisite_file in ./multisites/*; do
echo "Attempting to issue certificates for ${multisite_file##*/} and its multisites..."
unset sites issue_cmd deploy_cmd
declare -al sites issue_cmd deploy_cmd
readarray -t sites < "${multisite_file}"
issue_cmd=("$HOME/.acme.sh/acme.sh" "--issue" "--dns" "dns_cpaneldns")
deploy_cmd=("$HOME/.acme.sh/acme.sh" "--deploy" "--deploy-hook" "cpanel_uapi")
for site in "${sites[@]}"; do
[[ "$site" != "" ]] && issue_cmd+=("-d" "$site")
done
# if test enabled, issue test certificate first
if [[ "${test:-x}" == "true" ]]; then
"${issue_cmd[@]}" --staging
read -rp -n 1 "Was the certificate correctly issued without errors? [y/N]: "
echo
[[ ! "$REPLY" =~ ^[Yy]$ ]] && err=1 && return 1
fi
echo "Running:" "${issue_cmd[@]}"
if "${issue_cmd[@]}" --force; then
echo "Running:" "${deploy_cmd[@]}"
! "${deploy_cmd[@]}" && \
echo "Could not deploy" && \
err=1
else
echo "Could not issue"
err=1
fi
done
}
main() {
get_acme
run_config
issue_cert
}
main "$@"
exit "${err:-0}"

View File

@@ -1,201 +0,0 @@
#!/usr/bin/env bash
# This script uses acme.sh to issue and deploy SSL certificates from Let's Encrypt for a list of domains using the webroot method
# See README for more details
#
# Copyright 2020 Bryan Roessler <bryanroessler@gmail.com>
#
# USAGE
# ./acme-cpanel-webroot.sh [OPTIONS] [FILES...]
#
# EXAMPLES
# TESTING: ./acme-cpanel-webroot.sh --debug -e me@gmail.com multisites/flatwhitedesign.pw multisites/greengingermultisite.website
# PRODUCTION: ./acme-cpanel-webroot.sh --force -e me@gmail.com multisites/flatwhitedesign.pw multisites/greengingermultisite.website
#
# TESTING: ./acme-cpanel-webroot.sh --debug -s multisites
# PRODUCTION: ./acme-cpanel-webroot.sh --force -s multisites
#
# FILES is a list of files containing first-level DOMAIN names (see domains.txt) on newlines
# Certificates will automatically be issued and deployed for DOMAIN and www.DOMAIN using the webroot method
#
# NOTE: The webroot method does NOT support wildcard domains, Let's Encrypt requires wildcard domains to
# use DNS challenges, which the CPANEL uapi does not support (use dns_cpaneldns plugin instead)
unset SITES_DIR USEREMAIL DOMAIN_FILES DOMAIN_GROUPS DEPLOY_CMD_PREFIX ISSUE_CMD_PREFIX DEBUG GROUP
DEBUG="true" # quote this line to stop DEBUG mode and issue certificates for real, or use --force in user options
parse_input() {
local input
declare -g USEREMAIL
declare -ag DOMAIN_FILES
if input=$(getopt -o +e:fks:d -l email:,force,keep-grouping,sites-dir:,debug -- "$@"); then
eval set -- "$input"
while true; do
case "$1" in
--email|-e)
shift
USEREMAIL="$1"
;;
--force|-f)
unset DEBUG
;;
--keep-grouping|-k)
GROUP="true"
;;
--sites-dir|-s)
shift
SITES_DIR="$1"
;;
--debug|-d)
DEBUG="true"
;;
--)
shift
break
;;
esac
shift
done
else
echo "Incorrect options provided"
exit 1
fi
# Load domain files from remaining arguments
if [[ $# -lt 1 ]]; then
[[ -v SITES_DIR && -d "$SITES_DIR" ]] && return 0
if [[ -f "domains.txt" ]]; then
echo "You have not supplied any domain files, using domains.txt by default"
DOMAIN_FILES=("domains.txt")
else
echo "You must specify a domain list or use domains.txt by default"
exit 1
fi
else
DOMAIN_FILES=("$@")
fi
}
get_acme() {
curl https://get.acme.sh | sh
source "$HOME/.bashrc"
"$HOME/.acme.sh/acme.sh" --upgrade --auto-upgrade
}
update_email() { [[ -v USEREMAIL ]] && "$HOME/.acme.sh/acme.sh" --update-account --accountemail "${USEREMAIL}"; }
command_prefixes() {
declare -ag ISSUE_CMD_PREFIX DEPLOY_CMD_PREFIX
ISSUE_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--issue" "--force")
[[ -v DEBUG ]] && ISSUE_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--issue" "--staging")
DEPLOY_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--deploy" "--deploy-hook" "cpanel_uapi")
[[ -v DEBUG ]] && DEPLOY_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--deploy" "--deploy-hook" "cpanel_uapi")
}
# Either create a single array of all domains (DOMAINS) to issue one-by-one or create an array of array names to issue for a single webroot
load_domains() {
local domain_file
declare -ag DOMAIN_GROUPS=()
if [[ -v SITES_DIR ]]; then
for domain_file in "$SITES_DIR"/*; do
DOMAIN_GROUPS+=("$(<"$domain_file")")
done
fi
for domain_file in "${DOMAIN_FILES[@]}"; do
# Load list of domains as space-delimited strings in elements of the DOMAINS array
# We can keep these separate or combine them later
DOMAIN_GROUPS+=("$(<"$domain_file")")
done
}
get_webroot() {
local webroot
if ! webroot=$(uapi DomainInfo single_domain_data domain="$1" | grep documentroot); then
echo "UAPI call failed" >&2
fi
if [[ ! -v webroot || "$webroot" == "" ]]; then
if [[ -v DEBUG ]]; then
webroot="/tmp" # set missing webroot in DEBUG mode for testing
else
echo "Could not find $1's webroot" >&2
exit 1
fi
fi
echo "$webroot"
}
issue_and_deploy_certs() {
local domain_root domain domain_group
local -a issue_cmd=()
local -a deploy_cmd=()
if [[ -v GROUP ]]; then
for domain_group in "${DOMAIN_GROUPS[@]}"; do
unset i
for domain in $domain_group; do # we want to split on whitespace
[[ "$domain" == "" ]] && continue
# Get the webroot from the first domain
if [[ ! -v i ]]; then
local i="set"
domain_root=$(get_webroot "$domain")
issue_cmd=("${ISSUE_CMD_PREFIX[@]}" "-w" "$domain_root")
fi
issue_cmd+=("-d" "$domain" "-d" "www.$domain")
done
# Issue certificate for entire domain group
echo "Running:" "${issue_cmd[@]}"
"${issue_cmd[@]}"
# Deploy certificates one by one
for domain in $domain_group; do
deploy_cmd=("${DEPLOY_CMD_PREFIX[@]}" "-w" "$domain_root" "-d" "$domain")
echo "Running:" "${deploy_cmd[@]}"
"${deploy_cmd[@]}"
done
done
else
for domain_group in "${DOMAIN_GROUPS[@]}"; do
# Issue and deploy certificates one by one
for domain in $domain_group; do # we want to split on whitespace
domain_root=$(get_webroot "$domain")
issue_cmd=("${ISSUE_CMD_PREFIX[@]}" "-w" "$domain_root" "-d" "$domain" "-d" "www.$domain")
deploy_cmd=("${DEPLOY_CMD_PREFIX[@]}" "-w" "$domain_root" "-d" "$domain") # I think we only need to deploy to the domain, not subdomains
echo "Running:" "${issue_cmd[@]}"
if ! "${issue_cmd[@]}"; then
echo "Certificate issue failed for $domain"
exit_err=1
fi
echo "Running:" "${deploy_cmd[@]}"
if ! "${deploy_cmd[@]}"; then
echo "Certificate deployment failed for $domain"
exit_err=1
fi
done
done
fi
}
main() {
parse_input "$@"
get_acme
update_email
command_prefixes
load_domains
issue_and_deploy_certs
}
main "$@"
exit "${exit_err:-0}"