d8637b2c0f
Ubiquiti removed keytool (and java) from recent releases of Unifi OS. This moves from keytool to openssl's native pkcs12. Tested on Unifi Dream Machine which runs Unifi OS and a built-in Unifi controller. Also added backup of existing files prior to change in case anything goes wrong, and update system configuration with compatible ciphers.
205 lines
6.0 KiB
Bash
205 lines
6.0 KiB
Bash
#!/usr/bin/env sh
|
|
|
|
# Here is a script to deploy cert to routeros router.
|
|
# Deploy the cert to remote routeros
|
|
#
|
|
# ```sh
|
|
# acme.sh --deploy -d ftp.example.com --deploy-hook routeros
|
|
# ```
|
|
#
|
|
# Before you can deploy the certificate to router os, you need
|
|
# to add the id_rsa.pub key to the routeros and assign a user
|
|
# to that key.
|
|
#
|
|
# The user need to have access to ssh, ftp, read and write.
|
|
#
|
|
# There are no need to enable ftp service for the script to work,
|
|
# as they are transmitted over SCP, however ftp is needed to store
|
|
# the files on the router.
|
|
#
|
|
# Then you need to set the environment variables for the
|
|
# deploy script to work.
|
|
#
|
|
# ```sh
|
|
# export ROUTER_OS_USERNAME=certuser
|
|
# export ROUTER_OS_HOST=router.example.com
|
|
# export ROUTER_OS_PORT=22
|
|
#
|
|
# acme.sh --deploy -d ftp.example.com --deploy-hook routeros
|
|
# ```
|
|
#
|
|
# The deploy script will remove previously deployed certificates,
|
|
# and it does this with an assumption on how RouterOS names imported
|
|
# certificates, adding a "cer_0" suffix at the end. This is true for
|
|
# versions 6.32 -> 6.41.3, but it is not guaranteed that it will be
|
|
# true for future versions when upgrading.
|
|
#
|
|
# If the router have other certificates with the same name as the one
|
|
# beeing deployed, then this script will remove those certificates.
|
|
#
|
|
# At the end of the script, the services that use those certificates
|
|
# could be updated. Currently only the www-ssl service is beeing
|
|
# updated, but more services could be added.
|
|
#
|
|
# For instance:
|
|
# ```sh
|
|
# export ROUTER_OS_ADDITIONAL_SERVICES="/ip service set api-ssl certificate=$_cdomain.cer_0"
|
|
# ```
|
|
#
|
|
# One optional thing to do as well is to create a script that updates
|
|
# all the required services and run that script in a single command.
|
|
#
|
|
# To adopt parameters to `scp` and/or `ssh` set the optional
|
|
# `ROUTER_OS_SSH_CMD` and `ROUTER_OS_SCP_CMD` variables accordingly,
|
|
# see ssh(1) and scp(1) for parameters to those commands.
|
|
#
|
|
# Example:
|
|
# ```ssh
|
|
# export ROUTER_OS_SSH_CMD="ssh -i /acme.sh/.ssh/router.example.com -o UserKnownHostsFile=/acme.sh/.ssh/known_hosts"
|
|
# export ROUTER_OS_SCP_CMD="scp -i /acme.sh/.ssh/router.example.com -o UserKnownHostsFile=/acme.sh/.ssh/known_hosts"
|
|
# ````
|
|
#
|
|
# returns 0 means success, otherwise error.
|
|
|
|
######## Public functions #####################
|
|
|
|
#domain keyfile certfile cafile fullchain
|
|
routeros_deploy() {
|
|
_cdomain="$1"
|
|
_ckey="$2"
|
|
_ccert="$3"
|
|
_cca="$4"
|
|
_cfullchain="$5"
|
|
_err_code=0
|
|
|
|
_debug _cdomain "$_cdomain"
|
|
_debug _ckey "$_ckey"
|
|
_debug _ccert "$_ccert"
|
|
_debug _cca "$_cca"
|
|
_debug _cfullchain "$_cfullchain"
|
|
|
|
_getdeployconf ROUTER_OS_HOST
|
|
|
|
if [ -z "$ROUTER_OS_HOST" ]; then
|
|
_debug "Using _cdomain as ROUTER_OS_HOST, please set if not correct."
|
|
ROUTER_OS_HOST="$_cdomain"
|
|
fi
|
|
|
|
_getdeployconf ROUTER_OS_USERNAME
|
|
|
|
if [ -z "$ROUTER_OS_USERNAME" ]; then
|
|
_err "Need to set the env variable ROUTER_OS_USERNAME"
|
|
return 1
|
|
fi
|
|
|
|
_getdeployconf ROUTER_OS_PORT
|
|
|
|
if [ -z "$ROUTER_OS_PORT" ]; then
|
|
_debug "Using default port 22 as ROUTER_OS_PORT, please set if not correct."
|
|
ROUTER_OS_PORT=22
|
|
fi
|
|
|
|
_getdeployconf ROUTER_OS_SSH_CMD
|
|
|
|
if [ -z "$ROUTER_OS_SSH_CMD" ]; then
|
|
_debug "Use default ssh setup."
|
|
ROUTER_OS_SSH_CMD="ssh -p $ROUTER_OS_PORT"
|
|
fi
|
|
|
|
_getdeployconf ROUTER_OS_SCP_CMD
|
|
|
|
if [ -z "$ROUTER_OS_SCP_CMD" ]; then
|
|
_debug "USe default scp setup."
|
|
ROUTER_OS_SCP_CMD="scp -P $ROUTER_OS_PORT"
|
|
fi
|
|
|
|
_getdeployconf ROUTER_OS_ADDITIONAL_SERVICES
|
|
|
|
if [ -z "$ROUTER_OS_ADDITIONAL_SERVICES" ]; then
|
|
_debug "Not enabling additional services"
|
|
ROUTER_OS_ADDITIONAL_SERVICES=""
|
|
fi
|
|
|
|
_savedeployconf ROUTER_OS_HOST "$ROUTER_OS_HOST"
|
|
_savedeployconf ROUTER_OS_USERNAME "$ROUTER_OS_USERNAME"
|
|
_savedeployconf ROUTER_OS_PORT "$ROUTER_OS_PORT"
|
|
_savedeployconf ROUTER_OS_SSH_CMD "$ROUTER_OS_SSH_CMD"
|
|
_savedeployconf ROUTER_OS_SCP_CMD "$ROUTER_OS_SCP_CMD"
|
|
_savedeployconf ROUTER_OS_ADDITIONAL_SERVICES "$ROUTER_OS_ADDITIONAL_SERVICES"
|
|
|
|
# push key to routeros
|
|
if ! _scp_certificate "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key"; then
|
|
return $_err_code
|
|
fi
|
|
|
|
# push certificate chain to routeros
|
|
if ! _scp_certificate "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer"; then
|
|
return $_err_code
|
|
fi
|
|
|
|
DEPLOY_SCRIPT_CMD=":do {/system script remove \"LECertDeploy-$_cdomain\" } on-error={ }; \
|
|
/system script add name=\"LECertDeploy-$_cdomain\" owner=$ROUTER_OS_USERNAME \
|
|
comment=\"generated by routeros deploy script in acme.sh\" \
|
|
source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
|
|
\n/certificate remove [ find name=$_cdomain.cer_1 ];\
|
|
\n/certificate remove [ find name=$_cdomain.cer_2 ];\
|
|
\ndelay 1;\
|
|
\n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\
|
|
\n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\
|
|
\ndelay 1;\
|
|
\n:do {/file remove $_cdomain.cer; } on-error={ }\
|
|
\n:do {/file remove $_cdomain.key; } on-error={ }\
|
|
\ndelay 2;\
|
|
\n/ip service set www-ssl certificate=$_cdomain.cer_0;\
|
|
\n$ROUTER_OS_ADDITIONAL_SERVICES;\
|
|
\n\"
|
|
"
|
|
|
|
if ! _ssh_remote_cmd "$DEPLOY_SCRIPT_CMD"; then
|
|
return $_err_code
|
|
fi
|
|
|
|
if ! _ssh_remote_cmd "/system script run \"LECertDeploy-$_cdomain\""; then
|
|
return $_err_code
|
|
fi
|
|
|
|
if ! _ssh_remote_cmd "/system script remove \"LECertDeploy-$_cdomain\""; then
|
|
return $_err_code
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# inspired by deploy/ssh.sh
|
|
_ssh_remote_cmd() {
|
|
_cmd="$1"
|
|
_secure_debug "Remote commands to execute: $_cmd"
|
|
_info "Submitting sequence of commands to routeros"
|
|
# quotations in bash cmd below intended. Squash travis spellcheck error
|
|
# shellcheck disable=SC2029
|
|
$ROUTER_OS_SSH_CMD "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "$_cmd"
|
|
_err_code="$?"
|
|
|
|
if [ "$_err_code" != "0" ]; then
|
|
_err "Error code $_err_code returned from routeros"
|
|
fi
|
|
|
|
return $_err_code
|
|
}
|
|
|
|
_scp_certificate() {
|
|
_src="$1"
|
|
_dst="$2"
|
|
_secure_debug "scp '$_src' to '$_dst'"
|
|
_info "Push key '$_src' to routeros"
|
|
|
|
$ROUTER_OS_SCP_CMD "$_src" "$_dst"
|
|
_err_code="$?"
|
|
|
|
if [ "$_err_code" != "0" ]; then
|
|
_err "Error code $_err_code returned from scp"
|
|
fi
|
|
|
|
return $_err_code
|
|
}
|