Last active
July 29, 2021 15:58
-
-
Save rhymeswithmogul/2538f5c20d4cb81215e4566a0669231e to your computer and use it in GitHub Desktop.
Get a valid certificate for the UniFi Controller
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 | |
######################################################################### | |
# renew-unifi-cert.sh (Version 1.1, 2019-11-21) | |
# Copyright © 2019 Colin Cogle <colin@colincogle.name> | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU Affero 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 Affero General Public License | |
# along with this program. If not, see <https://www.gnu.org/licenses/>. | |
######################################################################### | |
# | |
# The latest version of this script can be found at: | |
# https://gist.github.com/rhymeswithmogul/2538f5c20d4cb81215e4566a0669231e | |
# | |
######################################################################### | |
# Set this to your UniFi Controller installation directory. | |
# When using the Ubuntu repos, this defaulted to /usr/lib/unifi. | |
UNIFI_BASE=/usr/lib/unifi | |
# Create a subdirectory for your certificate files. | |
CERT_BASE=$UNIFI_BASE/letsencrypt | |
# Fail immediately if an error is encountered, | |
# or if I've used an unknown variable. | |
set -eu | |
# If we have the old *chain file, see what the date is. | |
# Let's renew when there are less than 30 days left on the certificate. | |
if [ -f $CERT_BASE/0001_chain.pem ] | |
then | |
NOT_AFTER=$(/usr/bin/openssl x509 -in $CERT_BASE/0001_chain.pem -noout -text | /bin/grep 'Not After:' | /bin/sed -e "s/\s*Not After: //") | |
CERTIFICATE_DATE=$(/bin/date -d "$NOT_AFTER" +"%Y%m%d") | |
if [ $CERTIFICATE_DATE -le $(/bin/date -d "-30 days" +"%Y%m%d") ] | |
then | |
/bin/echo "The UniFi certificate is less than sixty days old. It will not be renewed at this time." | |
exit 0 | |
fi | |
fi | |
if [ ! -f $CERT_BASE/openssl.cnf ] | |
then | |
/bin/echo "The OpenSSL batch file is missing. Creating a new one." | |
/bin/cat << OPENSSL_CNF > $CERT_BASE/openssl.cnf | |
[req] | |
req_extensions = v3_req | |
default_bits = 2048 | |
default_md = sha256 | |
default_keyfile = private.key | |
prompt = no | |
encrypt_key = no | |
string_mask = nombstr | |
distinguished_name = req_dn | |
[v3_req] | |
basicConstraints = CA:FALSE | |
keyUsage = nonRepudiation, digitalSignature, keyEncipherment | |
subjectAltName = @san | |
[req_dn] | |
commonName = "unifi.example.com" | |
[san] | |
DNS.1 = unifi.example.com | |
DNS.2 = unifi.example.net | |
OPENSSL_CNF | |
/bin/echo "Please edit this file and add your UniFi domain names, then re-run this script." | |
exit 78 #EX_CONFIG | |
fi | |
# If the private key has been deleted, create a new one. | |
if [ ! -f $CERT_BASE/private.key ] | |
then | |
/bin/echo "The private key is missing. Creating a new one." | |
/usr/bin/openssl ecparam -name secp256r1 -genkey -noout -out $CERT_BASE/private.key | |
/bin/chown root:unifi $CERT_BASE/private.key | |
/bin/chmod 660 $CERT_BASE/private.key | |
/bin/rm -f $CERT_BASE/public.csr | |
fi | |
# Make a new CSR if we have generated a new private key, updated OpenSSL.cnf, | |
# or if the previous CSR is missing for whatever reason. | |
if [ ! -f $CERT_BASE/public.csr ] || [ "$CERT_BASE/public.csr" -ot "$CERT_BASE/openssl.cnf" ] | |
then | |
/bin/echo "The CSR is missing, outdated, or we made a new private key. Generating a new one." | |
/usr/bin/openssl req -new -key $CERT_BASE/private.key -sha256 -nodes -out $CERT_BASE/public.csr -outform DER -config $CERT_BASE/openssl.cnf | |
/bin/chown root:unifi $CERT_BASE/public.csr | |
/bin/chmod 664 $CERT_BASE/public.csr | |
fi | |
# Delete the old certificates. Then, start a temporary Web server and get a new certificate. | |
# TCP port 80 must not be blocked by your firewall. If using IPv4, forward it to your controller, too. | |
/bin/echo "Deleting old certificates." | |
/bin/rm -f $CERT_BASE/00??_chain.pem | |
/bin/rm -f $CERT_BASE/00??_cert.pem | |
/bin/echo "Requesting a new certificate from Let's Encrypt." | |
/usr/bin/letsencrypt certonly --csr $CERT_BASE/public.csr --standalone | |
# Convert it to PKCS #12 format, which UniFi supports. | |
/bin/echo "Converting to PKCS #12." | |
/usr/bin/openssl pkcs12 -export -in $CERT_BASE/0001_chain.pem -inkey $CERT_BASE/private.key -caname root -out $CERT_BASE/unifi.p12 -name unifi -passout pass:aircontrolenterprise | |
# Import into UniFi. | |
/bin/echo "Importing into UniFi." | |
/usr/bin/keytool -importkeystore -srcstoretype PKCS12 -srckeystore $CERT_BASE/unifi.p12 -srcstorepass aircontrolenterprise -destkeystore $UNIFI_BASE/data/keystore -destkeypass aircontrolenterprise -deststorepass aircontrolenterprise -alias unifi -noprompt | |
# Restart the Controller. | |
/bin/echo "Restarting UniFi." | |
/bin/systemctl restart unifi | |
/bin/echo "Done." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment