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

initial commit

parents
No related branches found
No related tags found
No related merge requests found
csr/*
log/*
inc_config.sh
templates/csr.txt
cm.sh 0 → 100755
#!/usr/bin/env bash
# ======================================================================
#
# WRAPPER FOR ACME.SH
# Let's Encrypt client
#
# requires
# - bash
# - openssl
# - curl
# - dig (opional)
# - acme.sh client
#
# ----------------------------------------------------------------------
# 2021-02-02
# ======================================================================
# ----------------------------------------------------------------------
#
# CONFIG
#
# ----------------------------------------------------------------------
selfdir="$( dirname $0 )"
touchfile="${selfdir}/log/lastchange.txt"
logfile="${selfdir}/log/certmanager-$( date +"%Y%M%d" ).log"
line="_______________________________________________________________________________"
showdebug=1
# ----------------------------------------------------------------------
#
# INTERNAL FUNCTIONS
#
# ----------------------------------------------------------------------
function _certExists(){
_listCerts | awk '{ print $1 }' | grep "^${CM_fqdn}$" >/dev/null
}
function _certMustExist(){
_certExists
if [ $? -ne 0 ]; then
echo "ERROR: cert ${CM_fqdn} was not added yet."
exit 1
fi
}
function _certMustNotExist(){
_certExists
if [ $? -eq 0 ]; then
echo "ERROR: cert ${CM_fqdn} was added already."
exit 1
fi
}
# internal function: transfer generated/ updated cert data to a
# known directory (based on ACME_Outdir - see inc_config.sh)
# used in public_add and public_renew
function _certTransfer(){
_wd "--- acme internal data"
ls -l ~/.acme.sh/${CM_fqdn}
_wd "--- transfer acme.sh files to ${CM_dircerts}"
$ACME \
--install-cert \
-d ${CM_fqdn} \
--cert-file ${CM_dircerts}/${CM_fqdn}.cert.pem \
--fullchain-file ${CM_dircerts}/${CM_fqdn}.fullchain.pem \
|| exit 1
# --key-file ${CM_dircerts}/${CM_fqdn}.key.pem \
_wd "--- copy key to ${CM_dircerts}"
cp ${CM_filekey} ${CM_dircerts}/${CM_fqdn}.key.pem
_wd "--- content of output dir $CM_dircerts:"
ls -l $CM_dircerts/*
}
# 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
# param string fqdn to check
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??"
exit 2
fi
_wd "OK"
else
_wd "SKIP: dig was not found"
fi
echo
}
# internal function; generate a csr file before creating a new certifcate
# this function is used in public_add
function _gencsr(){
altdns=
_checkDig $CM_fqdn
for myalt in $*
do
altdns="${altdns},DNS:$myalt"
done
_wd "--- $CM_fqdn"
_wd "DNS alternative names: $altdns"
rm -f $CM_filecnf $CM_filekey $CM_filecsr
cat ./templates/csr.txt \
| sed "s#__FQDN__#$CM_fqdn#g" \
| sed "s#__ALTNAMES__#$altdns#g" \
> $CM_filecnf || exit 1
# 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; list certificates incl. creation date and renew date
function _listCerts(){
$ACME --list
}
function _requiresFqdn(){
if [ -z "$CM_fqdn" ]; then
echo "ERROR: 2nd parameter must be a FQDN for Main_Domain."
exit 1
fi
}
# set update message in a file
# param string(s) message
function _update(){
echo $( date ) $* > ${touchfile}
}
# write debug output if showdebug is set to 1
function _wd(){
test ${showdebug} && echo "DEBUG: $*"
}
# ----------------------------------------------------------------------
#
# PUBLIC FUNCTIONS
#
# ----------------------------------------------------------------------
#
# pulic function ADD certificate
#
function public_add(){
_requiresFqdn
_certMustNotExist
_gencsr $CM_fqdn $*
_wd "--- create output dir $dircerts"
mkdir -p "${CM_dircerts}" 2>/dev/null
# _wd "--- domains in csr"
./acme.sh/acme.sh --showcsr --csr $CM_filecsr || exit 1
_wd "--- create certificate"
$ACME --signcsr --force --csr $CM_filecsr $ACME_Params || exit 1
_certTransfer
_update "added $CM_fqdn $*"
}
#
# public function to delete a cert
#
function public_delete(){
_requiresFqdn
_certMustExist
# TODO: revoke it too??
# $ACME --revoke -d ${CM_fqdn} || exit 2
$ACME --remove -d ${CM_fqdn} || exit 2
rm -rf ${CM_dircerts} ${CM_filecnf} ${CM_filekey} ${CM_filecsr} ~/.acme.sh/${CM_fqdn}
_update "deleted ${CM_fqdn}"
}
#
# public function; list certificates incl. creation date and renew date
#
function public_list(){
_listCerts
}
#
# public function - renew a certificate
# param string fqdn of domain to renew
function public_renew(){
_requiresFqdn
_certMustExist
$ACME --renew --force -d ${CM_fqdn} || exit 2
_certTransfer
_update "renew ${CM_fqdn}"
}
#
# list existing certs
# param string fqdn of domain to renew
function public_show(){
_requiresFqdn
_certMustExist
ls -l ${CM_filecsr} ${CM_dircerts}/*
echo $line
echo $CM_filecsr
openssl req -noout -text -in $CM_filecsr
echo $line
echo ${CM_dircerts}/${CM_fqdn}.cert.pem
openssl x509 -noout -text -in ${CM_dircerts}/${CM_fqdn}.cert.pem
}
# ----------------------------------------------------------------------
#
# main
#
# ----------------------------------------------------------------------
cd $( dirname $0 )
cat <<ENDOFHEADER
$line
- - - ---===>>> CERT MANAGER <<<===--- - - -
$line
ENDOFHEADER
which openssl >/dev/null || exit 1
. ./inc_config.sh
if [ $? -ne 0 ]; then
echo "ERROR: loading the config failed."
echo "Copy the inc_config.sh.dist to inc_config.sh and make your settings in it."
echo
exit 1
fi
grep "function\ public_$1" $0 >/dev/null
if [ $# -gt 0 -a $? -eq 0 ]; then
# _wd $*
action=$1
CM_fqdn=$2
shift 2
test -z "${ACME_Outdir}" && ACME_Outdir=./certs
test -z "${ACME}" && ACME=$( which acme.sh )
if [ ! -x "${ACME}" ]; then
echo "ERROR: acme.sh not found. You need to install acme.sh client and configure it in inc_config.sh."
exit 1
fi
CM_filecsr="./csr/${CM_fqdn}.csr"
CM_filecnf="./csr/${CM_fqdn}.cnf"
CM_filekey="./csr/${CM_fqdn}.key"
CM_dircerts="${ACME_Outdir}/${CM_fqdn}"
# echo $CM_fqdn
# set | grep "^CM_"
_wd "A C T I O N -->> $action <<--"
eval "public_$action $*"
else
self=$( basename $0 )
cat <<EOF
HELP
The basic syntax is
$self ACTION [FQDN]
The ACTIONs are:
add FQDN [.. FQDN-N]
create new certificate ... or force it
The first FQDN is a hostname to generate the certificate for.
Following hostnames will be used as DNS aliases in the same certificate.
delete FQDN
delete a given certificate
list
list all certificates including creation and renew date
renew FQDN
renew (an already added) certificate
show FQDN
show place of csr + certificate data and show certificate
EOF
fi
# ======================================================================
#
# add dns credentials and default params here
#
# ======================================================================
# ----------------------------------------------------------------------
# DNS API
# see https://github.com/acmesh-official/acme.sh/wiki/dnsapi
# - set the env vars of your dns provider
# - add provider in ACME_Params="--dns [PROVIDER]"
# ----------------------------------------------------------------------
# -- for infoblox access
# export Infoblox_Creds="[user]:[Passwort]"
# export Infoblox_Server="infoblox.localhost"
# export ACME_Params="--dns dns_infoblox"
# ----------------------------------------------------------------------
# general settings
# ----------------------------------------------------------------------
# set path to acme.sh
export ACME=../acme.sh/acme.sh
# activate LE staging server for testing ... uncomment it for development
# and testing purposes
# export ACME_Params="$ACME_Params --staging"
# where to write certificate data
# export ACME_Outdir="./certs"
# ----------------------------------------------------------------------
# iml-certman
Wrapper for acme.sh to create Let's Encrypt certificates based on CSR files using DNS authentication
source: https://git-repo.iml.unibe.ch/open-source/iml-certman
## Installation
* Install acme.sh client: https://github.com/acmesh-official/acme.sh
* 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
- optional: set custom target for generated certificates
- optional: for testing enable Let's Encrypt stage server to prevent running into weekly limits during tests
+ templates/csr.txt
- set location, company and department
## Usage
```text
./cm.sh
_______________________________________________________________________________
- - - ---===>>> CERT MANAGER <<<===--- - - -
_______________________________________________________________________________
HELP
The basic syntax is
cm.sh ACTION [FQDN]
The ACTIONs are:
add FQDN [.. FQDN-N]
create new certificate ... or force it
The first FQDN is a hostname to generate the certificate for.
Following hostnames will be used as DNS aliases in the same certificate.
delete FQDN
delete a given certificate
list
list all certificates including creation and renew date
renew FQDN
renew (an already added) certificate
show FQDN
show place of csr + certificate data and show certificate
```
# OpenSSL configuration file for creating a CSR for a server certificate
# Adapt at least the FQDN and ORGNAME lines, and then run
# openssl req -new -config myserver.cnf -keyout myserver.key -out myserver.csr
# on the command line.
# (1) the name of your location
LOCATION = Anywhere
# (2) the name of your organization
ORGNAME = My company
# (3) the name of your organization unit
UNITNAME = Department for magic things
# --- no modifications required below ---
# the fully qualified server (or service) name
FQDN = __FQDN__
# subjectAltName entries: to add DNS aliases to the CSR, delete
ALTNAMES = DNS:$FQDN__ALTNAMES__
[ req ]
default_bits = 2048
prompt = no
encrypt_key = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ dn ]
C = CH
ST = Bern
L = $LOCATION
O = $ORGNAME
OU = $UNITNAME
CN = $FQDN
[ req_ext ]
subjectAltName = $ALTNAMES
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment