Created
December 19, 2015 19:19
-
-
Save Kambfhase/9b612a03d588fd814593 to your computer and use it in GitHub Desktop.
Uberspace Scripts for let's encrypt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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