Browse Source

Merge pull request #648 from srvrco/timkimber/issue646

DNS scripts for cpanel
pull/652/head
Tim Kimber 5 years ago
committed by GitHub
parent
commit
c65bd5e812
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 210 additions and 7 deletions
  1. +60
    -4
      README.md
  2. +76
    -0
      dns_scripts/dns_add_cpanel
  3. +69
    -0
      dns_scripts/dns_del_cpanel
  4. +5
    -3
      getssl

+ 60
- 4
README.md View File

@ -1,21 +1,23 @@
# getssl
# getssl <!-- omit in toc -->
![Run all tests](https://github.com/srvrco/getssl/workflows/Run%20all%20tests/badge.svg) ![shellcheck](https://github.com/srvrco/getssl/workflows/shellcheck/badge.svg)
Obtain SSL certificates from the letsencrypt.org ACME server. Suitable
for automating the process on remote servers.
## Table of Contents
## Table of Contents <!-- omit in toc -->
- [Features](#features)
- [Installation](#installation)
- [Overview](#overview)
- [Getting started](#getting-started)
- [Wildcard certificates](#wildcard-certificates)
- [Automating updates](#automating-updates)
- [Structure](#structure)
- [Server-Types](#server-types)
- [Revoke a certificate](#revoke-a-certificate)
- [Elliptic curve keys](#elliptic-curve-keys)
- [Preferred Chain](#preferred-chain)
- [Full chain](#full-chain)
- [Issues / problems / help](#issues--problems--help)
## Features
@ -163,9 +165,35 @@ Change the server in your config file to get a fully valid certificate.
dns. The certificate can be used (and checked with getssl) on alternate
ports.
## Wildcard certificates
`getssl` supports creating wildcard certificates, i.e. _*.example.com_ which allows a single certificate to be used for any domain under *example.com*, e.g. *www.example.com*, *mail.example.com*. These must be validated using the dns-01 method.
A *partial* example `getssl.cfg` file is:
```sh
VALIDATE_VIA_DNS=true
export CPANEL_USERNAME=''
export CPANEL_URL='https://www.cpanel.host:2083'
export CPANEL_APITOKEN='1ABC2DEF3GHI4JKL5MNO6PQR7STU8VWX9YZA'
DNS_ADD_COMMAND=/home/root/getssl/dns_scripts/dns_add_cpanel
DNS_DEL_COMMAND=/home/root/getssl/dns_scripts/dns_del_cpanel
```
Create the wildcard certificate (need to use quotes to prevent globbing):
```sh
getssl "*.example.domain"
```
You can renew the certificate using `getssl -a` to renew all configured certificates.
You can also specify additional domains in the `SANS` line, e.g. `SANS="www.test.example.com"`.
This cannot contain any of the domains which would be covered by the wildcard certificate.
## Automating updates
I use the following cron
I use the following **cron** job
```cron
23 5 * * * /root/scripts/getssl -u -a -q
@ -353,6 +381,34 @@ key (different of course, don't use the same key for both). prime256v1
secp521r1 (NIST P-521) is included in the code, but not currently
supported by Let's Encrypt).
## Preferred Chain
If a CA offers multiple chains then it is possible to select which chain
is used by using the `PREFERRED_CHAIN` variable in `getssl.cfg` or specifying
`--preferred-chain` in the call to `getssl`
This uses wildcard matching so requesting "X1" returns the first certificate
returned by the CA which contains the text "X1", Note you may need to escape
any characters which special characters, e.g.
` PREFERRED_CHAIN="\(STAGING\) Doctored Durian Root CA X3"`
* Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1"
* Production options are: "ISRG Root X1" and "ISRG Root X2"
## Full chain
Some servers, including those that use Java keystores, will not accept a server certificate if it cannot valid the full chain of signers.
Specifically, Nutanix Prism (Element and Central) will not accept the `fullchain.crt` until the root CA's certificate has been appended to it manually.
If your application requires the full chain, i.e. including the
root certificate of the CA, then this can be included in the `fullchain.crt` file by
adding the following line to `getssl.cfg`
```sh
FULL_CHAIN_INCLUDE_ROOT="true"
```
## Issues / problems / help
If you have any issues, please log them at <https://github.com/srvrco/getssl/issues>


+ 76
- 0
dns_scripts/dns_add_cpanel View File

@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Need to add your email address and API key to cpanel below or set as env variables
user=${CPANEL_USERNAME:-''}
password=${CPANEL_PASSWORD:-''}
url=${CPANEL_URL:-''} # e.g. https://www.cpanel-host.test:2083
apitoken=${CPANEL_APITOKEN:-''}
fulldomain="${1}"
token="${2}"
# Check initial parameters
if [[ -z "$fulldomain" ]]; then
echo "DNS script requires full domain name as first parameter"
exit 1
fi
if [[ -z "$token" ]]; then
echo "DNS script requires challenge token as second parameter"
exit 1
fi
if [[ -z "$user" ]]; then
echo "CPANEL_USERNAME (username) parameter not set"
exit 1
fi
if [[ -z "$apitoken" ]] && [[ -z "$password" ]]; then
echo "Must set either CPANEL_APITOKEN or CPANEL_PASSWORD in dns script, environment variable or getssl.cfg"
exit 1
fi
if [[ -z "$url" ]]; then
echo "CPANEL_URL (url) parameter not set"
exit 1
fi
# Setup
request_func="${url}/json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit"
if [[ -n $apitoken ]]; then
curl_params=( -H "Authorization: cpanel $user:$apitoken" )
else
auth_string=$(echo -ne "$user:$password" | base64 --wrap 0)
curl_params=( -H "Authorization: Basic $auth_string" )
fi
# Check if domain is a CNAME
res=$(dig CNAME "$fulldomain")
domain=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g')
if [[ -n "$domain" ]]; then
name=".${fulldomain%.$domain}"
else
domain=$fulldomain
name=""
fi
# Check to see if challenge dns entry already exists (update or delete?)
request_params="&cpanel_jsonapi_func=fetchzone_records&domain=${domain}&type=TXT&name=_acme-challenge.${fulldomain}."
resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params")
if [[ "$resp" = *\"error\":* ]]; then
echo -n "cpanel fetchzone records failed: "
echo "$resp" | awk -F"error" '{ print $2 }' | awk -F\" '{ print $3 }'
exit 1
fi
# If no existing record, create a new TXT record, otherwise edit the existing record
if [[ "$resp" == *\"data\":[]* ]]; then
request_params="&cpanel_jsonapi_func=add_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&txtdata=$token"
else
# shellcheck disable=SC2001
line=$(echo "$resp" | sed -e 's/.*line":\([0-9]*\),.*/\1/')
request_params="&cpanel_jsonapi_func=edit_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&txtdata=${token}&line=${line}"
fi
resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params")
if [[ "$resp" = *\"status\":0* ]]; then
echo -n "cpanel edit zone record failed: "
echo "$resp" | awk -F"statusmsg" '{ print $2 }' | awk -F\" '{ print $3 }'
exit 1
fi

+ 69
- 0
dns_scripts/dns_del_cpanel View File

@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Need to add your email address and API key to cpanel below or set as env variables
user=${CPANEL_USERNAME:-''}
password=${CPANEL_PASSWORD:-''}
url=${CPANEL_URL:-''} # e.g. https://www.cpanel-host.test:2083
apitoken=${CPANEL_APITOKEN:-''}
fulldomain="${1}"
# Check initial parameters
if [[ -z "$fulldomain" ]]; then
echo "DNS script requires full domain name as first parameter"
exit 1
fi
if [[ -z "$user" ]]; then
echo "CPANEL_USERNAME (username) parameter not set"
exit 1
fi
if [[ -z "$apitoken" ]] && [[ -z "$password" ]]; then
echo "Must set either CPANEL_APITOKEN or CPANEL_PASSWORD in dns script, environment variable or getssl.cfg"
exit 1
fi
if [[ -z "$url" ]]; then
echo "CPANEL_URL (url) parameter not set"
exit 1
fi
# Setup
request_func="${url}/json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit"
if [[ -n $apitoken ]]; then
curl_params=( -H "Authorization: cpanel $user:$apitoken" )
else
auth_string=$(echo -ne "$user:$password" | base64 --wrap 0)
curl_params=( -H "Authorization: Basic $auth_string" )
fi
# Check if domain is a CNAME
res=$(dig CNAME "$fulldomain")
domain=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g')
if [[ -n "$domain" ]]; then
name=".${fulldomain%.$domain}"
else
domain=$fulldomain
name=""
fi
# Find line number of existing record
request_params="&cpanel_jsonapi_func=fetchzone_records&domain=${domain}&type=TXT&name=_acme-challenge.${fulldomain}."
resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params")
if [[ "$resp" = *\"error\":* ]]; then
echo -n "cpanel fetchzone records failed: "
echo "$resp" | awk -F"error" '{ print $2 }' | awk -F\" '{ print $3 }'
exit 1
fi
# shellcheck disable=SC2001
line=$(echo "$resp" | sed -e 's/.*line":\([0-9]*\),.*/\1/')
if [[ "$line" != "" ]]; then
# Delete the challenge token
request_params="&cpanel_jsonapi_func=remove_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&line=$line"
resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params")
fi
if [[ "$resp" = *\"status\":0* ]]; then
echo -n "cpanel remove zone record failed: "
echo "$resp" | awk -F"statusmsg" '{ print $2 }' | awk -F\" '{ print $3 }'
exit 1
fi

+ 5
- 3
getssl View File

@ -2073,16 +2073,18 @@ revoke_certificate() { # revoke a certificate
}
requires() { # check if required function is available
args=("${@}")
lastarg=${args[${#args[@]}-1]}
if [[ "$#" -gt 1 ]]; then # if more than 1 value, check list
for i in "$@"; do
if [[ "$i" == "${!#}" ]]; then # if on last variable then exit as not found
if [[ "$i" == "$lastarg" ]]; then # if on last variable then exit as not found
error_exit "this script requires one of: ${*:1:$(($#-1))}"
fi
res=$(command -v "$i" 2>/dev/null)
debug "checking for $i ... $res"
if [[ -n "$res" ]]; then # if function found, then set variable to function and return
debug "function $i found at $res - setting ${!#} to $i"
eval "${!#}=\$i"
debug "function $i found at $res - setting ${lastarg} to $i"
eval "${lastarg}=\$i"
return
fi
done


Loading…
Cancel
Save