Skip to content

Instantly share code, notes, and snippets.

@craigphicks
Last active October 26, 2019 01:34
Show Gist options
  • Save craigphicks/20681c2eb7c04e3921980c11862265c4 to your computer and use it in GitHub Desktop.
Save craigphicks/20681c2eb7c04e3921980c11862265c4 to your computer and use it in GitHub Desktop.
self managed private CA and certs - no config files, two levels only, no intermediate, no revocation list, file names are CN - ideal for personal IoT
#!/bin/bash
# craigphicks 2019
set -u
function CreateCertificateAuthority {
if [[ $# -ne 2 ]] ; then
echo "two args only: CA common name, CA org name"
exit 1
fi
CA_CN=${1}
CA_ORG=${2}
if ! [[ $USER = "root" ]] ; then
echo "must be root"
exit 1
fi
CAKeyFN=$(pwd)/private/${CA_CN}.key
CACrtFN=$(pwd)/public/${CA_CN}.crt
if [[ ! -d ./private ]] ; then
mkdir ./private;
sudo chmod 700 ./private
fi
if [[ ! -d ./public ]] ; then
mkdir ./public;
fi
if [[ -f ${CAKeyFN} ]] || [[ -f $CACrtFN ]] ; then
echo "server pem or key already exist"
exit 2
fi
#
# Create the Root Key
#
openssl genrsa -out ${CAKeyFN} 2048 || exit 3
#
# Now self-sign this certificate using the root key.
#
# CN: CommonName
# OU: OrganizationalUnit
# O: Organization
# L: Locality
# S: StateOrProvinceName
# C: CountryName
#
openssl req -x509 \
-new \
-nodes \
-key ${CAKeyFN} \
-sha256 \
-days 3650 \
-subj "/C=US/ST=--/L=--/O=${CA_ORG}/OU=--/CN=${CA_CN}" \
-out ${CACrtFN} || exit 4
}
# $1 = server CN, $2 = CA CN
function CreateServerCertificate {
if [[ $# -ne 3 ]] ; then
echo "three args only: CA common name, server common name. serverAltName arg"
exit 10
fi
CA_CN=${1}
SRV_CN=${2}
subjectAltNameArg=${3}
for f in ./private/${SRV_CN}.key ./public/${SRV_CN}.crt ; do
if [[ -f $f ]] ; then echo "$f exists already"; exit 1; fi
done
mkdir $(pwd)/temp
CAKeyFN=$(pwd)/private/${CA_CN}.key
CACrtFN=$(pwd)/public/${CA_CN}.crt
SrvKeyFN=$(pwd)/private/${SRV_CN}.key
SrvCsrFN=$(pwd)/temp/${SRV_CN}.csr
SrvCrtFN=$(pwd)/public/${SRV_CN}.crt
for f in ${SrvKeyFN} ${SrvCrtFN} ; do
if [[ -f $f ]] ; then echo "$f already exists"; exit 1; fi
done
#
# Create A Certificate
#
if ! openssl genrsa -out ${SrvKeyFN} 2048
then exit 12
fi
#
# Now generate the certificate signing request.
#
if ! openssl req -new \
-key ${SrvKeyFN} \
-subj "/C=US/ST=--/L=--/O=--/OU=--/CN=${SRV_CN}" \
-out ${SrvCsrFN}
then exit 13
fi
#
# Now generate the final certificate from the signing request.
#
if ! openssl x509 -req \
-in ${SrvCsrFN} \
-CA ${CACrtFN} \
-CAkey ${CAKeyFN} \
-CAcreateserial \
-extfile <(printf "subjectAltName=${subjectAltNameArg}") \
-out ${SrvCrtFN} -days 3650 -sha256
then exit 14
fi
}
function MakeForLighttpd {
if [[ $# -ne 2 ]] ; then
echo "three args only: CA common name, server common name"
exit 31
fi
CA_CN=${1}
SRV_CN=${2}
# DST_PIHOLE=${3}
CACrtFN=$(pwd)/public/${CA_CN}.crt
SrvKeyFN=$(pwd)/private/${SRV_CN}.key
SrvCrtFN=$(pwd)/public/${SRV_CN}.crt
mkdir -p lighttpd/ssl/Pihole-Home-Lan/private
mkdir -p lighttpd/ssl/Pihole-Home-Lan/public
chmod 750 lighttpd/ssl/Pihole-Home-Lan/private || exit 32
SrvKeyCrtFN=lighttpd/ssl/Pihole-Home-Lan/private/${SRV_CN}.key-crt.pem
SrvCAChainFN=lighttpd/ssl/Pihole-Home-Lan/public/${SRV_CN}-fullchain.pem
if ! cat ${SrvKeyFN} ${SrvCrtFN} > ${SrvKeyCrtFN}
then exit 33
fi
chmod 640 ${SrvKeyCrtFN}
if ! cat ${SrvCrtFN} ${CACrtFN} > ${SrvCAChainFN}
then exit 34
fi
# chown -R :$SUDO_USER lighttpd
# sudo --set-home -u $SUDO_USER scp -r lighttpd ${DST_PIHOLE} \
# || { chown -R :root lighttpd ; exit 35 ; }
# chown -R :root lighttpd
cat <<EOF
manually copy lighttpd directory to pihole device, e.g.
$SUDO_USER:$(pwd)# sudo chown -R :$SUDO_USER lighttpd
$SUDO_USER:$(pwd)# scp -r lighttpd user@pihole.home.lan:.
$SUDO_USER:$(pwd)# sudo chown -R :root lighttpd
$SUDO_USER:$(pwd)# ssh user@pihole.home.lan # set up for lighttpd, c.f. https://discourse.pi-hole.net/t/enabling-https-for-your-pi-hole-web-interface/5771 Note: make it www-data group readable!
EOF
}
trap "on_exit" 0
function on_exit {
exitval=$?
if [[ $exitval -eq 0 ]] ;
then echo "SUCCESS"
else echo "FAILED with error $exitval"
fi
$(exit $exitval)
}
function Usage {
cat <<EOF_
NOTE: NO SPACES ALLOWED IN COMMON NAMES - will be used as cert filenames.
$0 CreateCertificateAuthority <CA Common Name> <CA organization name>
$0 CreateServerCertificate <CA common name> <Server common name> <subjectAltNames>
$0 MakeForLighttpd <CA common name> <Server common name>
Examples:
$0 CreateCertificateAuthority Home-Lan "Self managed private certs"
$0 CreateServerCertificate Home-Lan Pihole-Home-Lan DNS:pihole.home.lan,DNS:pihole,IP:192.168.1.20
$0 MakeForLighttpd Home-Lan Pihole-Home-Lan
EOF_
}
if [[ $# -eq 0 ]] ; then Usage ; exit 1; fi
case $1 in
CreateCertificateAuthority)
if [[ $# -eq 3 ]] ; then CreateCertificateAuthority ${2} "${3}"; else Usage; fi
;;
CreateServerCertificate)
if [[ $# -eq 4 ]] ; then CreateServerCertificate ${2} ${3} ${4} ; else Usage; fi
;;
MakeForLighttpd)
if [[ $# -eq 3 ]] ; then MakeForLighttpd ${2} ${3} ; else Usage; fi
;;
*) Usage ; exit 1;
;;
esac
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment