2023-11-02 22:08:10 +01:00
#!/usr/bin/env bash
#
# this script shares the configured backend for a reserved share token
#
set -o errexit
set -o nounset
set -o pipefail
2024-10-10 17:19:51 +02:00
exec_with_common_opts( ) {
local zrok_cmd = " $* --headless ${ ZROK_VERBOSE :- } ${ ZROK_INSECURE :- } "
echo " INFO: running: zrok ${ zrok_cmd } "
exec zrok ${ zrok_cmd }
}
exec_share_reserved( ) {
2023-11-28 03:12:38 +01:00
local token = " $1 "
local target = " $2 "
shift 2
local opts = " ${ * :- } "
2024-10-10 17:19:51 +02:00
local zrok_cmd = " share reserved ${ token } ${ opts } --override-endpoint ${ target } "
exec_with_common_opts ${ zrok_cmd }
2023-11-28 03:12:38 +01:00
}
2023-11-02 22:08:10 +01:00
if ! command -v jq & >/dev/null; then
echo "ERROR: jq is needed but not installed" >& 2
exit 1
fi
2023-11-28 03:12:38 +01:00
# set HOME to the first colon-sep dir in STATE_DIRECTORY inherited from systemd (/var/lib/zrok-share) or docker (/mnt)
2024-07-08 00:13:22 +02:00
if [ [ -n " ${ STATE_DIRECTORY :- } " ] ] ; then
export HOME = " ${ STATE_DIRECTORY % : * } "
else
echo " WARNING: STATE_DIRECTORY is undefined. Using HOME= ${ HOME } " >& 2
fi
echo " DEBUG: zrok state directory is ${ HOME } /.zrok "
2023-11-02 22:08:10 +01:00
2023-12-11 21:36:19 +01:00
: " ${ ZROK_SHARE_RESERVED : =true } "
echo " DEBUG: ZROK_SHARE_RESERVED= ${ ZROK_SHARE_RESERVED } "
2023-11-02 22:08:10 +01:00
if ( ( $# ) ) ; then
if [ [ -s " $1 " ] ] ; then
2023-11-28 03:12:38 +01:00
echo " INFO: reading share configuration from $1 "
2023-11-02 22:08:10 +01:00
source " $1 "
2023-11-28 03:12:38 +01:00
shift
2023-11-02 22:08:10 +01:00
else
echo " ERROR: ' $1 ' is empty or not readable " >& 2
exit 1
fi
else
# TODO: consider defining a default environment file
# if [[ -s /opt/openziti/etc/zrok.env ]]; then
# source /opt/openziti/etc/zrok.env
# else
# echo "ERROR: need /opt/openziti/etc/zrok.env or filename argument to read share configuration" >&2
# exit 1
# fi
2023-11-28 03:12:38 +01:00
echo "INFO: reading share configuration from environment variables"
2023-11-02 22:08:10 +01:00
fi
2023-11-28 03:12:38 +01:00
[ [ -n " ${ ZROK_TARGET :- } " ] ] || {
echo "ERROR: ZROK_TARGET is not defined." >& 2
exit 1
}
2024-06-11 02:41:21 +02:00
# default mode is 'reserved-public', override modes are reserved-private, temp-public, temp-private.
2024-06-25 21:40:28 +02:00
: " ${ ZROK_FRONTEND_MODE : =reserved-public } "
2023-11-28 03:12:38 +01:00
if [ [ " ${ ZROK_FRONTEND_MODE :- } " = = temp-public ] ] ; then
2024-10-10 17:19:51 +02:00
ZROK_CMD = "share public"
2024-06-07 07:04:48 +02:00
elif [ [ " ${ ZROK_FRONTEND_MODE :- } " = = temp-private ] ] ; then
2024-10-10 17:19:51 +02:00
ZROK_CMD = "share private"
2023-11-28 03:12:38 +01:00
elif [ [ -s ~/.zrok/reserved.json ] ] ; then
ZROK_RESERVED_TOKEN = " $( jq -r '.token' ~/.zrok/reserved.json 2>/dev/null) "
2023-11-02 22:08:10 +01:00
if [ [ -z " ${ ZROK_RESERVED_TOKEN } " || " ${ ZROK_RESERVED_TOKEN } " = = null ] ] ; then
echo " ERROR: invalid reserved.json: ' $( jq -c . ~/.zrok/reserved.json) ' " >& 2
exit 1
else
echo " INFO: zrok backend is already reserved: ${ ZROK_RESERVED_TOKEN } "
2023-12-11 21:36:19 +01:00
ZROK_CMD = " ${ ZROK_RESERVED_TOKEN } ${ ZROK_TARGET } "
if [ [ " ${ ZROK_SHARE_RESERVED } " = = true ] ] ; then
2024-10-10 17:19:51 +02:00
exec_share_reserved ${ ZROK_CMD }
2023-12-11 21:36:19 +01:00
else
echo "INFO: finished reserving zrok backend, continuing without sharing"
exit 0
fi
2023-11-02 22:08:10 +01:00
fi
2024-06-07 07:04:48 +02:00
elif [ [ " ${ ZROK_FRONTEND_MODE :- } " = = reserved-public ] ] ; then
2023-11-02 22:08:10 +01:00
ZROK_CMD = " reserve public --json-output ${ ZROK_VERBOSE :- } "
2024-06-07 07:04:48 +02:00
elif [ [ " ${ ZROK_FRONTEND_MODE :- } " = = reserved-private ] ] ; then
ZROK_CMD = " reserve private --json-output ${ ZROK_VERBOSE :- } "
else
echo " ERROR: invalid value for ZROK_FRONTEND_MODE ' ${ ZROK_FRONTEND_MODE } ' " >& 2
exit 1
2023-11-28 03:12:38 +01:00
fi
[ [ -n " ${ ZROK_BACKEND_MODE :- } " ] ] || {
echo "WARNING: ZROK_BACKEND_MODE was not defined, assuming mode 'proxy'." >& 2
ZROK_BACKEND_MODE = "proxy"
}
case " ${ ZROK_BACKEND_MODE } " in
proxy)
if ! [ [ " ${ ZROK_TARGET } " = ~ ^https?:// ] ] ; then
echo " ERROR: ZROK_TARGET=' ${ ZROK_TARGET } ' is not an HTTP URL " >& 2
exit 1
else
2024-06-07 07:04:48 +02:00
echo " INFO: validated backend mode ' ${ ZROK_BACKEND_MODE } ' and target ' ${ ZROK_TARGET } ' "
2023-11-28 03:12:38 +01:00
fi
; ;
caddy)
if ! [ [ " ${ ZROK_TARGET } " = ~ ^/ ] ] ; then
2024-06-07 07:04:48 +02:00
echo " ERROR: ZROK_TARGET=' ${ ZROK_TARGET } ' is not an absolute filesystem path " >& 2
2023-11-28 03:12:38 +01:00
exit 1
elif ! [ [ -f " ${ ZROK_TARGET } " && -r " ${ ZROK_TARGET } " ] ] ; then
echo " ERROR: ZROK_TARGET=' ${ ZROK_TARGET } ' is not a readable regular file " >& 2
exit 1
else
echo " INFO: validated backend mode ${ ZROK_BACKEND_MODE } and target ${ ZROK_TARGET } "
2023-11-16 02:15:06 +01:00
fi
2023-11-28 03:12:38 +01:00
; ;
web| drive)
if ! [ [ " ${ ZROK_TARGET } " = ~ ^/ ] ] ; then
2024-06-07 07:04:48 +02:00
echo " ERROR: ZROK_TARGET=' ${ ZROK_TARGET } ' is not an absolute filesystem path " >& 2
2023-11-28 03:12:38 +01:00
exit 1
elif ! [ [ -d " ${ ZROK_TARGET } " && -r " ${ ZROK_TARGET } " ] ] ; then
echo " ERROR: ZROK_TARGET=' ${ ZROK_TARGET } ' is not a readable directory " >& 2
exit 1
else
echo " INFO: validated backend mode ${ ZROK_BACKEND_MODE } and target ${ ZROK_TARGET } "
fi
; ;
2024-06-25 21:40:28 +02:00
tcpTunnel| udpTunnel| socks| vpn)
if ! [ [ " ${ ZROK_FRONTEND_MODE } " = ~ -private$ ] ] ; then
echo " ERROR: ZROK_BACKEND_MODE=' ${ ZROK_BACKEND_MODE } ' is a private share backend mode and cannot be used with ZROK_FRONTEND_MODE=' ${ ZROK_FRONTEND_MODE } ' " >& 2
exit 1
else
case " ${ ZROK_BACKEND_MODE } " in
tcpTunnel| udpTunnel)
echo " INFO: ${ ZROK_BACKEND_MODE } backend mode has target ' ${ ZROK_TARGET } ' "
; ;
vpn)
if [ [ -n " ${ ZROK_TARGET } " ] ] ; then
ZROK_SVC_FILE = /etc/systemd/system/zrok-share.service.d/override.conf
if ! grep -qE '^AmbientCapabilities=CAP_NET_ADMIN' " ${ ZROK_SVC_FILE } " ; then
echo " ERROR: you must uncomment 'AmbientCapabilities=CAP_NET_ADMIN' in ' ${ ZROK_SVC_FILE } ' " \
"and run 'systemctl daemon-reload' to enable VPN mode" >& 2
exit 1
fi
fi
; ;
socks)
if [ [ -n " ${ ZROK_TARGET } " ] ] ; then
echo " WARNING: ZROK_TARGET=' ${ ZROK_TARGET } ' is ignored with ZROK_BACKEND_MODE=' ${ ZROK_BACKEND_MODE } ' " >& 2
unset ZROK_TARGET
fi
; ;
esac
fi
; ;
2023-11-28 03:12:38 +01:00
*)
echo " WARNING: ZROK_BACKEND_MODE=' ${ ZROK_BACKEND_MODE } ' is not a recognized mode for a zrok public share. " \
" ZROK_TARGET value will not validated before running." >& 2
; ;
esac
2024-07-08 00:13:22 +02:00
if [ [ " ${ ZROK_FRONTEND_MODE :- } " = ~ ^reserved- && -n " ${ ZROK_UNIQUE_NAME :- } " ] ] ; then
2023-12-12 00:05:29 +01:00
ZROK_CMD += " --unique-name ${ ZROK_UNIQUE_NAME } "
2024-07-08 00:13:22 +02:00
elif [ [ -n " ${ ZROK_UNIQUE_NAME :- } " ] ] ; then
echo " WARNING: ZROK_UNIQUE_NAME=' ${ ZROK_UNIQUE_NAME } ' is ignored with ZROK_FRONTEND_MODE=' ${ ZROK_FRONTEND_MODE } ' " >& 2
fi
2024-07-08 00:20:03 +02:00
if [ [ " ${ ZROK_FRONTEND_MODE :- } " = ~ -private$ && " ${ ZROK_PERMISSION_MODE :- } " = = closed ] ] ; then
2024-07-08 00:13:22 +02:00
ZROK_CMD += " --closed"
if [ [ -n " ${ ZROK_ACCESS_GRANTS :- } " ] ] ; then
for ACCESS_GRANT in ${ ZROK_ACCESS_GRANTS } ; do
ZROK_CMD += " --access-grant ${ ACCESS_GRANT } "
done
else
echo " WARNING: ZROK_PERMISSION_MODE=' ${ ZROK_PERMISSION_MODE } ' and no additional ZROK_ACCESS_GRANTS; will be granted access " >& 2
fi
2024-07-08 00:20:03 +02:00
elif [ [ " ${ ZROK_FRONTEND_MODE :- } " = ~ -private$ && -n " ${ ZROK_PERMISSION_MODE :- } " && " ${ ZROK_PERMISSION_MODE } " != open ] ] ; then
2024-07-08 00:13:22 +02:00
echo " WARNING: ZROK_PERMISSION_MODE=' ${ ZROK_PERMISSION_MODE } ' is not a recognized value' " >& 2
2024-07-08 00:20:03 +02:00
elif [ [ " ${ ZROK_FRONTEND_MODE :- } " = ~ -public$ && -n " ${ ZROK_PERMISSION_MODE :- } " ] ] ; then
echo " WARNING: ZROK_PERMISSION_MODE=' ${ ZROK_PERMISSION_MODE } ' is ignored with ZROK_FRONTEND_MODE=' ${ ZROK_FRONTEND_MODE } ' " >& 2
2024-07-08 00:13:22 +02:00
fi
2023-12-08 21:50:21 +01:00
2023-11-28 03:12:38 +01:00
ZROK_CMD += " --backend-mode ${ ZROK_BACKEND_MODE } ${ ZROK_TARGET } "
if [ [ -n " ${ ZROK_SHARE_OPTS :- } " ] ] ; then
ZROK_CMD += " ${ ZROK_SHARE_OPTS } "
fi
if [ [ -n " ${ ZROK_OAUTH_PROVIDER :- } " ] ] ; then
ZROK_CMD += " --oauth-provider ${ ZROK_OAUTH_PROVIDER } "
if [ [ -n " ${ ZROK_OAUTH_EMAILS :- } " ] ] ; then
for EMAIL in ${ ZROK_OAUTH_EMAILS } ; do
2024-06-04 15:00:20 +02:00
ZROK_CMD += " --oauth-email-address-patterns ${ EMAIL } "
2023-11-28 03:12:38 +01:00
done
2023-11-16 02:27:49 +01:00
fi
2023-11-28 03:12:38 +01:00
elif [ [ -n " ${ ZROK_BASIC_AUTH :- } " ] ] ; then
ZROK_CMD += " --basic-auth ${ ZROK_BASIC_AUTH } "
2023-11-02 22:08:10 +01:00
fi
2024-06-07 07:04:48 +02:00
if [ [ " ${ ZROK_FRONTEND_MODE :- } " = ~ ^temp- ] ] ; then
# frontend mode starts with 'temp-', so is temporary.
# share without reserving until exit.
2024-10-10 17:19:51 +02:00
exec_with_common_opts ${ ZROK_CMD }
2023-11-02 22:08:10 +01:00
else
2023-11-28 03:12:38 +01:00
# reserve and continue
2024-03-14 04:54:09 +01:00
zrok ${ ZROK_CMD } > ~/.zrok/reserved.json
2023-11-28 03:12:38 +01:00
# share the reserved backend target until exit
if ! [ [ -s ~/.zrok/reserved.json ] ] ; then
echo " ERROR: empty or missing $( realpath ~/.zrok) /reserved.json " >& 2
2023-11-02 22:08:10 +01:00
exit 1
2024-03-14 04:54:09 +01:00
elif ! jq . < ~/.zrok/reserved.json & >/dev/null; then
echo " ERROR: invalid JSON in $( realpath ~/.zrok) /reserved.json " >& 2
exit 1
2023-11-28 03:12:38 +01:00
else
ZROK_PUBLIC_URLS = $( jq -cr '.frontend_endpoints' ~/.zrok/reserved.json 2>/dev/null)
if [ [ -z " ${ ZROK_PUBLIC_URLS } " || " ${ ZROK_PUBLIC_URLS } " = = null ] ] ; then
echo " ERROR: frontend endpoints not defined in $( realpath ~/.zrok) /reserved.json " >& 2
exit 1
else
echo " INFO: zrok public URLs: ${ ZROK_PUBLIC_URLS } "
fi
ZROK_RESERVED_TOKEN = $( jq -r '.token' ~/.zrok/reserved.json 2>/dev/null)
if [ [ -z " ${ ZROK_RESERVED_TOKEN } " || " ${ ZROK_RESERVED_TOKEN } " = = null ] ] ; then
echo " ERROR: zrok reservation token not defined in $( realpath ~/.zrok) /reserved.json " >& 2
exit 1
fi
ZROK_CMD = " ${ ZROK_RESERVED_TOKEN } ${ ZROK_TARGET } "
2023-12-11 21:36:19 +01:00
if [ [ " ${ ZROK_SHARE_RESERVED } " = = true ] ] ; then
2024-10-10 17:19:51 +02:00
exec_share_reserved ${ ZROK_CMD }
2023-12-11 21:36:19 +01:00
else
echo "INFO: finished reserving zrok backend, continuing without sharing"
exit 0
fi
2023-11-02 22:08:10 +01:00
fi
fi