Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allows stateless acme cert renewal #222

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 100 additions & 4 deletions hooks/addon
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#!/bin/bash
set -eu

# Automatically set to 'true' when called by blueprint which removes all echo
# messages and uses default values for the answers
: "${SILENT_MODE:=false}"

info() { echo -e "\n\e[32m$*\e[0m"; }

header() {
local token="="
local line=$(printf "${token}%.0s" {1..80})
info "\n${line}\n${token} $*\n${line}"
}

list() {
echo "The following addons are defined:"
echo
Expand All @@ -17,6 +29,10 @@ list() {
echo
echo " stratos Deploy Stratos, the Cloud Foundry web console."
echo
echo " acme-client Install and configure the acme-client for stateless"
echo " crtificate renewal - preequisite for enabling"
echo " the '- haproxy-acme' feature"
echo
}

login() {
Expand Down Expand Up @@ -47,10 +63,86 @@ login() {
cf target
}

installacme(){
email="$(git config --global user.email)"
if [[ $SILENT_MODE != true ]]; then
header "Installing acme.sh shell script"

prompt_for email line --default "$email" \
'Type your email address'
fi
curl -s https://get.acme.sh | sh -s email=$email > /dev/null 2>&1
}



registeracme(){
if [[ $SILENT_MODE != true ]]; then
header "Registering acme client and setting vault credential"

lab_targets=($(safe targets --json 2>/dev/null | jq -r '.[].name'))

echo -e "Available targets: ${lab_targets[*]}"
current_target=$(safe target --json 2>/dev/null | jq -r '.name')

echo -e "You are currently targeting: '${current_target}'"
prompt_for change_target boolean --default false \
"Would you like to use another target?"

if [[ $change_target == "true" ]]; then
prompt_for new_target line 'Type your target'
safe target "$new_target"
fi
fi
current_thumbprint=$(safe get "$GENESIS_EXODUS_MOUNT$GENESIS_ENVIRONMENT/acme/acme:thumbprint" 2>/dev/null || true)

if [[ -n $current_thumbprint ]]; then
if [[ $SILENT_MODE != true ]]; then
prompt_for update_thumbprint boolean --default false \
"You have already set your thumbprint to '${current_thumbprint}'. Would you like to update it?"
else
update_thumbprint=false
fi
else
update_thumbprint=true
fi


if [[ $update_thumbprint == true ]]; then
thumbprint=$(~/.acme.sh/acme.sh --register-account | awk -F"'" '/ACCOUNT_THUMBPRINT=/{print $2}')
if [[ $SILENT_MODE != true ]]; then
echo -e "\n$GENESIS_EXODUS_MOUNT$GENESIS_ENVIRONMENT/acme/acme is being set with the following value:"
fi
safe set "$GENESIS_EXODUS_MOUNT$GENESIS_ENVIRONMENT/acme/acme" thumbprint="$thumbprint"
else
if [[ $SILENT_MODE != true ]]; then
echo "Skipping thumbprint update."
fi
fi
}

setup_acme(){
if [[ -x ~/.acme.sh/acme.sh ]]; then
acme_version=$(~/.acme.sh/acme.sh -v 2>/dev/null || true)
url=$(echo "$acme_version" | grep -Eo 'https?://[^ ]+' || true)
version=$(echo "$acme_version" | grep -Eo 'v[0-9]+\.[0-9]+\.[0-9]+' || true)
fi
if [[ -n $version ]]; then
if [[ $SILENT_MODE != true ]]; then
echo "You are currently using acme.sh '${version}' from '${url}'"
fi
else
installacme
fi
registeracme

}


case $GENESIS_ADDON_SCRIPT in
(list) list ; exit 0 ;;
(list) list ;;

(login) login ; exit 0 ;;
(login) login ;;

(remigrate)
# Migrate the secrets
Expand Down Expand Up @@ -90,9 +182,13 @@ case $GENESIS_ADDON_SCRIPT in
(smoketest)
"$GENESIS_BOSH_COMMAND" -e "$BOSH_ENVIRONMENT" -d "$BOSH_DEPLOYMENT" run-errand smoke_tests
;;


(acme-client)
setup_acme
;;

(*) run_extended_addon "$@" ;; # This will run the addon script in the
# $GENESIS_ADDON_SCRIPT file, if it exists.
# Ex: hooks/addon-stratos
esac

exit 0
13 changes: 13 additions & 0 deletions hooks/blueprint
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@ features::validate() {
(gcp-use-access-key)
features+=( "$want" )
;;
(haproxy-acme)
features+=( "$want" )
;;
(enable-service-discovery|ssh-proxy-on-routers|no-tcp-routers)
features+=( "$want" )
;;
Expand Down Expand Up @@ -820,6 +823,16 @@ features::process() {

want_feature "small-footprint" &&
manifests+=( "overlay/routing/haproxy-small-footprint.yml" )

if want_feature "haproxy-acme"; then
manifests+=( "overlay/routing/haproxy-acme.yml" )
(
GENESIS_ADDON_SCRIPT=acme-client
SILENT_MODE=true
source hooks/addon
)
fi

fi
done

Expand Down
15 changes: 15 additions & 0 deletions overlay/routing/haproxy-acme.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
meta:
ocfp:
certs:
acme_thumbprint: (( vault $GENESIS_EXODUS_MOUNT genesis.env "/acme/settings/cf-cert-management:acme_thumbprint" ))
instance_groups:
- name: haproxy
jobs:
- name: haproxy
properties:
ha_proxy:
frontend_config: |
acl is_acme_challenge path_beg /.well-known/acme-challenge/
http-request return status 200 content-type text/plain lf-string "%[path,field(-1,/)].%[env(ACCOUNT_THUMBPRINT)]\n" if is_acme_challenge
global_config: (( concat "setenv ACCOUNT_THUMBPRINT '" meta.ocfp.certs.acme_thumbprint "'"))