From 413a91646c03b0cd4ab6dace1bdabe78d702a710 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Sat, 16 Nov 2024 19:15:39 +0100 Subject: [PATCH 1/6] Create truenas_ws.sh --- deploy/truenas_ws.sh | 317 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 deploy/truenas_ws.sh diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh new file mode 100644 index 0000000000..b5ba51ab7f --- /dev/null +++ b/deploy/truenas_ws.sh @@ -0,0 +1,317 @@ +#!/usr/bin/env bash + +# TrueNAS deploy script for SCALE/CORE using websocket +# It is recommend to use a wildcard certificate +# +# Websocket Documentation: https://www.truenas.com/docs/api/scale_websocket_api.html +# +# Tested with TrueNAS Scale - Electric Eel 24.10 +# Changes certificate in the following services: +# - Web UI +# - FTP +# - iX Apps +# +# The following environment variables must be set: +# ------------------------------------------------ +# +# # API KEY +# # Use the folowing URL to create a new API token: /ui/apikeys +# export DEPLOY_TRUENAS_APIKEY=" Date: Sun, 24 Nov 2024 14:59:51 +0100 Subject: [PATCH 2/6] Update truenas_ws.sh (shfmt and shellcheck) --- deploy/truenas_ws.sh | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index b5ba51ab7f..4b3a5c727e 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -51,7 +51,7 @@ _ws_call() { _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1") fi _debug "_ws_response" "$_ws_response" - printf "%s" $_ws_response + printf "%s" "$_ws_response" return 0 } @@ -99,7 +99,7 @@ _ws_get_job_result() { then _ws_result="$(printf "%s" "$_ws_response" | jq '.[]."result"')" _debug "_ws_result" "$_ws_result" - printf "%s" $_ws_result + printf "%s" "$_ws_result" _ws_error="$(printf "%s" "$_ws_response" | jq '.[]."error"')" if [ "$_ws_error" != "null" ] then @@ -175,7 +175,7 @@ truenas_ws_deploy() { then _err "Error calling system.ready:" _err "$_ws_response" - exit $_ws_re + exit $_ws_ret fi if [ "$_ws_response" != "TRUE" ] @@ -196,7 +196,7 @@ truenas_ws_deploy() { _truenas_version=$(printf "%s" "$_ws_response" | jq -r '."version"' | cut -d '-' -f 3) _info "TrueNAS system: $_truenas_system" _info "TrueNAS version: $_truenas_version" - if [ "$_truenas_system" != "SCALE" ] && ["$_truenas_system" != "CORE" ] + if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ] then _err "Cannot gather TrueNAS system. Nor CORE oder SCALE detected." exit 10 @@ -210,7 +210,6 @@ truenas_ws_deploy() { _ui_certificate_name=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."name"') _info "Current WebUI certificate ID: $_ui_certificate_id" _info "Current WebUI certificate name: $_ui_certificate_name" - _info "WebUI redirect to https: $_ui_http_redirect" ########## Upload new certificate @@ -225,9 +224,10 @@ truenas_ws_deploy() { exit 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") - if [ $? -gt 0 ] + _ws_ret=$? + if [ $_ws_ret -gt 0 ] then - exit $? + exit $_ws_ret fi _debug "_ws_result" "$_ws_result" _new_certid=$(printf "%s" "$_ws_result" | jq -r '."id"') @@ -251,11 +251,11 @@ truenas_ws_deploy() { then _info "Replace app certificates..." _ws_response=$(_ws_call "app.query") - for _app_name in $(printf "%s" $_ws_response | jq -r '.[]."name"') + for _app_name in $(printf "%s" "$_ws_response" | jq -r '.[]."name"') do _info "Checking app $_app_name..." _ws_response=$(_ws_call "app.config" "$_app_name") - if [ "$(printf "%s" $_ws_response | jq -r '."network" | has("certificate_id")')" = "true" ] + if [ "$(printf "%s" "$_ws_response" | jq -r '."network" | has("certificate_id")')" = "true" ] then _info "App has certificate option, setup new certificate..." _info "App will be redeployed after updating the certificate." @@ -267,9 +267,10 @@ truenas_ws_deploy() { exit 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") - if [ $? -gt 0 ] + _ws_ret=$? + if [ $_ws_ret -gt 0 ] then - exit $? + exit $_ws_ret fi _debug "_ws_result" "$_ws_result" _info "App certificate replaced." @@ -305,10 +306,11 @@ truenas_ws_deploy() { _err "No JobID returned from websocket method." exit 3 fi - _ws_result=$(_ws_get_job_result $_ws_jobid) - if [ $? -gt 0 ] + _ws_result=$(_ws_get_job_result "$_ws_jobid") + _ws_ret=$? + if [ $_ws_ret -gt 0 ] then - exit $? + exit $_ws_ret fi From f2a311bb8194cff518978545da619c439b2f1621 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Mon, 25 Nov 2024 14:44:52 +0100 Subject: [PATCH 3/6] Update truenas_ws.sh (added return instead exit) --- deploy/truenas_ws.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 4b3a5c727e..952cfc42b5 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -161,7 +161,7 @@ truenas_ws_deploy() { if [ -z "$DEPLOY_TRUENAS_APIKEY" ] then _err "TrueNAS API key not found, please set the DEPLOY_TRUENAS_APIKEY environment variable." - exit 1 + return 1 fi _secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "Environment variables: OK" @@ -175,7 +175,7 @@ truenas_ws_deploy() { then _err "Error calling system.ready:" _err "$_ws_response" - exit $_ws_ret + return $_ws_ret fi if [ "$_ws_response" != "TRUE" ] @@ -183,7 +183,7 @@ truenas_ws_deploy() { _err "TrueNAS is not ready." _err "Please check environment variables DEPLOY_TRUENAS_APIKEY, DEPLOY_TRUENAS_HOSTNAME and DEPLOY_TRUENAS_PROTOCOL." _err "Verify API key." - exit 2 + return 2 fi _savedeployconf DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "TrueNAS health: OK" @@ -199,7 +199,7 @@ truenas_ws_deploy() { if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ] then _err "Cannot gather TrueNAS system. Nor CORE oder SCALE detected." - exit 10 + return 10 fi ########## Gather current certificate @@ -221,13 +221,13 @@ truenas_ws_deploy() { if ! _ws_check_jobid "$_ws_jobid" then _err "No JobID returned from websocket method." - exit 3 + return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? if [ $_ws_ret -gt 0 ] then - exit $_ws_ret + return $_ws_ret fi _debug "_ws_result" "$_ws_result" _new_certid=$(printf "%s" "$_ws_result" | jq -r '."id"') @@ -242,7 +242,7 @@ truenas_ws_deploy() { then _err "Cannot set FTP certificate." _debug "_ws_response" "$_ws_response" - exit 4 + return 4 fi ########## ix Apps (SCALE only) @@ -264,13 +264,13 @@ truenas_ws_deploy() { if ! _ws_check_jobid "$_ws_jobid" then _err "No JobID returned from websocket method." - exit 3 + return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? if [ $_ws_ret -gt 0 ] then - exit $_ws_ret + return $_ws_ret fi _debug "_ws_result" "$_ws_result" _info "App certificate replaced." @@ -288,7 +288,7 @@ truenas_ws_deploy() { if [ "$_changed_certid" != "$_new_certid" ] then _err "WebUI certificate change error.." - exit 5 + return 5 else _info "WebUI certificate replaced." fi @@ -304,13 +304,13 @@ truenas_ws_deploy() { if ! _ws_check_jobid "$_ws_jobid" then _err "No JobID returned from websocket method." - exit 3 + return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? if [ $_ws_ret -gt 0 ] then - exit $_ws_ret + return $_ws_ret fi From 91103751736161e43e1806bc485e591661f4591a Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:50:40 +0100 Subject: [PATCH 4/6] Update truenas_ws.sh (fixed shfmt) --- deploy/truenas_ws.sh | 98 ++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 62 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 952cfc42b5..3ee983a3cc 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -38,16 +38,13 @@ _ws_call() { _debug "_ws_call arg1" "$1" _debug "_ws_call arg2" "$2" _debug "_ws_call arg3" "$3" - if [ $# -eq 3 ] - then + if [ $# -eq 3 ]; then _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2" "$3") fi - if [ $# -eq 2 ] - then + if [ $# -eq 2 ]; then _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2") fi - if [ $# -eq 1 ] - then + if [ $# -eq 1 ]; then _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1") fi _debug "_ws_response" "$_ws_response" @@ -69,14 +66,13 @@ _ws_call() { # 1: false _ws_check_jobid() { case "$1" in - [0-9]*) - return 0 - ;; + [0-9]*) + return 0 + ;; esac return 1 } - # Wait for job to finish and return result as JSON # Usage: # _ws_result=$(_ws_get_job_result "$_ws_jobid") @@ -91,18 +87,15 @@ _ws_check_jobid() { # Returns: # n/a _ws_get_job_result() { - while true - do + while true; do sleep 2 _ws_response=$(_ws_call "core.get_jobs" "[[\"id\", \"=\", $1]]") - if [ "$(printf "%s" "$_ws_response" | jq -r '.[]."state"')" != "RUNNING" ] - then + if [ "$(printf "%s" "$_ws_response" | jq -r '.[]."state"')" != "RUNNING" ]; then _ws_result="$(printf "%s" "$_ws_response" | jq '.[]."result"')" _debug "_ws_result" "$_ws_result" printf "%s" "$_ws_result" _ws_error="$(printf "%s" "$_ws_response" | jq '.[]."error"')" - if [ "$_ws_error" != "null" ] - then + if [ "$_ws_error" != "null" ]; then _err "Job $1 failed:" _err "$_ws_error" return 7 @@ -113,9 +106,6 @@ _ws_get_job_result() { return 0 } - - - ######################## ### Public functions ### ######################## @@ -153,33 +143,30 @@ truenas_ws_deploy() { _debug _file_ca "$_file_ca" _debug _file_fullchain "$_file_fullchain" -########## Environment check + ########## Environment check _info "Checking environment variables..." _getdeployconf DEPLOY_TRUENAS_APIKEY # Check API Key - if [ -z "$DEPLOY_TRUENAS_APIKEY" ] - then + if [ -z "$DEPLOY_TRUENAS_APIKEY" ]; then _err "TrueNAS API key not found, please set the DEPLOY_TRUENAS_APIKEY environment variable." return 1 fi _secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "Environment variables: OK" -########## Health check + ########## Health check _info "Checking TrueNAS health..." _ws_response=$(_ws_call "system.ready" | tr '[:lower:]' '[:upper:]') _ws_ret=$? - if [ $_ws_ret -gt 0 ] - then + if [ $_ws_ret -gt 0 ]; then _err "Error calling system.ready:" _err "$_ws_response" return $_ws_ret fi - if [ "$_ws_response" != "TRUE" ] - then + if [ "$_ws_response" != "TRUE" ]; then _err "TrueNAS is not ready." _err "Please check environment variables DEPLOY_TRUENAS_APIKEY, DEPLOY_TRUENAS_HOSTNAME and DEPLOY_TRUENAS_PROTOCOL." _err "Verify API key." @@ -188,7 +175,7 @@ truenas_ws_deploy() { _savedeployconf DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "TrueNAS health: OK" -########## System info + ########## System info _info "Gather system info..." _ws_response=$(_ws_call "system.info") @@ -196,82 +183,73 @@ truenas_ws_deploy() { _truenas_version=$(printf "%s" "$_ws_response" | jq -r '."version"' | cut -d '-' -f 3) _info "TrueNAS system: $_truenas_system" _info "TrueNAS version: $_truenas_version" - if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ] - then + if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ]; then _err "Cannot gather TrueNAS system. Nor CORE oder SCALE detected." return 10 fi -########## Gather current certificate + ########## Gather current certificate _info "Gather current WebUI certificate..." _ws_response="$(_ws_call "system.general.config")" _ui_certificate_id=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."id"') - _ui_certificate_name=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."name"') + _ui_certificate_name=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."name"') _info "Current WebUI certificate ID: $_ui_certificate_id" _info "Current WebUI certificate name: $_ui_certificate_name" -########## Upload new certificate + ########## Upload new certificate _info "Upload new certificate..." _certname="acme_$(_utc_date | tr -d '\-\:' | tr ' ' '_')" _debug _certname "$_certname" _ws_jobid=$(_ws_call "certificate.create" "{\"name\": \"${_certname}\", \"create_type\": \"CERTIFICATE_CREATE_IMPORTED\", \"certificate\": \"$(_json_encode <"$_file_fullchain")\", \"privatekey\": \"$(_json_encode <"$_file_key")\", \"passphrase\": \"\"}") _debug "_ws_jobid" "$_ws_jobid" - if ! _ws_check_jobid "$_ws_jobid" - then + if ! _ws_check_jobid "$_ws_jobid"; then _err "No JobID returned from websocket method." return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? - if [ $_ws_ret -gt 0 ] - then + if [ $_ws_ret -gt 0 ]; then return $_ws_ret fi _debug "_ws_result" "$_ws_result" _new_certid=$(printf "%s" "$_ws_result" | jq -r '."id"') _info "New certificate ID: $_new_certid" -########## FTP + ########## FTP _info "Replace FTP certificate..." _ws_response=$(_ws_call "ftp.update" "{\"ssltls_certificate\": $_new_certid}") _ftp_certid=$(printf "%s" "$_ws_response" | jq -r '."ssltls_certificate"') - if [ "$_ftp_certid" != "$_new_certid" ] - then + if [ "$_ftp_certid" != "$_new_certid" ]; then _err "Cannot set FTP certificate." _debug "_ws_response" "$_ws_response" return 4 fi -########## ix Apps (SCALE only) + ########## ix Apps (SCALE only) - if [ "$_truenas_system" = "SCALE" ] - then + if [ "$_truenas_system" = "SCALE" ]; then _info "Replace app certificates..." _ws_response=$(_ws_call "app.query") - for _app_name in $(printf "%s" "$_ws_response" | jq -r '.[]."name"') - do + for _app_name in $(printf "%s" "$_ws_response" | jq -r '.[]."name"'); do _info "Checking app $_app_name..." _ws_response=$(_ws_call "app.config" "$_app_name") - if [ "$(printf "%s" "$_ws_response" | jq -r '."network" | has("certificate_id")')" = "true" ] - then + if [ "$(printf "%s" "$_ws_response" | jq -r '."network" | has("certificate_id")')" = "true" ]; then _info "App has certificate option, setup new certificate..." _info "App will be redeployed after updating the certificate." _ws_jobid=$(_ws_call "app.update" "$_app_name" "{\"values\": {\"network\": {\"certificate_id\": $_new_certid}}}") _debug "_ws_jobid" "$_ws_jobid" - if ! _ws_check_jobid "$_ws_jobid" - then + if ! _ws_check_jobid "$_ws_jobid"; then _err "No JobID returned from websocket method." return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? - if [ $_ws_ret -gt 0 ] - then - return $_ws_ret - fi + if [ $_ws_ret -gt 0 ]; then + return $_ws_ret + fi _debug "_ws_result" "$_ws_result" _info "App certificate replaced." else @@ -280,13 +258,12 @@ truenas_ws_deploy() { done fi -########## WebUI + ########## WebUI _info "Replace WebUI certificate..." _ws_response=$(_ws_call "system.general.update" "{\"ui_certificate\": $_new_certid}") _changed_certid=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."id"') - if [ "$_changed_certid" != "$_new_certid" ] - then + if [ "$_changed_certid" != "$_new_certid" ]; then _err "WebUI certificate change error.." return 5 else @@ -297,23 +274,20 @@ truenas_ws_deploy() { _info "Waiting for UI restart..." sleep 6 -########## Certificates + ########## Certificates _info "Deleting old certificate..." _ws_jobid=$(_ws_call "certificate.delete" "$_ui_certificate_id") - if ! _ws_check_jobid "$_ws_jobid" - then + if ! _ws_check_jobid "$_ws_jobid"; then _err "No JobID returned from websocket method." return 3 fi _ws_result=$(_ws_get_job_result "$_ws_jobid") _ws_ret=$? - if [ $_ws_ret -gt 0 ] - then + if [ $_ws_ret -gt 0 ]; then return $_ws_ret fi - _info "Have a nice day...bye!" } From 44240339d9856568d418d41f89556495cb651be2 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Mon, 25 Nov 2024 21:13:43 +0100 Subject: [PATCH 5/6] Update truenas_ws.sh (Interpreter changed from bash to sh) --- deploy/truenas_ws.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 3ee983a3cc..7292987bec 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh # TrueNAS deploy script for SCALE/CORE using websocket # It is recommend to use a wildcard certificate From ebaf4c9c01bd590003bc91dec4ca05e88c091cb7 Mon Sep 17 00:00:00 2001 From: Attackwave <51136146+Attackwave@users.noreply.github.com> Date: Mon, 25 Nov 2024 21:23:59 +0100 Subject: [PATCH 6/6] Update truenas_ws.sh (Output new certificate name) --- deploy/truenas_ws.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 7292987bec..940cde2e20 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -201,6 +201,7 @@ truenas_ws_deploy() { _info "Upload new certificate..." _certname="acme_$(_utc_date | tr -d '\-\:' | tr ' ' '_')" + _info "New WebUI certificate name: $_certname" _debug _certname "$_certname" _ws_jobid=$(_ws_call "certificate.create" "{\"name\": \"${_certname}\", \"create_type\": \"CERTIFICATE_CREATE_IMPORTED\", \"certificate\": \"$(_json_encode <"$_file_fullchain")\", \"privatekey\": \"$(_json_encode <"$_file_key")\", \"passphrase\": \"\"}") _debug "_ws_jobid" "$_ws_jobid"