From 26febd844b3cdb8d239fe1ddbb763e45d8805205 Mon Sep 17 00:00:00 2001 From: threeplanetssoftware Date: Thu, 11 Jul 2019 21:26:17 -0400 Subject: [PATCH 01/12] Updated README and settings file to reflect the use of RSA private keys, vice DSA. RSA private keys require manual intervention from the user to add a PubkeyAcceptedKeyTypes setting to their SSH config file in OpenSSH 7+ and users may not be aware. --- README.md | 18 +++++++++--------- letsencrypt-routeros.settings | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 0a770b2..0cdd0e6 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ### How it works: * Dedicated Linux renew and push certificates to RouterOS / Mikrotik * After CertBot renew your certificates -* The script connects to RouterOS / Mikrotik using DSA Key (without password or user input) +* The script connects to RouterOS / Mikrotik using RSA Key (without password or user input) * Delete previous certificate files * Delete the previous certificate * Upload two new files: **Certificate** and **Key** @@ -35,7 +35,7 @@ vim /opt/letsencrypt-routeros/letsencrypt-routeros.settings | ROUTEROS_USER | admin | user with admin rights to connect to RouterOS | | ROUTEROS_HOST | 10.0.254.254 | RouterOS\Mikrotik IP | | ROUTEROS_SSH_PORT | 22 | RouterOS\Mikrotik PORT | -| ROUTEROS_PRIVATE_KEY | /opt/letsencrypt-routeros/id_dsa | Private Key to connecto to RouterOS | +| ROUTEROS_PRIVATE_KEY | /opt/letsencrypt-routeros/id_rsa | Private RSA Key to connecto to RouterOS | | DOMAIN | mydomain.com | Use main domain for wildcard certificate or subdomain for subdomain certificate | @@ -43,18 +43,18 @@ Change permissions: ```sh chmod +x /opt/letsencrypt-routeros/letsencrypt-routeros.sh ``` -Generate DSA Key for RouterOS +Generate RSA Key for RouterOS *Make sure to leave the passphrase blank (-N "")* ```sh -ssh-keygen -t dsa -f /opt/letsencrypt-routeros/id_dsa -N "" +ssh-keygen -t rsa -f /opt/letsencrypt-routeros/id_rsa -N "" ``` -Send Generated DSA Key to RouterOS / Mikrotik +Send Generated RSA Key to RouterOS / Mikrotik ```sh source /opt/letsencrypt-routeros/letsencrypt-routeros.settings -scp -P $ROUTEROS_SSH_PORT /opt/letsencrypt-routeros/id_dsa.pub "$ROUTEROS_USER"@"$ROUTEROS_HOST":"id_dsa.pub" +scp -P $ROUTEROS_SSH_PORT /opt/letsencrypt-routeros/id_rsa.pub "$ROUTEROS_USER"@"$ROUTEROS_HOST":"id_rsa.pub" ``` ### Setup RouterOS / Mikrotik side @@ -67,8 +67,8 @@ scp -P $ROUTEROS_SSH_PORT /opt/letsencrypt-routeros/id_dsa.pub "$ROUTEROS_USER"@ :put "Enable SSH" /ip service enable ssh -:put "Add to the user DSA Public Key" -/user ssh-keys import user=admin public-key-file=id_dsa.pub +:put "Add to the user RSA Public Key" +/user ssh-keys import user=admin public-key-file=id_rsa.pub ``` ### CertBot Let's Encrypt @@ -92,7 +92,7 @@ certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public- ``` ### Usage of the script -*To use settings form the settings file:* +*To use settings from the settings file:* ```sh ./opt/letsencrypt-routeros/letsencrypt-routeros.sh ``` diff --git a/letsencrypt-routeros.settings b/letsencrypt-routeros.settings index 7b59f7b..5bb344e 100644 --- a/letsencrypt-routeros.settings +++ b/letsencrypt-routeros.settings @@ -5,5 +5,5 @@ ROUTEROS_USER=admin ROUTEROS_HOST=10.0.254.254 ROUTEROS_SSH_PORT=22 -ROUTEROS_PRIVATE_KEY=/opt/letsencrypt-routeros/id_dsa +ROUTEROS_PRIVATE_KEY=/opt/letsencrypt-routeros/id_rsa DOMAIN=vpnserver.yourdomain.com From 763ca6e066ac65e8dfde1d1df2e52abac59be23d Mon Sep 17 00:00:00 2001 From: threeplanetssoftware Date: Thu, 11 Jul 2019 22:04:24 -0400 Subject: [PATCH 02/12] Updated script to add in auto-setting of api-ssl, www-ssl services, as well as additional debugging information for the user. Added variables for key phrases that are repeated to cut down on typo options and ease of changing in the future. --- letsencrypt-routeros.sh | 56 +++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 10 deletions(-) mode change 100644 => 100755 letsencrypt-routeros.sh diff --git a/letsencrypt-routeros.sh b/letsencrypt-routeros.sh old mode 100644 new mode 100755 index a654821..d4642ed --- a/letsencrypt-routeros.sh +++ b/letsencrypt-routeros.sh @@ -21,9 +21,17 @@ fi CERTIFICATE=/etc/letsencrypt/live/$DOMAIN/cert.pem KEY=/etc/letsencrypt/live/$DOMAIN/privkey.pem +echo "" +echo "Updating certificate for $DOMAIN" +echo " Using certificate $CERTIFICATE" +echo " User private key $KEY" + #Create alias for RouterOS command routeros="ssh -i $ROUTEROS_PRIVATE_KEY $ROUTEROS_USER@$ROUTEROS_HOST -p $ROUTEROS_SSH_PORT" +echo "" +echo "Checking connection to RouterOS" + #Check connection to RouterOS $routeros /system resource print RESULT=$? @@ -48,32 +56,60 @@ if [ ! -f $CERTIFICATE ] && [ ! -f $KEY ]; then exit 1 fi +# Set up variables to remove erros +DOMAIN_INSTALLED_CERT_FILE=$DOMAIN.pem_0 +DOMAIN_CERT_FILE=$DOMAIN.pem +DOMAIN_KEY_FILE=$DOMAIN.key + # Remove previous certificate -$routeros /certificate remove [find name=$DOMAIN.pem_0] +echo "Removing old certificate from installed certificates: $DOMAIN_INSTALLED_CERT_FILE" +$routeros /certificate remove [find name=$DOMAIN_INSTALLED_CERT_FILE] +echo "" +echo "Handling new certificate file" # Create Certificate # Delete Certificate file if the file exist on RouterOS -$routeros /file remove $DOMAIN.pem > /dev/null +echo " Deleting any old copy of certificate file from disk: $DOMAIN_CERT_FILE" +$routeros /file remove $DOMAIN_CERT_FILE > /dev/null # Upload Certificate to RouterOS -scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$CERTIFICATE" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN.pem" +echo " Uploading new domain certificate file to router: $CERTIFICATE" +scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$CERTIFICATE" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN_CERT_FILE" sleep 2 # Import Certificate file -$routeros /certificate import file-name=$DOMAIN.pem passphrase=\"\" +echo " Importing new certificate file to router certificates" +$routeros /certificate import file-name=$DOMAIN_CERT_FILE passphrase=\"\" # Delete Certificate file after import -$routeros /file remove $DOMAIN.pem +echo " Deleting any new copy of certificate file from disk: $DOMAIN_CERT_FILE" +$routeros /file remove $DOMAIN_CERT_FILE +echo "" +echo "Handling new key file" # Create Key # Delete Certificate file if the file exist on RouterOS -$routeros /file remove $KEY.key > /dev/null +echo " Deleting any old copy of key file from disk: $DOMAIN_KEY_FILE" +$routeros /file remove $DOMAIN_KEY_FILE > /dev/null # Upload Key to RouterOS -scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$KEY" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN.key" +echo " Uploading new domain key file to router: $KEY" +scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$KEY" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN_KEY_FILE" sleep 2 # Import Key file -$routeros /certificate import file-name=$DOMAIN.key passphrase=\"\" +echo " Importing new key file to router certificates" +$routeros /certificate import file-name=$DOMAIN_KEY_FILE passphrase=\"\" # Delete Certificate file after import -$routeros /file remove $DOMAIN.key +echo " Deleting any new copy of key file from disk: $DOMAIN_KEY_FILE" +$routeros /file remove $DOMAIN_KEY_FILE + +echo "" # Setup Certificate to SSTP Server -$routeros /interface sstp-server server set certificate=$DOMAIN.pem_0 +echo "Updating SSTP Server to use $DOMAIN_INSTALLED_CERT_FILE" +$routeros /interface sstp-server server set certificate=$DOMAIN_INSTALLED_CERT_FILE + +# Setup Certificate to SSL +echo "Updating HTTPS Server to use $DOMAIN_INSTALLED_CERT_FILE" +$routeros /ip service set www-ssl certificate=$DOMAIN_INSTALLED_CERT_FILE + +echo "Updating API SSL Server to use $DOMAIN_INSTALLED_CERT_FILE" +$routeros /ip service set api-ssl certificate=$DOMAIN_INSTALLED_CERT_FILE exit 0 From 1822cb60853aa2f1e274b639ed7e8bcf487de303 Mon Sep 17 00:00:00 2001 From: threeplanetssoftware Date: Thu, 11 Jul 2019 22:29:03 -0400 Subject: [PATCH 03/12] Updated README to add the fact of setting the www-ssl and api-ssl certificates and fixed typo --- README.md | 5 ++++- letsencrypt-routeros.sh | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0cdd0e6..e48fcdd 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ **Let's Encrypt certificates for RouterOS / Mikrotik** *UPD 2018-05-27: Works with wildcard Let's Encrypt Domains* +*UPD 2019-07-11: Works with OpenSSH 7+* [![Mikrotik](https://i.mt.lv/mtv2/logo.svg)](https://mikrotik.com/) @@ -15,7 +16,9 @@ * Upload two new files: **Certificate** and **Key** * Import **Certificate** and **Key** * Change **SSTP Server Settings** to use new certificate -* Delete certificate and key files form RouterOS / Mikrotik storage +* Change **WWW-SSL Service** to use new certificate +* Change **API-SSL Service** to use new certificate +* Delete certificate and key files from RouterOS / Mikrotik storage ### Installation on Ubuntu 16.04 *Similar way you can use on Debian/CentOS/AMI Linux/Arch/Others* diff --git a/letsencrypt-routeros.sh b/letsencrypt-routeros.sh index d4642ed..27d6c2d 100755 --- a/letsencrypt-routeros.sh +++ b/letsencrypt-routeros.sh @@ -56,7 +56,7 @@ if [ ! -f $CERTIFICATE ] && [ ! -f $KEY ]; then exit 1 fi -# Set up variables to remove erros +# Set up variables to remove errors DOMAIN_INSTALLED_CERT_FILE=$DOMAIN.pem_0 DOMAIN_CERT_FILE=$DOMAIN.pem DOMAIN_KEY_FILE=$DOMAIN.key From e767e47aad92b5f5ec95c7fc4eb91f1070e7af22 Mon Sep 17 00:00:00 2001 From: threeplanetssoftware Date: Thu, 11 Jul 2019 22:30:55 -0400 Subject: [PATCH 04/12] Fixed formatting --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e48fcdd..3ad9c66 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ **Let's Encrypt certificates for RouterOS / Mikrotik** *UPD 2018-05-27: Works with wildcard Let's Encrypt Domains* + *UPD 2019-07-11: Works with OpenSSH 7+* [![Mikrotik](https://i.mt.lv/mtv2/logo.svg)](https://mikrotik.com/) From 15195d5abdd0891a5fec0818ed2787aa780e5ee1 Mon Sep 17 00:00:00 2001 From: threeplanetssoftware Date: Thu, 11 Jul 2019 22:32:04 -0400 Subject: [PATCH 05/12] Removed duplicative section of README after changes to script --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index 3ad9c66..88fdf66 100644 --- a/README.md +++ b/README.md @@ -114,13 +114,6 @@ certbot certonly --preferred-challenges=dns --manual -d *.$DOMAIN --manual-publi certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public-ip-logging-ok --post-hook /opt/letsencrypt-routeros/letsencrypt-routeros.sh ``` -### Edit Script -You can easily edit script to execute your commands on RouterOS / Mikrotik after certificates renewal -Add these strings in the «.sh» file before «exit 0» to have www-ssl and api-ssl works with Let's Encrypt SSL -```sh -$routeros /ip service set www-ssl certificate=$DOMAIN.pem_0 -$routeros /ip service set api-ssl certificate=$DOMAIN.pem_0 -``` --- ### Licence MIT Copyright 2018 Konstantin Gimpel From f47ee5855f225157c87d9d6f398ffe76451190e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0uvada?= Date: Sun, 9 Oct 2022 17:00:33 +0200 Subject: [PATCH 06/12] Add arguments and handling of custom configs and services --- letsencrypt-routeros.sh | 132 ++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 51 deletions(-) diff --git a/letsencrypt-routeros.sh b/letsencrypt-routeros.sh index 27d6c2d..2f22e81 100755 --- a/letsencrypt-routeros.sh +++ b/letsencrypt-routeros.sh @@ -1,33 +1,56 @@ #!/bin/bash -CONFIG_FILE=letsencrypt-routeros.settings - -if [[ -z $1 ]] || [[ -z $2 ]] || [[ -z $3 ]] || [[ -z $4 ]] || [[ -z $5 ]]; then - echo -e "Usage: $0 or $0 [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]\n" - source $CONFIG_FILE -else - ROUTEROS_USER=$1 - ROUTEROS_HOST=$2 - ROUTEROS_SSH_PORT=$3 - ROUTEROS_PRIVATE_KEY=$4 - DOMAIN=$5 +#set -x + +while getopts 'u:h:p:k:d:c:' OPTION; do + case "$OPTION" in + u) + ROUTEROS_USER=${OPTARG} + ;; + h) + ROUTEROS_HOST=${OPTARG} + ;; + p) + ROUTEROS_SSH_PORT=${OPTARG} + ;; + k) + ROUTEROS_PRIVATE_KEY=${OPTARG} + ;; + d) + DOMAIN=${OPTARG} + ;; + c) + CONFIG=${OPTARG} + ;; + esac +done +shift "$(($OPTIND -1))" + +if [[ -n ${CONFIG} ]]; then + source $CONFIG +elif [[ -z ${ROUTEROS_USER} ]] || [[ -z ${ROUTEROS_HOST} ]] || [[ -z ${ROUTEROS_SSH_PORT} ]] || [[ -z ${ROUTEROS_PRIVATE_KEY} ]] || [[ -z ${DOMAIN} ]]; then + echo -e "Usage:\n$0 -c /path/to/config\nOR\n$0 -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]" + exit 1 fi -if [[ -z $ROUTEROS_USER ]] || [[ -z $ROUTEROS_HOST ]] || [[ -z $ROUTEROS_SSH_PORT ]] || [[ -z $ROUTEROS_PRIVATE_KEY ]] || [[ -z $DOMAIN ]]; then - echo "Check the config file $CONFIG_FILE or start with params: $0 [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]" +if [[ -z ${ROUTEROS_USER} ]] || [[ -z ${ROUTEROS_HOST} ]] || [[ -z ${ROUTEROS_SSH_PORT} ]] || [[ -z ${ROUTEROS_PRIVATE_KEY} ]] || [[ -z ${DOMAIN} ]]; then + echo "Check the config file ${CONFIG_FILE} or start with params: $0 -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]" echo "Please avoid spaces" exit 1 fi -CERTIFICATE=/etc/letsencrypt/live/$DOMAIN/cert.pem -KEY=/etc/letsencrypt/live/$DOMAIN/privkey.pem +CERTIFICATE=/etc/letsencrypt/live/${DOMAIN}/cert.pem +KEY=/etc/letsencrypt/live/${DOMAIN}/privkey.pem echo "" -echo "Updating certificate for $DOMAIN" -echo " Using certificate $CERTIFICATE" -echo " User private key $KEY" +echo "Updating certificate for ${DOMAIN}" +echo " Using certificate ${CERTIFICATE}" +echo " User private key ${KEY}" #Create alias for RouterOS command -routeros="ssh -i $ROUTEROS_PRIVATE_KEY $ROUTEROS_USER@$ROUTEROS_HOST -p $ROUTEROS_SSH_PORT" +routeros="ssh -o PubkeyAcceptedAlgorithms=${SSH_ACCEPTED_ALGORITHMS:-ssh-dss,ssh-rsa} -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -i ${ROUTEROS_PRIVATE_KEY} ${ROUTEROS_USER}@${ROUTEROS_HOST} -p ${ROUTEROS_SSH_PORT}" + +#Create alias for scp command +scp="scp -q -o PubkeyAcceptedAlgorithms=${SSH_ACCEPTED_ALGORITHMS:-ssh-dss,ssh-rsa} -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -P ${ROUTEROS_SSH_PORT} -i ${ROUTEROS_PRIVATE_KEY}" echo "" echo "Checking connection to RouterOS" @@ -36,7 +59,7 @@ echo "Checking connection to RouterOS" $routeros /system resource print RESULT=$? -if [[ ! $RESULT == 0 ]]; then +if [[ ! ${RESULT} == 0 ]]; then echo -e "\nError in: $routeros" echo "More info: https://wiki.mikrotik.com/wiki/Use_SSH_to_execute_commands_(DSA_key_login)" exit 1 @@ -44,72 +67,79 @@ else echo -e "\nConnection to RouterOS Successful!\n" fi -if [ ! -f $CERTIFICATE ] && [ ! -f $KEY ]; then - echo -e "\nFile(s) not found:\n$CERTIFICATE\n$KEY\n" +if [ ! -f ${CERTIFICATE} ] && [ ! -f ${KEY} ]; then + echo -e "\nFile(s) not found:\n${CERTIFICATE}\n${KEY}\n" echo -e "Please use CertBot Let'sEncrypt:" echo "============================" - echo "certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public-ip-logging-ok" + echo "certbot certonly --preferred-challenges=dns --manual -d ${DOMAIN} --manual-public-ip-logging-ok" echo "or (for wildcard certificate):" - echo "certbot certonly --preferred-challenges=dns --manual -d *.$DOMAIN --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory" + echo "certbot certonly --preferred-challenges=dns --manual -d *.${DOMAIN} --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory" echo "===========================" echo -e "and follow instructions from CertBot\n" exit 1 fi # Set up variables to remove errors -DOMAIN_INSTALLED_CERT_FILE=$DOMAIN.pem_0 -DOMAIN_CERT_FILE=$DOMAIN.pem -DOMAIN_KEY_FILE=$DOMAIN.key +DOMAIN_INSTALLED_CERT_FILE=${DOMAIN}.pem_0 +DOMAIN_CERT_FILE=${DOMAIN}.pem +DOMAIN_KEY_FILE=${DOMAIN}.key # Remove previous certificate -echo "Removing old certificate from installed certificates: $DOMAIN_INSTALLED_CERT_FILE" -$routeros /certificate remove [find name=$DOMAIN_INSTALLED_CERT_FILE] +echo "Removing old certificate from installed certificates: ${DOMAIN_INSTALLED_CERT_FILE}" +$routeros /certificate remove [find name=${DOMAIN_INSTALLED_CERT_FILE}] echo "" echo "Handling new certificate file" # Create Certificate # Delete Certificate file if the file exist on RouterOS -echo " Deleting any old copy of certificate file from disk: $DOMAIN_CERT_FILE" -$routeros /file remove $DOMAIN_CERT_FILE > /dev/null +echo " Deleting any old copy of certificate file from disk: ${DOMAIN_CERT_FILE}" +$routeros /file remove ${DOMAIN_CERT_FILE} > /dev/null # Upload Certificate to RouterOS -echo " Uploading new domain certificate file to router: $CERTIFICATE" -scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$CERTIFICATE" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN_CERT_FILE" +echo " Uploading new domain certificate file to router: ${CERTIFICATE}" +$scp "${CERTIFICATE}" "${ROUTEROS_USER}"@"${ROUTEROS_HOST}":"${DOMAIN_CERT_FILE}" sleep 2 # Import Certificate file echo " Importing new certificate file to router certificates" -$routeros /certificate import file-name=$DOMAIN_CERT_FILE passphrase=\"\" +$routeros /certificate import file-name=${DOMAIN_CERT_FILE} passphrase=\"\" # Delete Certificate file after import -echo " Deleting any new copy of certificate file from disk: $DOMAIN_CERT_FILE" -$routeros /file remove $DOMAIN_CERT_FILE +echo " Deleting any new copy of certificate file from disk: ${DOMAIN_CERT_FILE}" +$routeros /file remove ${DOMAIN_CERT_FILE} echo "" echo "Handling new key file" # Create Key # Delete Certificate file if the file exist on RouterOS -echo " Deleting any old copy of key file from disk: $DOMAIN_KEY_FILE" -$routeros /file remove $DOMAIN_KEY_FILE > /dev/null +echo " Deleting any old copy of key file from disk: ${DOMAIN_KEY_FILE}" +$routeros /file remove ${DOMAIN_KEY_FILE} > /dev/null # Upload Key to RouterOS -echo " Uploading new domain key file to router: $KEY" -scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$KEY" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN_KEY_FILE" +echo " Uploading new domain key file to router: ${KEY}" +$scp "${KEY}" "${ROUTEROS_USER}"@"${ROUTEROS_HOST}":"${DOMAIN_KEY_FILE}" sleep 2 # Import Key file echo " Importing new key file to router certificates" -$routeros /certificate import file-name=$DOMAIN_KEY_FILE passphrase=\"\" +$routeros /certificate import file-name=${DOMAIN_KEY_FILE} passphrase=\"\" # Delete Certificate file after import -echo " Deleting any new copy of key file from disk: $DOMAIN_KEY_FILE" -$routeros /file remove $DOMAIN_KEY_FILE +echo " Deleting any new copy of key file from disk: ${DOMAIN_KEY_FILE}" +$routeros /file remove ${DOMAIN_KEY_FILE} echo "" -# Setup Certificate to SSTP Server -echo "Updating SSTP Server to use $DOMAIN_INSTALLED_CERT_FILE" -$routeros /interface sstp-server server set certificate=$DOMAIN_INSTALLED_CERT_FILE +# Setup Certificate to SSTP Service +if [[ "${SETUP_SERVICES[*]:-SSTP}" =~ "SSTP" ]]; then + echo "Updating SSTP Server to use ${DOMAIN_INSTALLED_CERT_FILE}" + $routeros /interface sstp-server server set certificate=${DOMAIN_INSTALLED_CERT_FILE} +fi -# Setup Certificate to SSL -echo "Updating HTTPS Server to use $DOMAIN_INSTALLED_CERT_FILE" -$routeros /ip service set www-ssl certificate=$DOMAIN_INSTALLED_CERT_FILE +# Setup Certificate to WWW Service +if [[ "${SETUP_SERVICES[*]:-WWW}" =~ "WWW" ]]; then + echo "Updating HTTPS Server to use ${DOMAIN_INSTALLED_CERT_FILE}" + $routeros /ip service set www-ssl certificate=${DOMAIN_INSTALLED_CERT_FILE} +fi -echo "Updating API SSL Server to use $DOMAIN_INSTALLED_CERT_FILE" -$routeros /ip service set api-ssl certificate=$DOMAIN_INSTALLED_CERT_FILE +# Setup Certificat to API Service +if [[ "${SETUP_SERVICES[*]:-API}" =~ "API" ]]; then + echo "Updating API SSL Server to use ${DOMAIN_INSTALLED_CERT_FILE}" + $routeros /ip service set api-ssl certificate=${DOMAIN_INSTALLED_CERT_FILE} +fi exit 0 From 90636e8424a2a2e5515444669c6e177cbde95c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0uvada?= Date: Sun, 9 Oct 2022 17:08:32 +0200 Subject: [PATCH 07/12] Update sample configuration --- letsencrypt-routeros.settings | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/letsencrypt-routeros.settings b/letsencrypt-routeros.settings index 5bb344e..d92b889 100644 --- a/letsencrypt-routeros.settings +++ b/letsencrypt-routeros.settings @@ -7,3 +7,10 @@ ROUTEROS_HOST=10.0.254.254 ROUTEROS_SSH_PORT=22 ROUTEROS_PRIVATE_KEY=/opt/letsencrypt-routeros/id_rsa DOMAIN=vpnserver.yourdomain.com +## Uncomment this to specify array of services that will be setup +## If not specified certificate is installed to (SSTP WWW API) +#SETUP_SERVICES=(WWW API) +## Uncomment this to disable StrictHostKeyChecking (default yes) +#SSH_STRICT_KEY_CHECKING=no +## Uncomment this to specify PubkeyAcceptedAlgorithms (default ssh-rsa,ssh-dsa) +#SSH_ACCEPTED_ALGORITHMS=ssh-dsa From e4200c8148a61fd32427a2bb6ca5a68b04bd816b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0uvada?= Date: Sun, 9 Oct 2022 17:18:54 +0200 Subject: [PATCH 08/12] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 88fdf66..5c8de55 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,9 @@ vim /opt/letsencrypt-routeros/letsencrypt-routeros.settings | ROUTEROS_SSH_PORT | 22 | RouterOS\Mikrotik PORT | | ROUTEROS_PRIVATE_KEY | /opt/letsencrypt-routeros/id_rsa | Private RSA Key to connecto to RouterOS | | DOMAIN | mydomain.com | Use main domain for wildcard certificate or subdomain for subdomain certificate | +| SETUP_SERVICES | (SSTP WWW API) | Array of services for which certificate will be installed | +| SSH_STRICT_KEY_CHECKING | yes | Allows to override SSH option StrictHostKeyChecking | +| SSH_ACCEPTED_ALGORITHMS | ssh-rsa,ssh-dsa | Allows to override SSH option PubkeyAcceptedAlgorithms | Change permissions: @@ -98,12 +101,12 @@ certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public- ### Usage of the script *To use settings from the settings file:* ```sh -./opt/letsencrypt-routeros/letsencrypt-routeros.sh +/opt/letsencrypt-routeros/letsencrypt-routeros.sh -c letsencrypt-routeros.settings ``` *To use script without settings file:* ```sh -./opt/letsencrypt-routeros/letsencrypt-routeros.sh [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain] +/opt/letsencrypt-routeros/letsencrypt-routeros.sh -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain] ``` *To use script with CertBot hooks for wildcard domain:* ```sh From 086ad134b112eb49f0cab25641cff110fa4160a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0uvada?= Date: Sun, 9 Oct 2022 18:50:49 +0200 Subject: [PATCH 09/12] Update README --- README.md | 1 - letsencrypt-routeros.settings | 2 -- letsencrypt-routeros.sh | 4 ++-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5c8de55..157971b 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,6 @@ vim /opt/letsencrypt-routeros/letsencrypt-routeros.settings | DOMAIN | mydomain.com | Use main domain for wildcard certificate or subdomain for subdomain certificate | | SETUP_SERVICES | (SSTP WWW API) | Array of services for which certificate will be installed | | SSH_STRICT_KEY_CHECKING | yes | Allows to override SSH option StrictHostKeyChecking | -| SSH_ACCEPTED_ALGORITHMS | ssh-rsa,ssh-dsa | Allows to override SSH option PubkeyAcceptedAlgorithms | Change permissions: diff --git a/letsencrypt-routeros.settings b/letsencrypt-routeros.settings index d92b889..429b95d 100644 --- a/letsencrypt-routeros.settings +++ b/letsencrypt-routeros.settings @@ -12,5 +12,3 @@ DOMAIN=vpnserver.yourdomain.com #SETUP_SERVICES=(WWW API) ## Uncomment this to disable StrictHostKeyChecking (default yes) #SSH_STRICT_KEY_CHECKING=no -## Uncomment this to specify PubkeyAcceptedAlgorithms (default ssh-rsa,ssh-dsa) -#SSH_ACCEPTED_ALGORITHMS=ssh-dsa diff --git a/letsencrypt-routeros.sh b/letsencrypt-routeros.sh index 2f22e81..7fcdc79 100755 --- a/letsencrypt-routeros.sh +++ b/letsencrypt-routeros.sh @@ -47,10 +47,10 @@ echo " Using certificate ${CERTIFICATE}" echo " User private key ${KEY}" #Create alias for RouterOS command -routeros="ssh -o PubkeyAcceptedAlgorithms=${SSH_ACCEPTED_ALGORITHMS:-ssh-dss,ssh-rsa} -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -i ${ROUTEROS_PRIVATE_KEY} ${ROUTEROS_USER}@${ROUTEROS_HOST} -p ${ROUTEROS_SSH_PORT}" +routeros="ssh -o PubkeyAcceptedKeyTypes=+ssh-dss -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -i ${ROUTEROS_PRIVATE_KEY} ${ROUTEROS_USER}@${ROUTEROS_HOST} -p ${ROUTEROS_SSH_PORT}" #Create alias for scp command -scp="scp -q -o PubkeyAcceptedAlgorithms=${SSH_ACCEPTED_ALGORITHMS:-ssh-dss,ssh-rsa} -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -P ${ROUTEROS_SSH_PORT} -i ${ROUTEROS_PRIVATE_KEY}" +scp="scp -q -o PubkeyAcceptedKeyTypes=+ssh-dss -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -P ${ROUTEROS_SSH_PORT} -i ${ROUTEROS_PRIVATE_KEY}" echo "" echo "Checking connection to RouterOS" From 79c9b9f6940f468eadda9a9cc2f87bb883976375 Mon Sep 17 00:00:00 2001 From: Miroslav Suvada Date: Fri, 13 Oct 2023 18:06:40 +0200 Subject: [PATCH 10/12] Remove unnecessary curly braces --- letsencrypt-routeros.sh | 140 ++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 69 deletions(-) diff --git a/letsencrypt-routeros.sh b/letsencrypt-routeros.sh index 7fcdc79..790403e 100755 --- a/letsencrypt-routeros.sh +++ b/letsencrypt-routeros.sh @@ -1,56 +1,58 @@ #!/bin/bash -#set -x while getopts 'u:h:p:k:d:c:' OPTION; do case "$OPTION" in - u) - ROUTEROS_USER=${OPTARG} - ;; - h) - ROUTEROS_HOST=${OPTARG} - ;; - p) - ROUTEROS_SSH_PORT=${OPTARG} - ;; - k) - ROUTEROS_PRIVATE_KEY=${OPTARG} - ;; - d) - DOMAIN=${OPTARG} - ;; - c) - CONFIG=${OPTARG} - ;; - esac + u) + ROUTEROS_USER=$OPTARG + ;; + h) + ROUTEROS_HOST=$OPTARG + ;; + p) + ROUTEROS_SSH_PORT=$OPTARG + ;; + k) + ROUTEROS_PRIVATE_KEY=$OPTARG + ;; + d) + DOMAIN=$OPTARG + ;; + c) + CONFIG=$OPTARG + ;; + *) + echo "Unknown option '$OPTION'" + ;; + esac done -shift "$(($OPTIND -1))" +shift "$((OPTIND - 1))" -if [[ -n ${CONFIG} ]]; then - source $CONFIG -elif [[ -z ${ROUTEROS_USER} ]] || [[ -z ${ROUTEROS_HOST} ]] || [[ -z ${ROUTEROS_SSH_PORT} ]] || [[ -z ${ROUTEROS_PRIVATE_KEY} ]] || [[ -z ${DOMAIN} ]]; then - echo -e "Usage:\n$0 -c /path/to/config\nOR\n$0 -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]" +if [[ -n $CONFIG ]]; then + source "$CONFIG" +elif [[ -z $ROUTEROS_USER ]] || [[ -z $ROUTEROS_HOST ]] || [[ -z $ROUTEROS_SSH_PORT ]] || [[ -z $ROUTEROS_PRIVATE_KEY ]] || [[ -z $DOMAIN ]]; then + echo -e "Usage:\n$0 -c /path/to/config\nOR\n$0 -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]" exit 1 fi -if [[ -z ${ROUTEROS_USER} ]] || [[ -z ${ROUTEROS_HOST} ]] || [[ -z ${ROUTEROS_SSH_PORT} ]] || [[ -z ${ROUTEROS_PRIVATE_KEY} ]] || [[ -z ${DOMAIN} ]]; then - echo "Check the config file ${CONFIG_FILE} or start with params: $0 -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]" - echo "Please avoid spaces" - exit 1 +if [[ -z $ROUTEROS_USER ]] || [[ -z $ROUTEROS_HOST ]] || [[ -z $ROUTEROS_SSH_PORT ]] || [[ -z $ROUTEROS_PRIVATE_KEY ]] || [[ -z $DOMAIN ]]; then + echo "Check the config file $CONFIG_FILE or start with params: $0 -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]" + echo "Please avoid spaces" + exit 1 fi CERTIFICATE=/etc/letsencrypt/live/${DOMAIN}/cert.pem KEY=/etc/letsencrypt/live/${DOMAIN}/privkey.pem echo "" -echo "Updating certificate for ${DOMAIN}" -echo " Using certificate ${CERTIFICATE}" -echo " User private key ${KEY}" +echo "Updating certificate for $DOMAIN" +echo " Using certificate $CERTIFICATE" +echo " User private key $KEY" #Create alias for RouterOS command -routeros="ssh -o PubkeyAcceptedKeyTypes=+ssh-dss -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -i ${ROUTEROS_PRIVATE_KEY} ${ROUTEROS_USER}@${ROUTEROS_HOST} -p ${ROUTEROS_SSH_PORT}" +routeros="ssh -o PubkeyAcceptedKeyTypes=+ssh-dss -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -i $ROUTEROS_PRIVATE_KEY ${ROUTEROS_USER}@${ROUTEROS_HOST} -p $ROUTEROS_SSH_PORT" #Create alias for scp command -scp="scp -q -o PubkeyAcceptedKeyTypes=+ssh-dss -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -P ${ROUTEROS_SSH_PORT} -i ${ROUTEROS_PRIVATE_KEY}" +scp="scp -q -o PubkeyAcceptedKeyTypes=+ssh-dss -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -P $ROUTEROS_SSH_PORT -i $ROUTEROS_PRIVATE_KEY" echo "" echo "Checking connection to RouterOS" @@ -60,23 +62,23 @@ $routeros /system resource print RESULT=$? if [[ ! ${RESULT} == 0 ]]; then - echo -e "\nError in: $routeros" - echo "More info: https://wiki.mikrotik.com/wiki/Use_SSH_to_execute_commands_(DSA_key_login)" - exit 1 + echo -e "\nError in: $routeros" + echo "More info: https://wiki.mikrotik.com/wiki/Use_SSH_to_execute_commands_(DSA_key_login)" + exit 1 else - echo -e "\nConnection to RouterOS Successful!\n" + echo -e "\nConnection to RouterOS Successful!\n" fi -if [ ! -f ${CERTIFICATE} ] && [ ! -f ${KEY} ]; then - echo -e "\nFile(s) not found:\n${CERTIFICATE}\n${KEY}\n" - echo -e "Please use CertBot Let'sEncrypt:" - echo "============================" - echo "certbot certonly --preferred-challenges=dns --manual -d ${DOMAIN} --manual-public-ip-logging-ok" - echo "or (for wildcard certificate):" - echo "certbot certonly --preferred-challenges=dns --manual -d *.${DOMAIN} --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory" - echo "===========================" - echo -e "and follow instructions from CertBot\n" - exit 1 +if [ ! -f "$CERTIFICATE" ] && [ ! -f "$KEY" ]; then + echo -e "\nFile(s) not found:\n${CERTIFICATE}\n${KEY}\n" + echo -e "Please use CertBot Let'sEncrypt:" + echo "============================" + echo "certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public-ip-logging-ok" + echo "or (for wildcard certificate):" + echo "certbot certonly --preferred-challenges=dns --manual -d *.$DOMAIN --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory" + echo "===========================" + echo -e "and follow instructions from CertBot\n" + exit 1 fi # Set up variables to remove errors @@ -85,61 +87,61 @@ DOMAIN_CERT_FILE=${DOMAIN}.pem DOMAIN_KEY_FILE=${DOMAIN}.key # Remove previous certificate -echo "Removing old certificate from installed certificates: ${DOMAIN_INSTALLED_CERT_FILE}" -$routeros /certificate remove [find name=${DOMAIN_INSTALLED_CERT_FILE}] +echo "Removing old certificate from installed certificates: $DOMAIN_INSTALLED_CERT_FILE" +$routeros /certificate remove [find name="$DOMAIN_INSTALLED_CERT_FILE"] echo "" echo "Handling new certificate file" # Create Certificate # Delete Certificate file if the file exist on RouterOS -echo " Deleting any old copy of certificate file from disk: ${DOMAIN_CERT_FILE}" -$routeros /file remove ${DOMAIN_CERT_FILE} > /dev/null +echo " Deleting any old copy of certificate file from disk: $DOMAIN_CERT_FILE" +$routeros /file remove "$DOMAIN_CERT_FILE" >/dev/null # Upload Certificate to RouterOS -echo " Uploading new domain certificate file to router: ${CERTIFICATE}" -$scp "${CERTIFICATE}" "${ROUTEROS_USER}"@"${ROUTEROS_HOST}":"${DOMAIN_CERT_FILE}" +echo " Uploading new domain certificate file to router: $CERTIFICATE" +$scp "$CERTIFICATE" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN_CERT_FILE" sleep 2 # Import Certificate file echo " Importing new certificate file to router certificates" -$routeros /certificate import file-name=${DOMAIN_CERT_FILE} passphrase=\"\" +$routeros /certificate import file-name="$DOMAIN_CERT_FILE" passphrase=\"\" # Delete Certificate file after import -echo " Deleting any new copy of certificate file from disk: ${DOMAIN_CERT_FILE}" -$routeros /file remove ${DOMAIN_CERT_FILE} +echo " Deleting any new copy of certificate file from disk: $DOMAIN_CERT_FILE" +$routeros /file remove "$DOMAIN_CERT_FILE" echo "" echo "Handling new key file" # Create Key # Delete Certificate file if the file exist on RouterOS echo " Deleting any old copy of key file from disk: ${DOMAIN_KEY_FILE}" -$routeros /file remove ${DOMAIN_KEY_FILE} > /dev/null +$routeros /file remove "$DOMAIN_KEY_FILE" >/dev/null # Upload Key to RouterOS -echo " Uploading new domain key file to router: ${KEY}" -$scp "${KEY}" "${ROUTEROS_USER}"@"${ROUTEROS_HOST}":"${DOMAIN_KEY_FILE}" +echo " Uploading new domain key file to router: $KEY" +$scp "$KEY" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN_KEY_FILE" sleep 2 # Import Key file echo " Importing new key file to router certificates" -$routeros /certificate import file-name=${DOMAIN_KEY_FILE} passphrase=\"\" +$routeros /certificate import file-name="$DOMAIN_KEY_FILE" passphrase=\"\" # Delete Certificate file after import -echo " Deleting any new copy of key file from disk: ${DOMAIN_KEY_FILE}" -$routeros /file remove ${DOMAIN_KEY_FILE} +echo " Deleting any new copy of key file from disk: $DOMAIN_KEY_FILE" +$routeros /file remove "$DOMAIN_KEY_FILE" echo "" # Setup Certificate to SSTP Service if [[ "${SETUP_SERVICES[*]:-SSTP}" =~ "SSTP" ]]; then - echo "Updating SSTP Server to use ${DOMAIN_INSTALLED_CERT_FILE}" - $routeros /interface sstp-server server set certificate=${DOMAIN_INSTALLED_CERT_FILE} + echo "Updating SSTP Server to use $DOMAIN_INSTALLED_CERT_FILE" + $routeros /interface sstp-server server set certificate="$DOMAIN_INSTALLED_CERT_FILE" fi # Setup Certificate to WWW Service if [[ "${SETUP_SERVICES[*]:-WWW}" =~ "WWW" ]]; then - echo "Updating HTTPS Server to use ${DOMAIN_INSTALLED_CERT_FILE}" - $routeros /ip service set www-ssl certificate=${DOMAIN_INSTALLED_CERT_FILE} + echo "Updating HTTPS Server to use $DOMAIN_INSTALLED_CERT_FILE" + $routeros /ip service set www-ssl certificate="$DOMAIN_INSTALLED_CERT_FILE" fi # Setup Certificat to API Service if [[ "${SETUP_SERVICES[*]:-API}" =~ "API" ]]; then - echo "Updating API SSL Server to use ${DOMAIN_INSTALLED_CERT_FILE}" - $routeros /ip service set api-ssl certificate=${DOMAIN_INSTALLED_CERT_FILE} + echo "Updating API SSL Server to use $DOMAIN_INSTALLED_CERT_FILE" + $routeros /ip service set api-ssl certificate="$DOMAIN_INSTALLED_CERT_FILE" fi exit 0 From da04e9c928342a0a27ad8ec97d4ef557e5e120a8 Mon Sep 17 00:00:00 2001 From: Miroslav Suvada Date: Fri, 13 Oct 2023 18:20:31 +0200 Subject: [PATCH 11/12] Replace -c option with -f --- letsencrypt-routeros.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/letsencrypt-routeros.sh b/letsencrypt-routeros.sh index 790403e..21d732d 100755 --- a/letsencrypt-routeros.sh +++ b/letsencrypt-routeros.sh @@ -1,6 +1,6 @@ #!/bin/bash -while getopts 'u:h:p:k:d:c:' OPTION; do +while getopts 'u:h:p:k:d:f:' OPTION; do case "$OPTION" in u) ROUTEROS_USER=$OPTARG @@ -17,7 +17,7 @@ while getopts 'u:h:p:k:d:c:' OPTION; do d) DOMAIN=$OPTARG ;; - c) + f) CONFIG=$OPTARG ;; *) @@ -138,7 +138,7 @@ if [[ "${SETUP_SERVICES[*]:-WWW}" =~ "WWW" ]]; then $routeros /ip service set www-ssl certificate="$DOMAIN_INSTALLED_CERT_FILE" fi -# Setup Certificat to API Service +# Setup Certificate to API Service if [[ "${SETUP_SERVICES[*]:-API}" =~ "API" ]]; then echo "Updating API SSL Server to use $DOMAIN_INSTALLED_CERT_FILE" $routeros /ip service set api-ssl certificate="$DOMAIN_INSTALLED_CERT_FILE" From efd4c5f2835a257e575648f5dd98556e326bc488 Mon Sep 17 00:00:00 2001 From: Miroslav Suvada Date: Fri, 13 Oct 2023 18:25:06 +0200 Subject: [PATCH 12/12] Fix small typos in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 157971b..a79e817 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ vim /opt/letsencrypt-routeros/letsencrypt-routeros.settings | ROUTEROS_USER | admin | user with admin rights to connect to RouterOS | | ROUTEROS_HOST | 10.0.254.254 | RouterOS\Mikrotik IP | | ROUTEROS_SSH_PORT | 22 | RouterOS\Mikrotik PORT | -| ROUTEROS_PRIVATE_KEY | /opt/letsencrypt-routeros/id_rsa | Private RSA Key to connecto to RouterOS | +| ROUTEROS_PRIVATE_KEY | /opt/letsencrypt-routeros/id_rsa | Private RSA Key to connect to RouterOS | | DOMAIN | mydomain.com | Use main domain for wildcard certificate or subdomain for subdomain certificate | | SETUP_SERVICES | (SSTP WWW API) | Array of services for which certificate will be installed | | SSH_STRICT_KEY_CHECKING | yes | Allows to override SSH option StrictHostKeyChecking | @@ -117,7 +117,7 @@ certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public- ``` --- -### Licence MIT +### License MIT Copyright 2018 Konstantin Gimpel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: