Skip to content

Commit

Permalink
openssl: Improve cert generation and generate vpn certs
Browse files Browse the repository at this point in the history
* use easyrsa for cert generation/management
* generate vpn requirements (ca, crt, dh)
* remove `node` requirement for generating jwt kid
* fix root ca cert generation
* fix haproxy certificate generation

Signed-off-by: Will Boyce <will@resin.io>
  • Loading branch information
wrboyce authored and Will Boyce committed Sep 27, 2018
1 parent 3a0bed7 commit 8be8bca
Show file tree
Hide file tree
Showing 12 changed files with 234 additions and 209 deletions.
6 changes: 6 additions & 0 deletions compose/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ services:
SENTRY_DSN:
VPN_HAPROXY_USEPROXYPROTOCOL: 'true'
VPN_SERVICE_API_KEY: ${OPENBALENA_VPN_SERVICE_API_KEY}
VPN_OPENVPN_CA_CRT: ${OPENBALENA_VPN_CA}
VPN_OPENVPN_SERVER_CRT: ${OPENBALENA_VPN_SERVER_CRT}
VPN_OPENVPN_SERVER_KEY: ${OPENBALENA_VPN_SERVER_KEY}
VPN_OPENVPN_SERVER_DH: ${OPENBALENA_VPN_SERVER_DH}
# FIXME: remove all of the following
API_SERVICE_API_KEY: __unused__
PROXY_SERVICE_API_KEY: __unused__5
Expand Down Expand Up @@ -176,6 +180,8 @@ services:
- img.${OPENBALENA_HOST_NAME}
environment:
BALENA_ROOT_CA: ${OPENBALENA_ROOT_CA}
BALENA_HAPROXY_CRT: ${OPENBALENA_ROOT_CRT}
BALENA_HAPROXY_KEY: ${OPENBALENA_ROOT_KEY}
HAPROXY_HOSTNAME: ${OPENBALENA_HOST_NAME}

# FIXME: remove the following
Expand Down
17 changes: 9 additions & 8 deletions haproxy/entry.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/bin/sh
#!/bin/bash -eu

CA_B64="$BALENA_ROOT_CA"
CA_FILE=/etc/ssl/private/root.chain.pem

mkdir -p $(dirname "$CA_FILE")
echo "$CA_B64" | base64 -d >"$CA_FILE"

exec haproxy -f /usr/local/etc/haproxy/haproxy.cfg
HAPROXY_CHAIN=/etc/ssl/private/open-balena.pem
mkdir -p "$(dirname "${HAPROXY_CHAIN}")"
(
echo "${BALENA_HAPROXY_CRT}" | base64 -d
echo "${BALENA_HAPROXY_KEY}" | base64 -d
echo "${BALENA_ROOT_CA}" | base64 -d
) > "${HAPROXY_CHAIN}"
exec haproxy -f /usr/local/etc/haproxy/haproxy.cfg
2 changes: 1 addition & 1 deletion haproxy/haproxy.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ backend redirect-to-https-in
frontend https-in
mode http
option forwardfor
bind 127.0.0.1:444 ssl crt /etc/ssl/private/root.chain.pem accept-proxy
bind 127.0.0.1:444 ssl crt /etc/ssl/private/open-balena.pem accept-proxy
reqadd X-Forwarded-Proto:\ https

acl host_api hdr_dom(host) -i "api.${HAPROXY_HOSTNAME}"
Expand Down
79 changes: 0 additions & 79 deletions scripts/_keyid.js

This file was deleted.

32 changes: 32 additions & 0 deletions scripts/gen-root-ca
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash -eu

usage() {
echo "usage: $0 COMMON_NAME [OUT]"
echo
echo " COMMON_NAME the domain name the certificate is valid for, eg. example.com"
echo " OUT path to output directory generated files will be placed in"
echo
}

if [ -z "$1" ]; then
usage
exit 1
fi

CMD="$(realpath "$0")"
DIR="$(dirname "${CMD}")"

CN="$1"
OUT="$(realpath "${2:-.}")"

source "${DIR}/ssl-common.sh"

# Create a secret key and CA file for the self-signed CA
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" init-pki 2>/dev/null
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" --days="${CA_EXPIRY_DAYS}" --req-cn="ca.${CN}" build-ca nopass 2>/dev/null
ROOT_CA="${ROOT_PKI}/ca.crt"
echo "ROOT_CA=${ROOT_CA//$OUT/\$OUT}"

# update indexes and generate CRLs
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" update-db 2>/dev/null
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" gen-crl 2>/dev/null
55 changes: 0 additions & 55 deletions scripts/gen-root-ca-cert

This file was deleted.

33 changes: 33 additions & 0 deletions scripts/gen-root-cert
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash -eu

usage() {
echo "usage: $0 COMMON_NAME [OUT]"
echo
echo " COMMON_NAME the domain name the certificate is valid for, eg. example.com"
echo " OUT path to output directory generated files will be placed in"
echo
}

if [ -z "$1" ]; then
usage
exit 1
fi

CMD="$(realpath "$0")"
DIR="$(dirname "${CMD}")"

CN="$1"
OUT="$(realpath "${2:-.}")"

source "${DIR}/ssl-common.sh"

# generate default CSR and sign (root + wildcard)
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" --days="${CRT_EXPIRY_DAYS}" --subject-alt-name="DNS:${CN}" build-server-full "*.${CN}" nopass 2>/dev/null
ROOT_CRT="${ROOT_PKI}"'/issued/*.'"${CN}"'.crt'
ROOT_KEY="${ROOT_PKI}"'/private/*.'"${CN}"'.key'
echo "ROOT_CRT=${ROOT_CRT//$OUT/\$OUT}"
echo "ROOT_KEY=${ROOT_KEY//$OUT/\$OUT}"

# update indexes and generate CRLs
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" update-db 2>/dev/null
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" gen-crl 2>/dev/null
58 changes: 29 additions & 29 deletions scripts/gen-token-auth-cert
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
#!/bin/sh

set -e

CMD=$0
DIR=$(dirname "$CMD")

CN=$1
OUT=${2:-.}

CERT_FILE="${OUT}/token-auth"
EXPIRY_DAYS=730
#!/bin/bash -eu

usage() {
echo "usage: $0 HOST_NAME [OUT]"
echo "usage: $0 COMMON_NAME [OUT]"
echo
echo " HOST_NAME the domain name the certificate is valid for, eg. example.com"
echo " COMMON_NAME the domain name the certificate is valid for, eg. example.com"
echo " OUT path to output directory generated files will be placed in"
echo
}

keyid() {
# FIXME: do this in bash or python, not node
nodejs "${DIR}/_keyid.js" "$1"
}

if [ -z "$CN" ]; then
if [ -z "$1" ]; then
usage
exit 1
fi

openssl ecparam -name prime256v1 -genkey -noout -out "${CERT_FILE}.pem" 2>/dev/null
openssl req -x509 -new -nodes -days "${EXPIRY_DAYS}" -key "${CERT_FILE}.pem" -subj "/CN=api.${CN}" -out "${CERT_FILE}.crt" 2>/dev/null
openssl ec -in "${CERT_FILE}.pem" -pubout -outform DER -out "${CERT_FILE}".der 2>/dev/null
keyid "${CERT_FILE}".der >"${CERT_FILE}".kid
CMD="$(realpath "$0")"
DIR="$(dirname "${CMD}")"

CN="$1"
OUT="$(realpath "${2:-.}")"

source "${DIR}/ssl-common.sh"

keyid() {
local sha256="$(openssl ec -in "$1" -pubout -outform DER 2>/dev/null | openssl sha256 -binary)"
python -c "from base64 import b32encode as b32; import sys; s=b32(sys.argv[1][:30]); sys.stdout.write(':'.join([s[i:i+4] for i in range(0, len(s), 4)]))" "${sha256}"
}

# generate api CSR and sign
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" --days=730 --use-algo=ec --curve=prime256v1 build-server-full "api.${CN}" nopass 2>/dev/null
JWT_CRT="${ROOT_PKI}/issued/api.${CN}.crt"
JWT_KEY="${ROOT_PKI}/private/api.${CN}.key"
echo "JWT_CRT=${JWT_CRT//$OUT/\$OUT}"
echo "JWT_KEY=${JWT_KEY//$OUT/\$OUT}"

# Cleanup
rm "${CERT_FILE}.der"
# update indexes and generate CRLs
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" update-db 2>/dev/null
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" gen-crl 2>/dev/null

echo "PUB=${CERT_FILE}.crt"
echo "KEY=${CERT_FILE}.pem"
echo "KID=${CERT_FILE}.kid"
# generate key ID
JWT_KID="$(keyid "${JWT_CRT}")"
echo "JWT_KID=${JWT_KID//$OUT/\$OUT}"
52 changes: 52 additions & 0 deletions scripts/gen-vpn-certs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash -eu

usage() {
echo "usage: $0 COMMON_NAME [OUT]"
echo
echo " COMMON_NAME the domain name the certificate is valid for, eg. example.com"
echo " OUT path to output directory generated files will be placed in"
echo
}

if [ -z "$1" ]; then
usage
exit 1
fi

CMD="$(realpath "$0")"
DIR="$(dirname "${CMD}")"

CN="$1"
OUT="$(realpath "${2:-.}")"

source "${DIR}/ssl-common.sh"
VPN_PKI="$(realpath "${OUT}/vpn")"

# generate VPN sub-CA
"$easyrsa_bin" --pki-dir="${VPN_PKI}" init-pki 2>/dev/null
"$easyrsa_bin" --pki-dir="${VPN_PKI}" --days="${CA_EXPIRY_DAYS}" --req-cn="vpn-ca.${CN}" build-ca nopass subca 2>/dev/null

# import sub-CA CSR into root PKI, sign, and copy back to vpn PKI
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" import-req "${VPN_PKI}/reqs/ca.req" "vpn-ca" 2>/dev/null
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" sign-req ca "vpn-ca" 2>/dev/null
cp "${ROOT_PKI}/issued/vpn-ca.crt" "${VPN_PKI}/ca.crt"
VPN_CA="${VPN_PKI}/ca.crt"
echo "VPN_CA=${VPN_CA//$OUT/\$OUT}"

# generate and sign vpn server certificate
"$easyrsa_bin" --pki-dir="${VPN_PKI}" --days="${CRT_EXPIRY_DAYS}" build-server-full "vpn.${CN}" nopass 2>/dev/null
VPN_CRT="${VPN_PKI}/issued/vpn.${CN}.crt"
VPN_KEY="${VPN_PKI}/private/vpn.${CN}.key"
echo "VPN_CRT=${VPN_CRT//$OUT/\$OUT}"
echo "VPN_KEY=${VPN_KEY//$OUT/\$OUT}"

# generate vpn dhparams
"$easyrsa_bin" --pki-dir="${VPN_PKI}" gen-dh 2>/dev/null
VPN_DH="${VPN_PKI}/dh.pem"
echo "VPN_DH=${VPN_DH//$OUT/\$OUT}"

# update indexes and generate CRLs
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" update-db 2>/dev/null
"$easyrsa_bin" --pki-dir="${VPN_PKI}" update-db 2>/dev/null
"$easyrsa_bin" --pki-dir="${ROOT_PKI}" gen-crl 2>/dev/null
"$easyrsa_bin" --pki-dir="${VPN_PKI}" gen-crl 2>/dev/null
Loading

0 comments on commit 8be8bca

Please sign in to comment.