From 1a2c3c575255868584ba7a53fe28bf49bafe6c02 Mon Sep 17 00:00:00 2001 From: Bruno FACHE Date: Thu, 20 Jul 2023 14:04:22 +0200 Subject: [PATCH] feat(ngrok): Adding ngrok feature --- commands/env.cmd | 15 ++++ commands/ngrok.cmd | 63 ++++++++++++++++ commands/ngrok.help | 16 ++++ environments/drupal/init.env | 3 + environments/includes/ngrok.base.yml | 26 +++++++ environments/laravel/init.env | 3 + environments/magento1/init.env | 3 + environments/magento2/init.env | 2 + environments/shopware/init.env | 2 + environments/symfony/init.env | 2 + environments/wordpress/init.env | 3 + utils/env.sh | 1 + utils/ngrok.sh | 109 +++++++++++++++++++++++++++ 13 files changed, 248 insertions(+) create mode 100644 commands/ngrok.cmd create mode 100755 commands/ngrok.help create mode 100644 environments/includes/ngrok.base.yml create mode 100644 utils/ngrok.sh diff --git a/commands/env.cmd b/commands/env.cmd index 7f464e1a..3f82d2a0 100644 --- a/commands/env.cmd +++ b/commands/env.cmd @@ -94,6 +94,21 @@ fi [[ ${WARDEN_VARNISH} -eq 1 ]] \ && appendEnvPartialIfExists "varnish" +if [[ ${WARDEN_NGROK} -eq 1 ]]; then + if [[ ! -f "${WARDEN_ENV_PATH}/.warden/ngrok.yml" ]]; then + fatal "Ngrok is not initialized, please run \"warden ngrok init\" or set WARDEN_NGROK=0 in .env file. File ${WARDEN_ENV_PATH}/.warden/ngrok.yml is missing." + fi + + if [[ ! -f "${WARDEN_ENV_PATH}/.warden/ngrok.caddy" ]]; then + fatal "Ngrok is not initialized, please run \"warden ngrok init\" or set WARDEN_NGROK=0 in .env file. File ${WARDEN_ENV_PATH}/.warden/ngrok.caddy is missing." + fi + + if [[ "$NGROK_AUTHTOKEN" == "" ]]; then + fatal "NGROK_AUTHTOKEN is not defined in the .env, please create an account at https://ngrok.com and set the authtoken in your .env file." + fi + appendEnvPartialIfExists "ngrok" +fi + [[ ${WARDEN_RABBITMQ} -eq 1 ]] \ && appendEnvPartialIfExists "rabbitmq" diff --git a/commands/ngrok.cmd b/commands/ngrok.cmd new file mode 100644 index 00000000..fa716322 --- /dev/null +++ b/commands/ngrok.cmd @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1 + +WARDEN_ENV_PATH="$(locateEnvPath)" || exit $? +loadEnvConfig "${WARDEN_ENV_PATH}" || exit $? +assertDockerRunning + +if [[ ${WARDEN_NGROK:-0} -eq 0 ]]; then + fatal "Ngrok environment is not used (WARDEN_NGROK=0)." +fi + +source "${WARDEN_DIR}/utils/ngrok.sh" + +if (( ${#WARDEN_PARAMS[@]} == 0 )) || [[ "${WARDEN_PARAMS[0]}" == "help" ]]; then + warden ngrok --help || exit $? && exit $? +fi + +## load connection information for the mysql service + +## sub-command execution +case "${WARDEN_PARAMS[0]}" in + init) + if [[ "${WARDEN_PARAMS[1]}" == "" ]]; then + domain="$TRAEFIK_DOMAIN"; + if [[ ${TRAEFIK_SUBDOMAIN} != "" ]]; then + domain="${TRAEFIK_SUBDOMAIN}.${domain}" + fi + mkdir -p ${WARDEN_ENV_PATH}/.warden; #create directoy if does not exists + generateNgrokConfigurationFile "${WARDEN_ENV_PATH}/.warden/ngrok.yml" "$domain" + else + mkdir -p ${WARDEN_ENV_PATH}/.warden; #create directoy if does not exists + generateNgrokConfigurationFile "${WARDEN_ENV_PATH}/.warden/ngrok.yml" ${WARDEN_PARAMS[@]:1} + fi + if [ ! -f ${WARDEN_ENV_PATH}/.warden/ngrok.caddy ]; then + touch ${WARDEN_ENV_PATH}/.warden/ngrok.caddy + $WARDEN_DIR/bin/warden ngrok refresh-config + fi + + warning "You have to run the command \"warden ngrok refresh-config\" after every ngrok container start. It will generate the config for the reverse proxy allowing correct url rewrites and mapping." + + ;; + refresh-config) + if [[ ${CADDY_NGROK_TARGET_SERVICE} == "" ]]; then + if [[ ${WARDEN_VARNISH} == "1" ]]; then + CADDY_NGROK_TARGET_SERVICE=varnish; + else + CADDY_NGROK_TARGET_SERVICE=nginx; + fi + fi + if [[ ${CADDY_NGROK_TARGET_PORT} == "" ]]; then + CADDY_NGROK_TARGET_PORT=80; + fi + mkdir -p ${WARDEN_ENV_PATH}/.warden; #create directoy if does not exists + generateCaddyConfigurationFile "${WARDEN_ENV_PATH}/.warden/ngrok.caddy" "$CADDY_NGROK_TARGET_SERVICE" "$CADDY_NGROK_TARGET_PORT" + displayNgrokUrls + ;; + ls) + displayNgrokUrls + ;; + *) + fatal "The command \"${WARDEN_PARAMS[0]}\" does not exist. Please use --help for usage." + ;; +esac diff --git a/commands/ngrok.help b/commands/ngrok.help new file mode 100755 index 00000000..fc929b0c --- /dev/null +++ b/commands/ngrok.help @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1 + +WARDEN_USAGE=$(cat < + +\033[33mOptions:\033[0m + -h, --help Display this help menu + +\033[33mCommands:\033[0m + init <...> Initialize the ngrok configuration file with the default TRAEFIK_DOMAIN. + refresh-config Regenerate the caddy configuration to match the urls in ngrok. + ls Show the list of ngrok urls +EOF +) diff --git a/environments/drupal/init.env b/environments/drupal/init.env index 6b1756fc..58bd563c 100644 --- a/environments/drupal/init.env +++ b/environments/drupal/init.env @@ -22,3 +22,6 @@ BLACKFIRE_CLIENT_ID= BLACKFIRE_CLIENT_TOKEN= BLACKFIRE_SERVER_ID= BLACKFIRE_SERVER_TOKEN= + +WARDEN_NGROK=0 +NGROK_AUTHTOKEN= \ No newline at end of file diff --git a/environments/includes/ngrok.base.yml b/environments/includes/ngrok.base.yml new file mode 100644 index 00000000..dc47045b --- /dev/null +++ b/environments/includes/ngrok.base.yml @@ -0,0 +1,26 @@ +services: + ngrok: + hostname: "${WARDEN_ENV_NAME}-ngrok" + image: ngrok/ngrok:${NGROK_VERSION:-latest} + environment: + NGROK_AUTHTOKEN: ${NGROK_AUTHTOKEN} + volumes: + - ${WARDEN_ENV_PATH:-.}/.warden/ngrok.yml:/etc/ngrok.yml:ro,cached + command: + - "start" + - "--all" + - "--config" + - "/etc/ngrok.yml" + + + caddy-ngrok: + hostname: "${WARDEN_ENV_NAME}-caddy-ngrok" + image: ${WARDEN_IMAGE_REPOSITORY}/caddy-ngrok:${CADDY_NGROK_VERSION:-latest} + volumes: + - ${WARDEN_ENV_PATH:-.}/.warden/ngrok.caddy:/etc/caddy/Caddyfile:ro,cached + command: + - "caddy" + - "run" + - "--watch" + - "--config" + - "/etc/caddy/Caddyfile" \ No newline at end of file diff --git a/environments/laravel/init.env b/environments/laravel/init.env index 0c97ca6a..4efb335b 100644 --- a/environments/laravel/init.env +++ b/environments/laravel/init.env @@ -31,3 +31,6 @@ REDIS_HOST=redis REDIS_PORT=6379 MAIL_DRIVER=sendmail + +WARDEN_NGROK=0 +NGROK_AUTHTOKEN= diff --git a/environments/magento1/init.env b/environments/magento1/init.env index 5b92aad6..e3971ad7 100644 --- a/environments/magento1/init.env +++ b/environments/magento1/init.env @@ -19,3 +19,6 @@ BLACKFIRE_CLIENT_TOKEN= BLACKFIRE_SERVER_ID= BLACKFIRE_SERVER_TOKEN= +WARDEN_NGROK=0 +NGROK_AUTHTOKEN= + diff --git a/environments/magento2/init.env b/environments/magento2/init.env index f60032c4..aa470209 100644 --- a/environments/magento2/init.env +++ b/environments/magento2/init.env @@ -35,3 +35,5 @@ BLACKFIRE_CLIENT_TOKEN= BLACKFIRE_SERVER_ID= BLACKFIRE_SERVER_TOKEN= +WARDEN_NGROK=0 +NGROK_AUTHTOKEN= \ No newline at end of file diff --git a/environments/shopware/init.env b/environments/shopware/init.env index f0f867b2..3872ec47 100644 --- a/environments/shopware/init.env +++ b/environments/shopware/init.env @@ -15,3 +15,5 @@ RABBITMQ_VERSION=3.8 REDIS_VERSION=5.0 VARNISH_VERSION=6.0 +WARDEN_NGROK=0 +NGROK_AUTHTOKEN= \ No newline at end of file diff --git a/environments/symfony/init.env b/environments/symfony/init.env index f0f867b2..3872ec47 100644 --- a/environments/symfony/init.env +++ b/environments/symfony/init.env @@ -15,3 +15,5 @@ RABBITMQ_VERSION=3.8 REDIS_VERSION=5.0 VARNISH_VERSION=6.0 +WARDEN_NGROK=0 +NGROK_AUTHTOKEN= \ No newline at end of file diff --git a/environments/wordpress/init.env b/environments/wordpress/init.env index cf8c0218..a1a5548b 100644 --- a/environments/wordpress/init.env +++ b/environments/wordpress/init.env @@ -18,3 +18,6 @@ DB_PORT=3306 DB_DATABASE=wordpress DB_USERNAME=wordpress DB_PASSWORD=wordpress + +WARDEN_NGROK=0 +NGROK_AUTHTOKEN= \ No newline at end of file diff --git a/utils/env.sh b/utils/env.sh index 598021d6..ece21b8f 100644 --- a/utils/env.sh +++ b/utils/env.sh @@ -36,6 +36,7 @@ function loadEnvConfig () { eval "$(cat "${WARDEN_ENV_PATH}/.env" | sed 's/\r$//g' | grep "^WARDEN_")" eval "$(cat "${WARDEN_ENV_PATH}/.env" | sed 's/\r$//g' | grep "^TRAEFIK_")" eval "$(cat "${WARDEN_ENV_PATH}/.env" | sed 's/\r$//g' | grep "^PHP_")" + eval "$(cat "${WARDEN_ENV_PATH}/.env" | sed 's/\r$//g' | grep "^NGROK_")" WARDEN_ENV_NAME="${WARDEN_ENV_NAME:-}" WARDEN_ENV_TYPE="${WARDEN_ENV_TYPE:-}" diff --git a/utils/ngrok.sh b/utils/ngrok.sh new file mode 100644 index 00000000..667cbfdc --- /dev/null +++ b/utils/ngrok.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash +[[ ! ${WARDEN_DIR} ]] && >&2 echo -e "\033[31mThis script is not intended to be run directly!\033[0m" && exit 1 + +function replaceDots() { + local input_string="$1" + local output_string="${input_string//./\\.}" + echo "$output_string" +} + +function displayNgrokUrls() { + # Sample text input + local text=$($WARDEN_DIR/bin/warden env logs ngrok | grep name=) + + # Extract name and url using grep and awk + local names=$(echo "$text" | grep -o 'name=[^ ]*' | awk -F'=' '{print $2}') + local urls=$(echo "$text" | grep -o 'url=[^ ]*' | awk -F'=https://' '{print $2}') + + local names=($(echo "${names[@]}" | tr '\n' ' ')) + local urls=($(echo "${urls[@]}" | tr '\n' ' ')) + + # Check if the number of names and urls match + if [[ ${#names[@]} -ne ${#urls[@]} ]]; then + echo "Error: The number of names and URLs doesn't match!" + exit 1 + fi + + # Return only unique urls, latest values in logs are replacing oldest values + declare -A unique_urls + for ((i = 0; i < ${#names[@]}; i++)); do + unique_urls[${names[i]}]=${urls[i]} + done + + for name in "${!unique_urls[@]}"; do + echo "Use url: https://${name} for https://${unique_urls[$name]}" + done +} + +function generateCaddyConfigurationFile() { + local target_file="$1" + local target_service="$2" + local target_port="$3" + + # Sample text input + local text=$($WARDEN_DIR/bin/warden env logs ngrok | grep name=) + + # Extract name and url using grep and awk + local names=$(echo "$text" | grep -o 'name=[^ ]*' | awk -F'=' '{print $2}') + local urls=$(echo "$text" | grep -o 'url=[^ ]*' | awk -F'=https://' '{print $2}') + + local names=($(echo "${names[@]}" | tr '\n' ' ')) + local urls=($(echo "${urls[@]}" | tr '\n' ' ')) + + # Check if the number of names and urls match + if [[ ${#names[@]} -ne ${#urls[@]} ]]; then + echo "Error: The number of names and URLs doesn't match!" + exit 1 + fi + + # Return only unique urls, latest values in logs are replacing oldest values + declare -A unique_urls + for ((i = 0; i < ${#names[@]}; i++)); do + unique_urls[${names[i]}]=${urls[i]} + done + + echo "{ + order replace after encode +} +:2080 { + @get { + method GET + path /* + } + handle @get { + replace {" > $target_file; + + # Loop through the urls to get before and after replacement + for name in "${!unique_urls[@]}"; do + echo " ${name} ${unique_urls[$name]}" >> $target_file; + done + + echo " } + } + + reverse_proxy $target_service:$target_port { + header_up Accept-Encoding identity + header_up X-Forwarded-Proto https" >> $target_file; + + # Loop through the arrays and map the headers to be replaced + for name in "${!unique_urls[@]}"; do + echo " header_up * $(replaceDots ${unique_urls[$name]}) ${name} + header_down * $(replaceDots ${name}) ${unique_urls[$name]}" >> $target_file; + done + + echo " } +}" >> $target_file; +} + +function generateNgrokConfigurationFile() { + local target_file="$1" + local domains="${@:2}" +echo 'version: "2" +log: stdout +tunnels:'> $target_file; +for domain in $domains ; do +echo ' '${domain}': + proto: "http" + addr: "caddy-ngrok:2080"' >> $target_file; +done +} \ No newline at end of file