Files
dokku/plugins/certs/commands
Justin Clark 8a1f7fb900 Cause certs:remove to return non zero on error
This was caught when writing the certs.bats. This patch will return
non zero on error instead of zero which can casue false negatives
in testing.
2015-11-11 18:18:06 -08:00

183 lines
6.3 KiB
Bash
Executable File

#!/usr/bin/env bash
[[ " certs:add certs:generate certs:info certs:remove certs:update help certs:help " == *" $1 "* ]] || exit $DOKKU_NOT_IMPLEMENTED_EXIT
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/certs/functions"
source "$PLUGIN_AVAILABLE_PATH/nginx-vhosts/functions"
is_tar_import() {
[[ -t 0 ]] && return 1
return 0
}
is_file_import() {
local CRT_FILE="$1"
local KEY_FILE="$2"
if [[ $CRT_FILE ]] && [[ $KEY_FILE ]]; then
if [[ ! -f $CRT_FILE ]]; then
dokku_log_fail "CRT file specified not found, please check file paths"
elif [[ ! -f $KEY_FILE ]]; then
dokku_log_fail "KEY file specified not found, please check file paths"
else
return 0
fi
fi
return 1
}
certs_set() {
[[ -z $2 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_app_name "$2"
APP="$2"; CRT_FILE="$3"; KEY_FILE="$4"
is_file_import $CRT_FILE $KEY_FILE || is_tar_import || dokku_log_fail "Tar archive containing server.crt and server.key expected on stdin"
if is_tar_import; then
TEMP_DIR=$(mktemp -d)
cd $TEMP_DIR
tar xvf - <&0
CRT_FILE_SEARCH=$(find . -type f -name "*.crt")
CRT_FILE_COUNT=$(printf "%s" "$CRT_FILE_SEARCH" | grep -c '^')
if [[ $CRT_FILE_COUNT -lt 1 ]]; then
dokku_log_fail "Tar archive is missing .crt file"
elif [[ $CRT_FILE_COUNT -gt 1 ]]; then
dokku_log_fail "Tar archive contains more than one .crt file"
else
CRT_FILE=$CRT_FILE_SEARCH
fi
KEY_FILE_SEARCH=$(find . -type f -name "*.key")
KEY_FILE_COUNT=$(printf "%s" "$KEY_FILE_SEARCH" | grep -c '^')
if [[ $KEY_FILE_COUNT -lt 1 ]]; then
dokku_log_fail "Tar archive is missing .key file"
elif [[ $KEY_FILE_COUNT -gt 1 ]]; then
dokku_log_fail "Tar archive contains more than one .key file"
else
KEY_FILE=$KEY_FILE_SEARCH
fi
fi
mkdir -p "$DOKKU_ROOT/$APP/tls"
cp "$CRT_FILE" "$DOKKU_ROOT/$APP/tls/server.crt"
cp "$KEY_FILE" "$DOKKU_ROOT/$APP/tls/server.key"
cd $DOKKU_ROOT
rm -rf $TEMP_DIR
nginx_build_config $APP
}
case "$1" in
certs:add)
certs_set "$@"
;;
certs:generate)
[[ -z $2 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_app_name "$2"
APP="$2"; DOMAIN="$3"; SSL_PATH="$DOKKU_ROOT/$APP/tls"
if [[ ! -f "$SSL_PATH/server.key" ]] && [[ ! -f "$SSL_PATH/server.crt" ]]; then
TMP_WORK_DIR=$(mktemp -d -t "dokku_certs.XXXXXXXXX")
trap 'rm -rf "$TMP_WORK_DIR" > /dev/null' INT TERM EXIT
pushd $TMP_WORK_DIR > /dev/null
openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
openssl rsa -passin pass:x -in server.pass.key -out server.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
mkdir -p "$DOKKU_ROOT/$APP/tls"
dokku_log_info1 "Installing certificate and key..."
mv -f $TMP_WORK_DIR/server.key $TMP_WORK_DIR/server.crt $SSL_PATH
[[ -n "$DOMAIN" ]] && (dokku domains:add $APP $DOMAIN || nginx_build_config $APP)
dokku_log_info1 "The following is a certificate signing request that can be used"
dokku_log_info1 "to generate an 'officially' signed SSL certificate for $APP at $DOMAIN"
dokku_log_info1 "by a CA of your choosing."
cat server.csr
else
dokku_log_info1 "$APP has an SSL endpoint already defined"
fi
;;
certs:info)
[[ -z $2 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_app_name "$2"
APP="$2"; SSL_TYPE=$(is_ssl_enabled $APP)
case "$SSL_TYPE" in
app)
SSL_PATH="$DOKKU_ROOT/$APP/tls"
;;
global)
SSL_PATH="$DOKKU_ROOT/tls"
;;
*)
;;
esac
if [[ -n "$SSL_PATH" ]]; then
dokku_log_info1 "Fetching SSL Endpoint info for $APP..."
dokku_log_info1 "Certificate details:"
dokku_log_info2 "Common Name(s): "
for domain in $(get_ssl_hostnames $APP | xargs); do
dokku_log_info2 " $domain"
done
dokku_log_info2 "Expires At: $(openssl x509 -in $SSL_PATH/server.crt -noout -text | grep "Not After :" | awk -F " : " '{ print $2 }')"
dokku_log_info2 "Issuer: $(openssl x509 -in $SSL_PATH/server.crt -noout -text | grep "Issuer:" | xargs | sed -e "s/Issuer: //g")"
dokku_log_info2 "Starts At: $(openssl x509 -in $SSL_PATH/server.crt -noout -text | grep "Not Before:" | awk -F ": " '{ print $2 }')"
dokku_log_info2 "Subject: $(openssl x509 -in $SSL_PATH/server.crt -noout -subject | sed -e "s:subject= ::g"| sed -e "s:^/::g" | sed -e "s:/:; :g")"
SSL_VERIFY_OUTPUT="$(openssl verify -verbose -purpose sslserver $SSL_PATH/server.crt | awk -F ':' '{ print $2 }' | tail -1 | xargs || true)"
if [[ "$SSL_VERIFY_OUTPUT" == "OK" ]]; then
SSL_SELF_SIGNED="verified by a certificate authority."
else
SSL_SELF_SIGNED="self signed."
fi
dokku_log_info2 "SSL certificate is $SSL_SELF_SIGNED"
else
dokku_log_info1 "$APP does not have an SSL endpoint"
fi
;;
certs:remove)
[[ -z $2 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_app_name "$2"
APP="$2"; APP_SSL_PATH="$DOKKU_ROOT/$APP/tls"
if [[ -d "$APP_SSL_PATH" ]]; then
dokku_log_info1 "Removing SSL endpoint from $APP"
rm -rf $APP_SSL_PATH
plugn trigger post-domains-update $APP
else
dokku_log_fail "An app-specific SSL endpoint is not defined"
fi
;;
certs:update)
certs_set "$@"
;;
help | certs:help)
cat && cat<<EOF
certs:add <app> CRT KEY, Add an ssl endpoint to an app. Can also import from a tarball on stdin
certs:chain CRT [CRT ...], [NOT IMPLEMENTED] Print the ordered and complete chain for the given certificate.
certs:generate <app> DOMAIN, Generate a key and certificate signing request (and self-signed certificate)
certs:info <app>, Show certificate information for an ssl endpoint.
certs:key <app> CRT KEY [KEY ...], [NOT IMPLEMENTED] Print the correct key for the given certificate.
certs:remove <app>, Remove an SSL Endpoint from an app.
certs:rollback <app>, [NOT IMPLEMENTED] Rollback an SSL Endpoint for an app.
certs:update <app> CRT KEY, Update an SSL Endpoint on an app. Can also import from a tarball on stdin
EOF
;;
*)
exit $DOKKU_NOT_IMPLEMENTED_EXIT
;;
esac