Skip to content
Snippets Groups Projects
Commit 2e629052 authored by Hahn Axel (hahn)'s avatar Hahn Axel (hahn)
Browse files

Merge branch '5213-handle-dns-alias-domain' into 'master'

Handle dns alias domain

See merge request open-source/iml-certman!1
parents 12786cf3 34b28637
No related branches found
No related tags found
1 merge request!1Handle dns alias domain
......@@ -25,6 +25,8 @@
# 2021-09-27 <axel.hahn@iml.unibe.ch> softer behaviour: do not revoke changed certs (add does not stop; ensure does not delete)
# 2021-12-23 <axel.hahn@iml.unibe.ch> added param --trace as 1st param to generate a trace log
# 2022-01-10 <axel.hahn@iml.unibe.ch> _wait_for_free_slot: exclude ssh calls
# 2022-03-30 <axel.hahn@iml.unibe.ch> remove usage of csr and generation of key file
# 2022-03-31 <axel.hahn@iml.unibe.ch> dns authentication with alias domain
# ======================================================================
......@@ -38,7 +40,8 @@ logdir="./log"
touchfile="$logdir/lastchange.txt"
logfile="$logdir/certmanager.log"
csrfile="./templates/csr.txt"
# CSR USAGE WAS REMOVED
# csrfile="./templates/csr.txt"
line="_______________________________________________________________________________"
......@@ -84,12 +87,12 @@ function _certMustExist(){
# the script will be aborted
# param string FQDN
function _certMustNotExist(){
_certExists
if [ $? -eq 0 ]; then
echo "WARNING: cert ${CM_fqdn} was added already."
# exit 1
echo "Press Ctrl+C to abort within the next 10 sec..."
sleep 10
if _certExists
then
echo "ERROR: cert ${CM_fqdn} was added already."
exit 1
# echo "Press Ctrl+C to abort within the next 10 sec..."
# sleep 10
fi
}
......@@ -105,39 +108,47 @@ function _certTransfer(){
test -d ${CM_dircerts} && rm -f "${CM_dircerts}/*" 2>/dev/null
_wd "--- transfer acme.sh files to ${CM_dircerts}/"
$ACME \
if ! $ACME \
--install-cert \
-d ${CM_fqdn} \
--cert-file ${CM_outfile_cert} \
--fullchain-file ${CM_outfile_chain} \
--ca-file ${CM_outfile_ca}
if [ $? -ne 0 ]; then
echo "ERROR occured during transfer. Removing files in ${CM_dircerts} to prevent strange effects..."
-d "${CM_fqdn}" \
--key-file "${CM_outfile_key}" \
--cert-file "${CM_outfile_cert}" \
--fullchain-file "${CM_outfile_chain}" \
--ca-file "${CM_outfile_ca}"
then
echo "ERROR occured during acme transfer. Removing files in ${CM_dircerts} to prevent strange effects..."
rm -f "${CM_dircerts}/*"
exit
exit 2
fi
echo "OK."
_wd "--- copy key to ${CM_dircerts}"
cp ${CM_filekey} ${CM_outfile_key}
# _wd "--- copy key to ${CM_dircerts}"
# cp ${CM_filekey} ${CM_outfile_key}
_wd "--- create chained file for haproxy"
cat ${CM_outfile_chain} ${CM_outfile_key} > ${CM_outfile_haproxy}
cat "${CM_outfile_chain}" "${CM_outfile_key}" > "${CM_outfile_haproxy}"
_wd "--- content of output dir $CM_dircerts:"
ls -l $CM_dircerts/*
if ! ls -l "${CM_outfile_cert}" "${CM_outfile_chain}" "${CM_outfile_key}" "${CM_outfile_haproxy}"
then
echo "ERROR missing a file (or no access?)"
rm -f "${CM_dircerts}/*"
exit 2
fi
}
# internal function; show md5 hashsums for certificate, csr and key
# internal function; show md5 hashsums for certificate and key
# for visual comparison if the match
function _certMatching(){
local md5_csr=$( test -f ${CM_filecsr} && openssl req -noout -modulus -in ${CM_filecsr} | openssl md5 | cut -f 2 -d " " )
# CSR USAGE WAS REMOVED
# local md5_csr=$( test -f ${CM_filecsr} && openssl req -noout -modulus -in ${CM_filecsr} | openssl md5 | cut -f 2 -d " " )
local md5_key=$( test -f ${CM_outfile_key} && openssl rsa -noout -modulus -in ${CM_outfile_key} | openssl md5 | cut -f 2 -d " " )
local md5_cert=$( test -f ${CM_outfile_cert} && openssl x509 -noout -modulus -in ${CM_outfile_cert} | openssl md5 | cut -f 2 -d " " )
echo
echo "--- compare hashes"
echo "csr : $md5_csr (used for creation of cert)"
# CSR USAGE WAS REMOVED
# echo "csr : $md5_csr (used for creation of cert)"
echo "key : $md5_key"
echo "cert : $md5_cert"
if [ "$md5_key" = "$md5_cert" ]; then
......@@ -151,19 +162,24 @@ function _certMatching(){
# internal function: dig for given fqdn.
# Function stops if fqdn was not found in DNS.
# If dig is not found the function skips the DNS check.
# This function is used in _gencsr
# This function is used in _dnsCheck
# param string fqdn to check
# param string type of dns entry; one of a|cname
# param string optional filter on output of dig (regex)
function _checkDig(){
local myfqdn=$1
which dig >/dev/null
if [ $? -eq 0 ]; then
_wd "CHECK: $myfqdn exists in DNS (using dig) ..."
dig $myfqdn | grep -v '^;' | grep $myfqdn
if [ $? -ne 0 ]; then
echo "ERROR: not found. Was there a typo in the hostname??"
local _type=${2:-"a"}
local _verify=${3:-"."}
if which dig >/dev/null
then
# _wd "[$myfqdn] exists as type [$_type] in DNS?"
if ! dig "${myfqdn}" "${_type}" | grep "^${myfqdn}" | grep -E "${_verify}"
then
echo "ERROR: [$myfqdn] was not found. Maybe there is a typo in the hostname or it does not exist in DNS."
exit 2
fi
_wd "OK"
_wd "OK: [$myfqdn] exists in DNS."
else
_wd "SKIP: dig was not found"
fi
......@@ -171,36 +187,64 @@ function _checkDig(){
}
# internal function: check DNS entries
# - the hostname to be added in the certificate must exist
# - if a hostname does not match and CM_challenge_alias was set:
# - _acme-challenge.FQDN must be a cname to _acme-challenge.${CM_challenge_alias}
# Function stops if a fqdn was not found in DNS.
# param string fqdn(s) that are part of the certificate
function _dnsCheck(){
local altdns=
local _mydomain=
local _subdomain='_acme-challenge'
for _mydomain in $*
do
_wd "dig check - domain for cert"
_checkDig "$_mydomain" "a" "IN.*(A|CNAME)" # matches A and CNAME records
if [ -n "${CM_challenge_alias}" ] && ! echo "$_mydomain" | grep "${CM_certmatch}" >/dev/null
then
_wd "dig check - cname ${_subdomain}.${_mydomain} must exist"
_checkDig "${_subdomain}.${_mydomain}" "cname"
_wd "dig check - cname ${_subdomain}.${_mydomain} must point to ${_subdomain}.${CM_challenge_alias}"
_checkDig "${_subdomain}.${_mydomain}" "cname" "${_subdomain}.${CM_challenge_alias}"
fi
done
}
# CSR USAGE WAS REMOVED
# internal function; generate a csr file before creating a new certifcate
# this function is used in public_add
function _gencsr(){
# function _UNUSED_gencsr(){
altdns=
_checkDig $CM_fqdn
for myalt in $*
do
altdns="${altdns}DNS:$myalt,"
done
altdns=$( echo $altdns | sed "s#,\$##" )
_wd "--- $CM_fqdn"
_wd "DNS alternative names: $altdns"
# local altdns=
rm -f $CM_filecnf $CM_filekey $CM_filecsr
mkdir -p "${CM_dircsr}" 2>/dev/null
# for myalt in $*
# do
# altdns="${altdns}DNS:$myalt,"
# done
# altdns=$( echo $altdns | sed "s#,\$##" )
# _wd "--- $CM_fqdn"
# _wd "DNS alternative names: $altdns"
cat $csrfile \
| sed "s#__FQDN__#$CM_fqdn#g" \
| sed "s#__ALTNAMES__#$altdns#g" \
> $CM_filecnf || exit 1
# rm -f $CM_filecnf $CM_filekey $CM_filecsr
# mkdir -p "${CM_dircsr}" 2>/dev/null
# generate csr
_wd "creating key and csr"
openssl req -new -config $CM_filecnf -keyout $CM_filekey -out $CM_filecsr || exit 1
# cat $csrfile \
# | sed "s#__FQDN__#$CM_fqdn#g" \
# | sed "s#__ALTNAMES__#$altdns#g" \
# > $CM_filecnf || exit 1
# view csr
# openssl req -noout -text -in $CM_filecsr
ls -ltr $CM_filecnf $CM_filekey $CM_filecsr
}
# # generate csr
# _wd "creating key and csr"
# openssl req -new -config $CM_filecnf -keyout $CM_filekey -out $CM_filecsr || exit 1
# # view csr
# # openssl req -noout -text -in $CM_filecsr
# ls -ltr $CM_filecnf $CM_filekey $CM_filecsr
# }
# internal function; get a sorted list of DNS aliases in the current cert
function _getAliases(){
......@@ -285,6 +329,8 @@ function _wd(){
# param string FQDN
function _setenv(){
CM_fqdn=$1
# CSR USAGE WAS REMOVED
# keeping vars to delete files of existing certs that used a csr
CM_filecsr="${CM_dircsr}/${CM_fqdn}.csr"
CM_filecnf="${CM_dircsr}/${CM_fqdn}.cnf"
CM_filekey="${CM_dircsr}/${CM_fqdn}.key"
......@@ -331,29 +377,31 @@ function _testFqdncount(){
# pulic function ADD certificate
#
function public_add(){
local _params=""
_wait_for_free_slot
_requiresFqdn
_certMustNotExist
for myhost in $( echo $CM_fqdn $*)
do
echo $myhost | grep "$CM_certmatch" >/dev/null
if [ $? -ne 0 ]; then
echo "ERROR: host $myhost does not match [$CM_certmatch]."
exit 1
_dnsCheck $CM_fqdn $*
for _mydomain in $CM_fqdn $*
do
_params+="-d $_mydomain "
if [ -n "${CM_challenge_alias}" ] && ! echo "$_mydomain" | grep "${CM_certmatch}" >/dev/null
then
_params+="--challenge-alias ${CM_challenge_alias}"
fi
done
_gencsr $CM_fqdn $*
_wd "--- create output dir $dircerts"
mkdir -p "${CM_dircerts}" 2>/dev/null
_wd "--- csr data"
$ACME --showcsr --csr $CM_filecsr || exit 1
_wd "--- create certificate"
$ACME --signcsr --csr $CM_filecsr $ACME_Params
if [ $? -ne 0 ]; then
echo $ACME --issue $_params $ACME_Params
if ! $ACME --issue $_params $ACME_Params
then
echo "ERROR: adding cert failed. Trying to delete internal data ..."
public_delete $CM_fqdn
exit 1
......@@ -366,6 +414,44 @@ function public_add(){
_update "added $CM_fqdn $*"
}
# CSR USAGE WAS REMOVED
# function OLD__public_add(){
# _wait_for_free_slot
# _requiresFqdn
# _certMustNotExist
# for myhost in $( echo $CM_fqdn $*)
# do
# echo $myhost | grep "$CM_certmatch" >/dev/null
# if [ $? -ne 0 ]; then
# echo "ERROR: host $myhost does not match [$CM_certmatch]."
# exit 1
# fi
# done
# _gencsr $CM_fqdn $*
# _wd "--- create output dir $dircerts"
# mkdir -p "${CM_dircerts}" 2>/dev/null
# _wd "--- csr data"
# $ACME --showcsr --csr $CM_filecsr || exit 1
# _wd "--- create certificate"
# echo $ACME --signcsr --csr $CM_filecsr $ACME_Params
# $ACME --signcsr --csr $CM_filecsr $ACME_Params
# if [ $? -ne 0 ]; then
# echo "ERROR: adding cert failed. Trying to delete internal data ..."
# public_delete $CM_fqdn
# exit 1
# fi
# # $ACME --issue -d $CM_fqdn $ACME_Params || exit 1
# _certTransfer
# _certMatching
# _update "added $CM_fqdn $*"
# }
#
# pulic function ADD OR RENEW certificate
#
......@@ -409,6 +495,8 @@ function public_delete(){
_wd "--- delete ACME.SH data"
$ACME --remove -d ${CM_fqdn} $ACME_Params
_wd "--- delete local data"
# CSR USAGE WAS REMOVED
rm -rf ${CM_dircerts} ${CM_filecnf} ${CM_filekey} ${CM_filecsr} ~/.acme.sh/${CM_fqdn} && echo OK
_update "deleted ${CM_fqdn}"
}
......@@ -490,7 +578,7 @@ function public_selftest(){
echo
echo --- dependencies
_selftestItem "which openssl" "opemssl was found"
_selftestItem "which openssl" "openssl was found"
_selftestItem "which curl" "curl was found"
echo
......@@ -504,15 +592,16 @@ function public_selftest(){
_selftestItem "test -w ~/.acme.sh/" "it is writable"
echo
echo --- csr template
_selftestItem "ls -ld ${csrfile}" "csr base template exists"
_selftestItem "test -r ${csrfile}" "it is readable"
echo
echo --- output directory for csr and key
_selftestItem "ls -ld ${CM_dircsr}" "data dir for csr exists"
_selftestItem "test -w ${CM_dircsr}" "it is writable"
echo
# CSR USAGE WAS REMOVED
# echo --- csr template
# _selftestItem "ls -ld ${csrfile}" "csr base template exists"
# _selftestItem "test -r ${csrfile}" "it is readable"
# echo
#
# echo --- output directory for csr and key
# _selftestItem "ls -ld ${CM_dircsr}" "data dir for csr exists"
# _selftestItem "test -w ${CM_dircsr}" "it is writable"
# echo
echo --- output dir for centralized place of certificates
_selftestItem "ls -ld ${CM_diracme}" "central output dir for certificate data exists"
......@@ -540,11 +629,15 @@ function public_show(){
_requiresFqdn
_certMustExist
ls -l ${CM_filecsr} ${CM_dircerts}/*
# CSR USAGE WAS REMOVED
# ls -l ${CM_filecsr} ${CM_dircerts}/*
ls -l ${CM_dircerts}/*
_certMatching
echo $line
echo CSR $CM_filecsr
openssl req -noout -text -in $CM_filecsr | grep -E "(Subject:|DNS:)" | sed "s#^\ *##g"
# CSR USAGE WAS REMOVED
# echo $line
# echo CSR $CM_filecsr
# openssl req -noout -text -in $CM_filecsr | grep -E "(Subject:|DNS:)" | sed "s#^\ *##g"
for myfile in ${CM_outfile_cert} ${CM_outfile_haproxy}
do
......@@ -668,7 +761,7 @@ The ACTIONs for SINGLE certificate handlings are:
and update files in ${CM_diracme}
show FQDN
show place of csr + certificate data and show basic certificate data
show place of certificate data and show basic certificate data
(issuer, subject, aliases, ending date)
transfer FQDN
......
# IML certman
Wrapper for **acme.sh** to create Let's Encrypt certificates using DNS authentication.
It was written to create/ renew all needed certificates at a central system to deploy it from there (Ansible, Puppet, ...).
source: <https://git-repo.iml.unibe.ch/open-source/iml-certman>
license: GNU GPL 3.0 <http://www.gnu.org/licenses/gpl-3.0.html>
## Requirements
* bash
* openssl
* curl
* acme.sh client
# Installation
* Install acme.sh client: <https://github.com/acmesh-official/acme.sh>
* If you use Ansible/ Puppet/ ... to renew and deploy new certificates then you can deactivate the acme cronjob (`crontab -e`)
* Clone or extract files of iml-certman
* Make your changes by copying *dist files to file without ".dist" extension and edit
* inc_config.sh
* set credentials for dns api
* set path to acme.sh script; the default is a relative path for the suggested contellation below.
* optional: set custom target for generated certificates
* optional: for testing enable Let's Encrypt stage server to prevent running into weekly limits during tests
* optional: set a filter that must match to new certificate and all aliases
* UNUSED: templates/csr.txt
* set location, company and department ... remark: (currently?) it is removed by LE
A suggested structure is having acme.sh and this wrapper below the same parent directory, i.e.
```text
/opt/letsenecrypt/
|
+-- acme.sh/
| |
| + acme.sh
| + ...
|
+-- iml-certman/
|
+-- certs/
+-- templates/
+ cm.sh
+ inc_config.sh
+ ...
```
Verify a new setup (or changes in the config) with `./cm.sh selftest`.
# Usage
## Selftest
Verify a new setup (or changes in the config) with `./cm.sh selftest`.
## Show help
Without any parameter it shows a help.
```text
./cm.sh
_______________________________________________________________________________
- - - ---===>>> CERT MANAGER <<<===--- - - -
_______________________________________________________________________________
DEBUG: Using Let's Encrypt STAGE environment ...
DEBUG: You can test and mess around. Do not use certs in production.
HELP
The basic syntax is
cm.sh [--trace] ACTION [FQDN] [ALIAS_1 [.. ALIAS_N]]
The ACTIONs for SINGLE certificate handlings are:
add FQDN [.. FQDN-N]
create new certificate
The first FQDN is a hostname to generate the certificate for.
Following multiple hostnames will be used as DNS aliases in the
same certificate.
It updates files in ./certs
ensure FQDN [.. FQDN-N]
It ensures that a certificate with given aliases exists and is up to date.
This param is for simple usage in automation tools like Ansible or Puppet.
It is required to add all aliases as parameters what is unhandy for
direct usage on cli.
If the cert does not exist it will be created (see "add").
If fqdn and aliases are the same like in the certificate it performs a renew.
If fqdn and aliases differ:
- the current certificate will be rejected + deleted (see "delete")
- a new certificate will be added ()
delete FQDN
delete all files of a given certificate
renew FQDN
renew (an already added) certificate
and update files in ./certs
show FQDN
show place of certificate data and show basic certificate data
(issuer, subject, aliases, ending date)
transfer FQDN
Transfer cert from acme.sh internal cache to our output dir again.
It is done during add or renew. With transfer command you can repeat it.
ACTIONs for ALL certs
list
list all certificates including creation and renew date
renew-all
renew all certificates (fast mode - without --force)
and update files in ./certs
It is useful for a cronjob.
other ACTIONs
selftest
check of health with current setup and requirements.
This command is helpful for initial setups.
OPTIONS
--trace (it must be the 1st parameter)
the output additionally will be written into a tracelog file
below ./log.
DEBUG: Using Let's Encrypt STAGE environment ...
DEBUG: You can test and mess around. Do not use certs in production.
```
## CRUD actions for a certificate
With parameter `add` you need to add all domains that should be included in a new certificate.
`[APPPATH]/cm.sh add www.example.com mail.example.com`
All other actions need the first domain only.
The parameter **show** shows details.
`[APPPATH]/cm.sh show www.example.com`
If a certificate reaches the time for renewing (i.e. 4 weeks before expiration) you can renew it with **renew**.
Remark: if you try to renew before renewing date this results in a skip message (and exitcode 0).
`[APPPATH]/cm.sh renew www.example.com`
With a delete command the certificate will be revoked and the local files will be deleted.
`[APPPATH]/cm.sh delete www.example.com`
Then a certificate does not appear with cm.sh list anymore.
## The action "ensure"
In a scenario of automatic deployment with Ansible or Puppet you don't want to find out what action is needed: action add, remove old and add a new certificate or renew. The ensure action is a universal command to ensure somehow that the certificate exists, contains all DNS alt names and is up to date.
`[APPPATH]/cm.sh ensure www.example.com mail.example.com`
creates (or renews if close to expiriation) a certificate with 2 hostnames in it.
## Show certificate data
Use the listing `[APPPATH]/cm.sh list` or maybe filter it `[APPPATH]/cm.sh list | grep "mail."`
to get a list of existing certs an then use the hostname in the 1st column to show details:
`[APPPATH]/cm.sh show mail.example.com`
## Renew all certificates
`[APPPATH]/cm.sh renew-all`
## Logs
In **log/certmanager.log** you find a logging about time of changes for a certificate: when it was added, renewed, deleted. A skipped renew execution (even if it was triggered internally by "ensure") won't be logged.
Additionally there is a --trace option (must be the 1st param) - an execution output will be put to logfile that contains domain and timestamp.
......@@ -43,6 +43,10 @@ export ACME=../acme.sh/acme.sh
# have no permission
# export CM_certmatch="\.example\.com"
# if a host is not matching CM_certmatch we will use authentication
# with an alias domain
# export CM_challenge_alias="example.com"
# optional: force a user to execute cm.sh
# this is for a central installation with a software deployment
# like Ansible or puppet; default: none (=any user can run cm.sh)
......
# iml-certman
# IML certman
Wrapper for **acme.sh** to create Let's Encrypt certificates based on CSR files using DNS authentication.
Wrapper for **acme.sh** to create Let's Encrypt certificates using DNS authentication.
It was written to create/ renew all needed certificates at a central system to deploy it from there (Ansible, Puppet, ...).
source: <https://git-repo.iml.unibe.ch/open-source/iml-certman>
license: GNU GPL 3.0 <http://www.gnu.org/licenses/gpl-3.0.html>
## Installation
* Install acme.sh client: <https://github.com/acmesh-official/acme.sh>
* If you use Ansible/ Puppet/ ... to renew and deploy new certificates then you can deactivate the acme cronjob (`crontab -e`)
* Clone or extract files of iml-certman
* Make your changes by copying *dist files to file without ".dist" extension and edit
* inc_config.sh
* set credentials for dns api
* set path to acme.sh script; the default is a relative path for the suggested contellation below.
* optional: set custom target for generated certificates
* optional: for testing enable Let's Encrypt stage server to prevent running into weekly limits during tests
* optional: set a filter that must match to new certificate and all aliases
* templates/csr.txt
* set location, company and department ... remark: (currently?) it is removed by LE
A suggested structure is having acme.sh and this wrapper below the same parent directory, i.e.
```text
/opt/letsenecrypt/
|
+-- acme.sh/
| |
| + acme.sh
| + ...
|
+-- iml-certman/
|
+-- certs/
+-- csr/
+-- templates/
+ cm.sh
+ inc_config.sh
+ ...
```
## Usage
### Selftest
Verify a new setup (or changes in the config) with ``./cm.sh selftest``.
### Show help
Without any parameter it shows a help.
```text
./cm.sh
_______________________________________________________________________________
- - - ---===>>> CERT MANAGER <<<===--- - - -
_______________________________________________________________________________
DEBUG: Using Let's Encrypt STAGE environment ...
DEBUG: You can test and mess around. Do not use certs in production.
HELP
The basic syntax is
cm.sh [--trace] ACTION [FQDN] [ALIAS_1 [.. ALIAS_N]]
The ACTIONs for SINGLE certificate handlings are:
add FQDN [.. FQDN-N]
create new certificate
The first FQDN is a hostname to generate the certificate for.
Following multiple hostnames will be used as DNS aliases in the
same certificate.
It updates files in ./certs
ensure FQDN [.. FQDN-N]
It ensures that a certificate with given aliases exists and is up to date.
This param is for simple usage in automation tools like Ansible or Puppet.
It is required to add all aliases as parameters what is unhandy for
direct usage on cli.
If the cert does not exist it will be created (see "add").
If fqdn and aliases are the same like in the certificate it performs a renew.
If fqdn and aliases differ:
- the current certificate will be rejected + deleted (see "delete")
- a new certificate will be added ()
delete FQDN
delete all files of a given certificate
renew FQDN
renew (an already added) certificate
and update files in ./certs
show FQDN
show place of csr + certificate data and show basic certificate data
(issuer, subject, aliases, ending date)
transfer FQDN
Transfer cert from acme.sh internal cache to our output dir again.
It is done during add or renew. With transfer command you can repeat it.
ACTIONs for ALL certs
list
list all certificates including creation and renew date
renew-all
renew all certificates (fast mode - without --force)
and update files in ./certs
It is useful for a cronjob.
other ACTIONs
selftest
check of health with current setup and requirements.
This command is helpful for initial setups.
OPTIONS
--trace (it must be the 1st parameter)
the output additionally will be written into a tracelog file
below ./log.
DEBUG: Using Let's Encrypt STAGE environment ...
DEBUG: You can test and mess around. Do not use certs in production.
```
### CRUD actions for a certificate
A certificate is created for a host and can have additional DNS names (optional).
For integration into a system deployment with Ansible & co the `ensure` prameter
is the best choice because it detects what action is required.
The command
`[APPPATH]/cm.sh ensure www.example.com mail.example.com`
creates (or renews if close to expiriation) a certificate with 2 hostnames in it.
The "manual way" with atomic actions is:
* Create `[APPPATH]/cm.sh add www.example.com mail.example.com`
* Renew `[APPPATH]/cm.sh renew www.example.com`
* Modify hostnames with add command `[APPPATH]/cm.sh add www.example.com mail.example.com newhost.example.com` what creates a new certificate. Optionally you can/ should revoke the existing certificate with the former host list before (see next command). The impact is: Your SSL certificate on the website is invalid up to the moment you create and deploy the new certificate what can take a few minutes. If you maintain many certificates with the same domain and the request limit is reached your application can be broken broken for an even longer time.
* Deletin the certificates includes a revoke `[APPPATH]/cm.sh delete www.example.com`
### Show certificate data
Use the listing `[APPPATH]/cm.sh list` or maybe filter it `[APPPATH]/cm.sh list | grep "mail."`
to get a list of existing certs an then use the hostname in the 1st column to show details:
`[APPPATH]/cm.sh show www.example.com`
See [docs](docs/)
# CSR template is not used anymore
We added support for authentication with an dns alias.
The CSR template won't be used anymore.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment