Skip to content

Instantly share code, notes, and snippets.

@Kambfhase
Created December 19, 2015 19:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kambfhase/9b612a03d588fd814593 to your computer and use it in GitHub Desktop.
Save Kambfhase/9b612a03d588fd814593 to your computer and use it in GitHub Desktop.
Uberspace Scripts for let's encrypt
#!/bin/sh -e
########################################################################
#
# 2015-11-24
# Jonas Pasche
# jpasche@jonaspasche.com
#
########################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################
#
# This script will setup a basic Let's Encrypt config for a user
#
########################################################################
# make sure we're not running CentOS 5
set +e
grep -qsE "CentOS release 5" /etc/redhat-release
if [ "$?" = "0" ] ; then
echo "Your host is running CentOS 5, unfortunately we don't support Let's Encrypt on CentOS 5, sorry."
exit
fi
set -e
LE_DIR="${HOME}/.config/letsencrypt"
LE_CONFIG="${LE_DIR}/cli.ini"
# don't do anything if there already is some config
if [ -e ${LE_CONFIG} ] ; then
echo "You already seem to have a valid Let's Encrypt config, so you're ready to go."
echo "If you want to start over, you can move it out of your way:"
echo
echo "mv ${LE_CONFIG} ${LE_CONFIG}.old"
echo
echo "If you want to simply retrieve some certificates with the existing config, execute:"
echo
echo "letsencrypt certonly"
echo
exit 1
fi
# generate a list of hostnames to receive certificates for
LE_DOMAINS=()
# exclude uberspace.de subdomains because Let's Encrypt won't issue certificates
# for that domain anyway ("Too many certificates already issued for: uberspace.de")
for LE_HOSTNAME in `uberspace-list-domains -w | grep -v ${USER}\.${HOSTNAME}` ; do
if [[ ${LE_HOSTNAME} =~ ^\* ]] ; then
# look for matching directories above the default DocumentRoot
WILDCARD_DIRS=`find /var/www/virtual/${USER} -maxdepth 1 -name "${LE_HOSTNAME}" -printf "%f\n"`
if [ "${WILDCARD_DIRS}" != "" ] ; then
for WILDCARD_DIR in ${WILDCARD_DIRS} ; do
LE_DOMAINS+=(${WILDCARD_DIR})
done
else
# If there are no wildcard directories, assume one "www" as a more-or-less sane default
LE_DOMAINS+=(`echo ${LE_HOSTNAME} | sed 's/^\*/www/'`)
fi
else
# regular hostname
LE_DOMAINS+=(${LE_HOSTNAME})
fi
done
DOCUMENTROOT=/var/www/virtual/${USER}/html
# combine domains into comma-separated list for cli.ini
OLDIFS=$IFS
IFS=","
LE_CSVDOMAINS="${LE_DOMAINS[*]}"
IFS=$OLDIFS
# create config directory, if needed
mkdir -p ${LE_DIR}
# create config file
cat > ${LE_CONFIG} <<__EOF__
rsa-key-size = 4096
server = https://acme-v01.api.letsencrypt.org/directory
authenticator = webroot
# Don't change this without real good reasons. Our web frontend
# uses a separate backend for answering ACME challenges which
# *enforces* to use the default web root.
# If you change this, things will break. You have been warned!
webroot-path = ${DOCUMENTROOT}
config-dir = ${HOME}/.config/letsencrypt
work-dir = ${HOME}/.local/share/letsencrypt/work
logs-dir = ${HOME}/.local/share/letsencrypt/logs
email = ${USER}@${HOSTNAME}
# Beware that Let's Encrypt does NOT support wildcard hostnames.
# If you're using wildcards you have to add each subdomain explicitly.
domains = ${LE_CSVDOMAINS}
text = True
# To prevent being forced to agree manually to the terms
#agree-dev-preview = True
#agree-tos = True
__EOF__
echo
echo "We have now created the following config file for you:"
echo
echo " ${LE_CONFIG}"
echo
echo "Please review especially the domain list we have generated for you"
echo "and adapt the 'domains' setting if you want to make some changes:"
echo
for LE_DOMAIN in "${LE_DOMAINS[@]}" ; do
echo " ${LE_DOMAIN}"
done
echo
echo "When you're done you can use the official Let's Encrypt client by executing:"
echo
echo " letsencrypt certonly"
echo
echo "You can safely ignore all 'Root (sudo) is required to run most of letsencrypt functionality' warnings."
echo
#!/bin/bash
########################################################################
# 2015-12-01 Moritz Werner mwerner@jonaspasche.com
########################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################
# 2014-04-09 initial script
# 2014-06-12 added error handling, less verbosity in openssl
# 2015-11-25 rework, added Emojis!
# 2015-12-01 rework, automatic import of certifictes via
# uberspace-check-certificate
########################################################################
export LANG=C
# make sure we're not running CentOS 5
grep -qsE "CentOS release 5" /etc/redhat-release
if [[ "$?" = "0" ]] ;
then
echo "Your host is running CentOS 5, unfortunately we can't import your certificates because of a different setup on our CentOS 5 hosts than on our newer ones.";
echo "Consider moving to a new host and check https://wiki.uberspace.de/uberspace2uberspace for more information.";
echo "As always feel free to send an email to hallo@uberspace.de if you have any questions.";
exit 1
else
:
fi
USAGE="Usage:\n-h\t\tthis help message\n-k\t\tKey File\n-c\t\tCertificate File\n";
if [[ ! $# -ge 1 ]] ;
then
printf "No arguments given.\n$USAGE" $(basename $0) >&2
exit 2;
fi
KEYGIVEN=''
CERTGIVEN=''
## Parse arguments
while getopts ":hk:c:" Option; do
case $Option in
h )
printf "$USAGE" $(basename $0);
exit 0;
;;
k )
KEYGIVEN=1;
KEY=${OPTARG};
;;
c )
CERTGIVEN=1;
CERT=${OPTARG};
;;
? )
printf "Invalid option or option without parameter: -${OPTARG}\n$USAGE" $(basename $0) >&2
exit 2;
;;
* ) # Default.
printf "Unimplemented option: -${OPTARG}\n$USAGE" $(basename $0) >&2
exit 2;
;;
esac
done
shift $(($OPTIND - 1))
if [[ ! "$KEYGIVEN" ]] ;
then
printf "πŸ”‘ No key given.\n$USAGE" $(basename $0) >&2
exit 2;
fi
if [[ ! "$CERTGIVEN" ]] ;
then
printf "No certificate given.\n$USAGE" $(basename $0) >&2
exit 2;
fi
USERNAME=$(whoami)
# check if files exist
if [[ -f $KEY ]] ;
then
echo "πŸ”‘ Found key..."
else
echo "πŸ”‘ Key not found... Wrong filename?"
exit 1
fi
# check if files exist
if [[ -f $CERT ]] ;
then
echo "πŸ“ Found certificate..."
else
echo "πŸ“ certificate not found... Wrong filename?"
exit 1
fi
# decrypt if key is encrypted
if [[ `grep -c ENCRYPTED $KEY` -ge 1 ]] ;
then
echo "πŸ”‘ Key is encrypted, let's decrypt it (We will decrypt it to $KEY.dec). You chose the password yourself:"
openssl rsa < $KEY > $KEY.dec
if [[ "$?" != "0" ]] ;
then
echo "πŸ”‘ Decryption went wrong. Wrong password?"
exit 1
fi
KEY=$KEY.dec
echo "πŸ”‘ decryption succeeded"
fi
# check for file validity
KEYCHECK=$(openssl rsa -noout -text -in $KEY 2>&1)
if [[ "$?" != "0" ]] ;
then
# Key is not okay
if [[ $KEYCHECK == *"unable to load Private Key"* ]] ;
then
echo "πŸ”‘ Key does not seem to be valid, check your file. We need .pem format."
echo ""
exit 1
else
echo "Uh-oh. You found a bug that's not supposed to be here."
echo ""
echo "$KEYCHECK"
echo ""
echo "Please write to hallo@uberspace.de"
echo ""
exit 1
fi
fi
echo "πŸ”‘ Key seems valid, moving on..."
CRTCHECK=$(openssl x509 -noout -text -in $CERT 2>&1)
if [[ "$?" != "0" ]] ;
then
# Certificate is not okay
if [[ $CRTCHECK == *"unable to load certificate"* ]] ;
then
echo "πŸ“ Certificate does not seem to be valid, check your file. We need .pem format."
echo ""
exit 1
else
echo "Uh-oh. You found a bug that's not supposed to be here."
echo ""
echo "$CRTCHECK"
echo ""
echo "Please write to hallo@uberspace.de"
exit 1
fi
fi
echo "πŸ“ Certificate seems valid, moving on... (step by step)"
# Get full path
KEY=`readlink -f $KEY`
CERT=`readlink -f $CERT`
BUNDLE="`dirname $CERT`/full_`basename $CERT`"
# Get md5 checksum
md5key=`openssl rsa -noout -modulus -in $KEY | openssl md5`
md5crt=`openssl x509 -noout -modulus -in $CERT | openssl md5`
# Comparing md5 checksum
if [[ "$md5crt" = "$md5key" ]] ;
then
echo "πŸ” Certificate matches key, moving on... (we're getting there!)"
else
echo "πŸ” Your Key does not match your certificate. It just does not fit. They're not meant to be together."
echo "You can check for yourself:"
echo
echo "\$ openssl rsa -noout -modulus -in $KEY | openssl md5"
echo $md5key
echo
echo "\$ openssl x509 -noout -modulus -in $CERT | openssl md5"
echo $md5crt
echo
echo "The outcome of both commands must be identical."
echo "If you need any help feel free to mail to hallo@uberspace.de"
exit 1
fi
# Get Domainname of certificate
domain=`openssl x509 -noout -subject -in $CERT |awk -F CN= '{ print $2 }' |awk -F / '{ print $1 }' | sed 's/^\*/wildcard/' | sed 's/[^a-z0-9\-\.]/_/g'`
if [[ "$domain" = "" ]] ;
then
echo "No Common Name (CN) in certificate, this won't work."
echo ""
exit 1
fi
if [[ $domain == *"@"* ]] ;
then
echo "E-Mail-Adress in Common Name (CN), this won't work. CN needs to be an URL."
echo ""
exit 1
fi
# Get intermediate(s)
echo "πŸ“œ Magically getting intermediate certificate(s) if there are any needed... (hold on tight)"
cert-chain-resolver $CERT $BUNDLE &>/dev/null
# verify
cat $BUNDLE $KEY | sudo -u certtest /usr/local/bin/uberspace-check-certificate
if [[ $? = "0" ]] ;
then
FAILED=0
else
DEBUG=$(certtool --infile=$BUNDLE --verify)
if [[ $DEBUG == *"The certificate issuer is not a CA"* ]]; then
echo "πŸ” The certificate is self signed. Well... Okay."
FAILED=1
MOREINFO="self signed."
elif [[ $DEBUG == *"The certificate issuer is unknown."* ]]; then
echo "πŸ” The certificate issuer is unknown (CAcert probably...). Well... Okay. We can't import that automatically though."
echo "πŸ” And you'll have to build your chain on your own because we can't find the intermediate certificate(s)."
FAILED=1
MOREINFO="unknown CA."
fi
fi
if [[ $FAILED != "0" ]] ;
then
echo "πŸš€ We can't import you're certificate automatically."
echo ""
echo "Feel free to mail to hallo@uberspace.de, please include the following information and don't forget to tell us where to find your intermediate certificate if you have one."
echo ""
echo "--debug--"
echo "$DEBUG"
echo "--debug--"
echo ""
echo "Host: `hostname`"
echo "User: ${USER}"
echo "Key: ${KEY}"
echo "Cert: ${BUNDLE}"
echo "probably: ${MOREINFO}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment