From 3ac5d55204ac197999506571771448a35a04a557 Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Thu, 28 Oct 2021 17:45:13 -0400 Subject: [PATCH 01/14] add a Dockerfile and shell script for reproducible Linux builds of all Ziti artifacts to enable forks and contributors who can't run ziti-ci Release v0.22.12 always build the Linux container with latest Go Use go install instead of go get reconcile upstream's main workflow reconcile upstream's common/version/info_generated.go --- Dockerfile.linux-build | 70 ++++++++++++++++++++++++++++++++++++++++++ linux-build.sh | 12 ++++++++ 2 files changed, 82 insertions(+) create mode 100644 Dockerfile.linux-build create mode 100755 linux-build.sh diff --git a/Dockerfile.linux-build b/Dockerfile.linux-build new file mode 100644 index 000000000..b269bbf79 --- /dev/null +++ b/Dockerfile.linux-build @@ -0,0 +1,70 @@ +FROM ubuntu:18.04 +# +# this file mirrors the build params used in the GitHub Actions and enables +# reproducible builds for downstream forks and Ziti contributors +# + +ARG latest_golang=1.17.2 +ARG go_distribution_file=go${latest_golang}.linux-amd64.tar.gz +ARG GOPATH=/root/go +ARG GOROOT=/usr/local/go +RUN apt-get update +RUN apt-get -yq install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf gcc-aarch64-linux-gnu +RUN apt-get -yq install wget build-essential +RUN wget -q https://golang.org/dl/${go_distribution_file} +RUN tar -xzf ${go_distribution_file} -C /usr/local/ +RUN mkdir ${GOPATH} +ENV GOPATH=${GOPATH} +ENV GOROOT=${GOROOT} +ENV PATH=$GOPATH/bin:$GOROOT/bin:$PATH +RUN go install github.com/mitchellh/gox@latest +WORKDIR /mnt +CMD ["./linux-build.sh"] + +## +# build this Dockerfile +## +# +# MINIMUM_GOLANG=$(grep -Po '^go\s+\K\d+\.\d+(\.\d+)?$' go.mod) +# LATEST_GOLANG=$(curl -sSf "https://golang.org/VERSION?m=text" | /bin/grep -Po '^go(\s+)?\K\d+\.\d+\.\d+$') +# docker build --tag=zitibuilder --file=Dockerfile.linux-build --build-arg latest_golang=${LATEST_GOLANG} . + +## +# build Ziti +## +# docker run --rm --name=zitibuilder --volume=$PWD:/mnt zitibuilder + +# $ tree ./release +# ./release +# ├── amd64 +# │   └── linux +# │   ├── ziti +# │   ├── ziti-controller +# │   ├── ziti-fabric +# │   ├── ziti-fabric-gw +# │   ├── ziti-fabric-test +# │   ├── ziti-probe +# │   ├── ziti-router +# │   └── ziti-tunnel +# ├── arm +# │   └── linux +# │   ├── ziti +# │   ├── ziti-controller +# │   ├── ziti-fabric +# │   ├── ziti-fabric-gw +# │   ├── ziti-fabric-test +# │   ├── ziti-probe +# │   ├── ziti-router +# │   └── ziti-tunnel +# └── arm64 +# └── linux +# ├── ziti +# ├── ziti-controller +# ├── ziti-fabric +# ├── ziti-fabric-gw +# ├── ziti-fabric-test +# ├── ziti-probe +# ├── ziti-router +# └── ziti-tunnel + +# 6 directories, 24 files diff --git a/linux-build.sh b/linux-build.sh new file mode 100755 index 000000000..05383a33d --- /dev/null +++ b/linux-build.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# +# build the Linux artifacts for amd64, arm, arm64 +# +# see instructions to run reproducible build with Docker in ./Dockerfile.linux-build +# +set -o pipefail -e -u + +GOX_OUTPUT="release/{{.Arch}}/{{.OS}}/{{.Dir}}" +CGO_ENABLED=true gox -os=linux -arch=amd64 -output=${GOX_OUTPUT} ./... +CC=arm-linux-gnueabihf-gcc CGO_ENABLED=true gox -cgo -os=linux -arch=arm -output=${GOX_OUTPUT} ./... +CC=aarch64-linux-gnu-gcc CGO_ENABLED=true gox -cgo -os=linux -arch=arm64 -output=$GOX_OUTPUT ./... From d4c38d9d4647e9dfcf6337a12e229e52d6c5a3ae Mon Sep 17 00:00:00 2001 From: Geoff Berl Date: Fri, 3 Dec 2021 12:01:59 -0500 Subject: [PATCH 02/14] 554: Added prompt for user input when detecting ziti env variables, some cleanup as well --- quickstart/docker/image/ziti-cli-functions.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index c7caaaea2..15c955266 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -221,7 +221,7 @@ function checkPrereqs { echo " " return 1 fi - echo "Let's get stated creating your local development network!" + echo "Let's get started creating your local development network!" echo "" echo "" } @@ -276,8 +276,8 @@ function setupZitiNetwork { fi echo "name: ${ZITI_NETWORK-}" else - echo " " - echo "nah bro" + echo "" + echo "============ FAILED TO SETUP NETWORK ============" return 1 fi echo " " @@ -323,8 +323,16 @@ function generateEnvFile { function ziti_expressConfiguration { if [[ "${ZITIx_EXPRESS_COMPLETE-}" != "" ]]; then echo -e "$(RED " --- It looks like you've run an express install in this shell already. ---")" - echo -e "$(RED " --- Please execute unsetZitiEnv to clear any variables already set. ---")" - return 1 + echo -en "Would you like to clear existing Ziti variables and continue (y/n)? " + read -q -r + echo + if [[ "${REPLY}" =~ [Yy]$ ]]; then + echo -e "$(GREEN "Clearing existing Ziti variables and continuing with express install")" + unsetZitiEnv + else + echo -e "$(RED " --- Exiting express install ---")" + return 1 + fi fi export ZITIx_EXPRESS_COMPLETE="true" echo " " From 7ca8a1aba4eef8bc66ca38ce6311c6e2143de35c Mon Sep 17 00:00:00 2001 From: Geoff Berl Date: Fri, 3 Dec 2021 13:41:57 -0500 Subject: [PATCH 03/14] 554: Fixing read option to work in both ZSH and bash --- quickstart/docker/image/ziti-cli-functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index 15c955266..3847b3104 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -324,7 +324,7 @@ function ziti_expressConfiguration { if [[ "${ZITIx_EXPRESS_COMPLETE-}" != "" ]]; then echo -e "$(RED " --- It looks like you've run an express install in this shell already. ---")" echo -en "Would you like to clear existing Ziti variables and continue (y/n)? " - read -q -r + read -n 1 -r echo if [[ "${REPLY}" =~ [Yy]$ ]]; then echo -e "$(GREEN "Clearing existing Ziti variables and continuing with express install")" From 7c858b06753d7b7cab3decc84162f900925f5516 Mon Sep 17 00:00:00 2001 From: Geoff Berl Date: Fri, 3 Dec 2021 14:40:21 -0500 Subject: [PATCH 04/14] 554: Removed -n option which responds differently in ZSH vs bash --- quickstart/docker/image/ziti-cli-functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index 3847b3104..b4f4dea47 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -324,7 +324,7 @@ function ziti_expressConfiguration { if [[ "${ZITIx_EXPRESS_COMPLETE-}" != "" ]]; then echo -e "$(RED " --- It looks like you've run an express install in this shell already. ---")" echo -en "Would you like to clear existing Ziti variables and continue (y/n)? " - read -n 1 -r + read -r echo if [[ "${REPLY}" =~ [Yy]$ ]]; then echo -e "$(GREEN "Clearing existing Ziti variables and continuing with express install")" From d7ae9e1cc0608d87b4df708756fb8a71da2faf35 Mon Sep 17 00:00:00 2001 From: Geoff Berl <95235264+gberl002@users.noreply.github.com> Date: Fri, 3 Dec 2021 14:51:53 -0500 Subject: [PATCH 05/14] Changed the y/n to y/N indicating No is default --- quickstart/docker/image/ziti-cli-functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index b4f4dea47..f7d5baab3 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -323,7 +323,7 @@ function generateEnvFile { function ziti_expressConfiguration { if [[ "${ZITIx_EXPRESS_COMPLETE-}" != "" ]]; then echo -e "$(RED " --- It looks like you've run an express install in this shell already. ---")" - echo -en "Would you like to clear existing Ziti variables and continue (y/n)? " + echo -en "Would you like to clear existing Ziti variables and continue (y/N)? " read -r echo if [[ "${REPLY}" =~ [Yy]$ ]]; then From c9107e96af0905da200c50d4184cc80e16d52a72 Mon Sep 17 00:00:00 2001 From: gberl002 Date: Mon, 6 Dec 2021 11:33:41 -0500 Subject: [PATCH 06/14] Updated user prompts to support zsh closes #555 --- quickstart/docker/image/ziti-cli-functions.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index f7d5baab3..516eb66b4 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -267,7 +267,8 @@ function setupZitiNetwork { echo -n "what a hostname looks like. A good choice is to actually use your system's hostname: " echo -e "$(BLUE "$(hostname)")" echo " " - read -rp "$(echo -ne "Network Name [$(BLUE "$(hostname)")]: ")" ZITI_NETWORK + echo -en "$(echo -ne "Network Name [$(BLUE "$(hostname)")]: ")" + read -r ZITI_NETWORK echo " " if checkControllerName; then : #clear to continue @@ -422,7 +423,8 @@ function decideToUseDefaultZitiHome { do echo "ZITI_HOME has not been set. Do you want to use the default ZITI_HOME: ${DEFAULT_ZITI_HOME_LOCATION}" echo " " - read -rp "Select an action: " yn + echo -en "Select an action: " + read -r yn case $yn in [yY]* ) break;; @@ -449,7 +451,8 @@ function decideOperation { echo " 3.) Create Edge Router configuration - answer a few questions and an edge router config will be emitted" echo " 4.) Start a network with the provided name" echo " " - read -rp "Select an action: " yn + echo -en "Select an action: " + read -r yn fi case $yn in [1]* ) From a8f9ae28941f26009fc11c40c7e5e38e35ea05f2 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Tue, 7 Dec 2021 19:10:28 -0500 Subject: [PATCH 07/14] fix the ca file referenced --- quickstart/docker/image/ziti-cli-functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index 516eb66b4..578122a45 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -990,7 +990,7 @@ identity: cert: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_CONTROLLER_HOSTNAME}-client.cert" server_cert: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_CONTROLLER_HOSTNAME}-server.chain.pem" key: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/keys/${ZITI_CONTROLLER_HOSTNAME}-server.key" - ca: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_CONTROLLER_INTERMEDIATE_NAME}.cert" + ca: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_EDGE_ROUTER_RAWNAME}-cas.cert" ctrl: listener: tls:0.0.0.0:${ZITI_FAB_CTRL_PORT} From 8c0c8ecfb10584910ab01ed3aa9e9e7a3e844813 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Tue, 7 Dec 2021 19:16:17 -0500 Subject: [PATCH 08/14] use the proper chain file --- quickstart/docker/image/ziti-cli-functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index 578122a45..c330dd66f 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -990,7 +990,7 @@ identity: cert: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_CONTROLLER_HOSTNAME}-client.cert" server_cert: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_CONTROLLER_HOSTNAME}-server.chain.pem" key: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/keys/${ZITI_CONTROLLER_HOSTNAME}-server.key" - ca: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_EDGE_ROUTER_RAWNAME}-cas.cert" + ca: "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_CONTROLLER_HOSTNAME}-server.chain.pem" ctrl: listener: tls:0.0.0.0:${ZITI_FAB_CTRL_PORT} From 666881b3cfdffb346af8e7aadf0e1ce179be6f02 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Tue, 7 Dec 2021 21:34:32 -0500 Subject: [PATCH 09/14] create a cas file using signing certs and server certs for controller --- quickstart/docker/image/ziti-cli-functions.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index c330dd66f..dd7a1aef1 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -974,6 +974,10 @@ function createControllerConfig { return 1 fi +cat "${ZITI_PKI_OS_SPECIFIC}/${ZITI_CONTROLLER_INTERMEDIATE_NAME}/certs/${ZITI_CONTROLLER_HOSTNAME}-server.chain.pem" > "${ZITI_PKI_OS_SPECIFIC}/cas.pem" +cat "${ZITI_PKI_OS_SPECIFIC}/${ZITI_SIGNING_INTERMEDIATE_NAME}/certs/${ZITI_SIGNING_INTERMEDIATE_NAME}.cert" >> "${ZITI_PKI_OS_SPECIFIC}/cas.pem" +echo "wrote CA file to: ${ZITI_PKI_OS_SPECIFIC}/cas.pem" + cat > "${ziti_home}/controller.yaml" < Date: Thu, 9 Dec 2021 09:25:26 -0500 Subject: [PATCH 10/14] commands that require a parameter now prompt user for input when argument not provided added console outputs when a command is executed successfully (stopZitiController, stopAllEdgeRouters) Added a single checkEnvVariable function so it can be used repeatedly for consistent output All functions that create a file now output the file location --- quickstart/docker/image/ziti-cli-functions.sh | 518 +++++++++++------- 1 file changed, 330 insertions(+), 188 deletions(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index dd7a1aef1..878db6316 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -45,13 +45,11 @@ function zitiLogin { "${ZITI_BIN_DIR-}/ziti" edge login "${ZITI_EDGE_CONTROLLER_API}" -u "${ZITI_USER-}" -p "${ZITI_PWD}" -c "${ZITI_PKI_OS_SPECIFIC}/${ZITI_EDGE_CONTROLLER_ROOTCA_NAME}/certs/${ZITI_EDGE_CONTROLLER_INTERMEDIATE_NAME}.cert" } function cleanZitiController { - ziti_home="${ZITI_HOME-}" - if [[ "${ziti_home}" == "" ]]; then - echo -e " * ERROR: $(RED "ZITI_HOME is not set") " + if [ "$(checkEnvVariable ZITI_HOME)" ]; then return 1 fi - rm -rf "${ziti_home}/db" - mkdir "${ziti_home}/db" + rm -rf "${ZITI_HOME}/db" + mkdir "${ZITI_HOME}/db" initializeController } function initializeController { @@ -65,18 +63,26 @@ function startZitiController { echo -e "ziti-controller started as process id: $pid. log located at: $(BLUE "${ZITI_HOME-}/ziti-edge-controller.log")" return $pid } + function stopZitiController { killall ziti-controller + # shellcheck disable=SC2181 + if [[ $? == 0 ]]; then echo "Controller stopped."; fi } + function startExpressEdgeRouter { "${ZITI_BIN_DIR}/ziti-router" run "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.yaml" > "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.log" 2>&1 & pid=$! echo -e "Express Edge Router started as process id: $pid. log located at: $(BLUE "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.log")" return $pid } + function stopAllEdgeRouters { - killall ziti-router + killall ziti-controller + # shellcheck disable=SC2181 + if [[ $? == 0 ]]; then echo "Router(s) stopped."; fi } + function checkHostsFile { ctrlexists=$(grep -c "${ZITI_CONTROLLER_HOSTNAME}" /etc/hosts) edgectrlexists=$(grep -c "${ZITI_EDGE_CONTROLLER_HOSTNAME}" /etc/hosts) @@ -111,6 +117,8 @@ function checkHostsFile { echo " " echo "add these entries to your hosts file, and rerun the script when ready" return 1 + else + echo -e "$(GREEN "Hosts file looks good")" fi } @@ -140,8 +148,7 @@ function getLatestZitiVersion { function getLatestZiti { setupZitiHome - if [[ "${ZITI_HOME-}" == "" ]]; then - echo "ERROR: ZITI_HOME is not set!" + if [ "$(checkEnvVariable ZITI_HOME)" ]; then return 1 fi @@ -157,12 +164,7 @@ function getLatestZiti { return 1 fi - ziti_bin_ver="${ZITI_BINARIES_VERSION-}" - if [[ "${ziti_bin_ver}" == "" ]]; then - echo "ERROR: ZITI_BINARIES_VERSION is not set!" - return 1 - fi - export ZITI_BIN_DIR="${ziti_bin_root}/ziti-${ziti_bin_ver}" + export ZITI_BIN_DIR="${ziti_bin_root}/ziti-${ZITI_BINARIES_VERSION}" ZITI_BINARIES_FILE_ABSPATH="${ZITI_HOME-}/ziti-bin/${ZITI_BINARIES_FILE}" if ! test -f "${ZITI_BINARIES_FILE_ABSPATH}"; then @@ -220,10 +222,9 @@ function checkPrereqs { echo " " echo " " return 1 + else + echo -e "$(GREEN "Prerequisites confirmed")" fi - echo "Let's get started creating your local development network!" - echo "" - echo "" } function checkControllerName { @@ -235,7 +236,12 @@ function checkControllerName { } function unsetZitiEnv { - for zEnvVar in $(set | grep -e "^ZITI_" | sort); do envvar="$(echo "${zEnvVar}" | cut -d '=' -f1)"; echo unsetting "[${envvar}]${zEnvVar}"; unset "${envvar}"; done + if [[ "${1-}" == "-s" ]]; then + # Silent... + for zEnvVar in $(set | grep -e "^ZITI_" | sort); do envvar="$(echo "${zEnvVar}" | cut -d '=' -f1)"; unset "${envvar}"; done + else + for zEnvVar in $(set | grep -e "^ZITI_" | sort); do envvar="$(echo "${zEnvVar}" | cut -d '=' -f1)"; echo unsetting "[${envvar}]${zEnvVar}"; unset "${envvar}"; done + fi unset ZITIx_EXPRESS_COMPLETE } @@ -290,7 +296,7 @@ function setupZitiNetwork { function setupZitiHome { if [[ "${ZITI_HOME-}" == "" ]]; then export ZITI_HOME="${HOME}/.ziti/quickstart/${ZITI_NETWORK-}" - echo "using default ZITI_HOME: ${ZITI_HOME}" + echo -e "using default ZITI_HOME: $(BLUE "${ZITI_HOME}")" fi } @@ -318,7 +324,7 @@ function generateEnvFile { export ENV_FILE="${ZITI_HOME-}/${ZITI_NETWORK-}.env" - echo -e "environment file created and sourced from: $(BLUE "${ENV_FILE}")" + echo -e "environment file sourced from: $(BLUE "${ENV_FILE}")" } function ziti_expressConfiguration { @@ -326,10 +332,10 @@ function ziti_expressConfiguration { echo -e "$(RED " --- It looks like you've run an express install in this shell already. ---")" echo -en "Would you like to clear existing Ziti variables and continue (y/N)? " read -r - echo + echo " " if [[ "${REPLY}" =~ [Yy]$ ]]; then echo -e "$(GREEN "Clearing existing Ziti variables and continuing with express install")" - unsetZitiEnv + unsetZitiEnv "-s" else echo -e "$(RED " --- Exiting express install ---")" return 1 @@ -356,6 +362,9 @@ function ziti_expressConfiguration { if [[ "${ZITI_EDGE_ROUTER_HOSTNAME-}" != "" ]]; then echo "ZITI_EDGE_ROUTER_HOSTNAME OVERIDDEN: $ZITI_EDGE_ROUTER_HOSTNAME"; fi if [[ "${ZITI_EDGE_ROUTER_PORT-}" != "" ]]; then echo "ZITI_EDGE_ROUTER_PORT OVERIDDEN: $ZITI_EDGE_ROUTER_PORT"; fi + echo " " + echo " " + echo -e "******** Setting Up Environment ********" if [[ "${1-}" == "" ]]; then nw="$(hostname)" else @@ -364,7 +373,7 @@ function ziti_expressConfiguration { setupZitiNetwork "${nw}" setupZitiHome - echo "ZITI HOME SET TO: ${ZITI_HOME}" + echo "ZITI HOME SET TO: $(BLUE "${ZITI_HOME}")" if ! getLatestZiti "no"; then echo -e "$(RED "getLatestZiti failed")" @@ -376,9 +385,16 @@ function ziti_expressConfiguration { fi #checkHostsFile + echo " " + echo " " + echo -e "******** Setting Up Public Key Infrastructure ********" createPki - createControllerConfig - #createControllerSystemdFile + + echo " " + echo " " + echo -e "******** Setting Up Controller ********" + createControllerConfig "controller" + #createControllerSystemdFile controller initializeController startZitiController echo "waiting for the controller to come online to allow the edge router to enroll" @@ -386,6 +402,9 @@ function ziti_expressConfiguration { zitiLogin + echo " " + echo " " + echo -e "******** Setting Up Edge Routers ********" echo -e "---------- Creating an edge router policy allowing all identities to connect to routers with a $(GREEN "#public") attribute" "${ZITI_BIN_DIR-}/ziti" edge delete edge-router-policy allEdgeRouters > /dev/null "${ZITI_BIN_DIR-}/ziti" edge create edge-router-policy allEdgeRouters --edge-router-roles '#public' --identity-roles '#all' > /dev/null @@ -402,12 +421,12 @@ function ziti_expressConfiguration { "${ZITI_BIN_DIR-}/ziti" edge delete edge-router "${ZITI_EDGE_ROUTER_RAWNAME}" > /dev/null "${ZITI_BIN_DIR-}/ziti" edge create edge-router "${ZITI_EDGE_ROUTER_RAWNAME}" -o "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.jwt" -t -a "public"> /dev/null sleep 1 - echo "---------- Enrolling edge-router ${ZITI_EDGE_ROUTER_RAWNAME}...." + echo "---------- Enrolling edge-router ${ZITI_EDGE_ROUTER_RAWNAME}...." "${ZITI_BIN_DIR-}/ziti-router" enroll "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.yaml" --jwt "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.jwt" &> "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.enrollment.log" echo "" - killall ziti-controller + stopZitiController echo "Edge Router enrolled. Controller stopped." echo "" @@ -490,6 +509,10 @@ function expressInstall { #make sure the user has all the necessary commands to be successful checkPrereqs + echo "Let's get started creating your local development network!" + echo "" + echo "" + #prompt the user for input and do what they want/need decideOperation 1 "${1-}" } @@ -550,13 +573,11 @@ function pki_create_intermediate { fi echo " " } -function printUsage() -{ +function printUsage() { echo "Usage: ${1-} [cert to test] [ca pool to use]" } -function verifyCertAgainstPool() -{ +function verifyCertAgainstPool() { if [[ "" == "${1-}" ]] then printUsage "verifyCertAgainstPool" @@ -585,8 +606,7 @@ function verifyCertAgainstPool() fi } -function showIssuerAndSubjectForPEM() -{ +function showIssuerAndSubjectForPEM() { echo "Displaying Issuer and Subject for cert pool:" echo " ${1-}" openssl crl2pkcs7 -nocrl -certfile "${1-}" | openssl pkcs7 -print_certs -text -noout | grep -E "(Subject|Issuer)" @@ -597,18 +617,29 @@ function createRouterPki { } function createPrivateRouterConfig { + # Allow router name to be passed in as arg router_name="${1-}" if [[ "${router_name}" == "" ]]; then - echo -e " * ERROR: $(RED "createPrivateRouterConfig requires a parameter to be supplied") " + + # If router name is not passed as arg, prompt user for input + echo -e "$(YELLOW "createPrivateRouterConfig requires a router name to be supplied") " + default_router_name="${ZITI_EDGE_ROUTER_RAWNAME}" + echo -en "Enter router name (${default_router_name}):" + read -r router_name + + # Accept the default if no name provided + if [[ "${router_name}" == "" ]]; then + router_name="${default_router_name}" + fi + fi + + # Make sure necessary env variables are set + if [ "$(checkEnvVariable ZITI_HOME ZITI_BIN_DIR)" ]; then return 1 fi - ziti_home="${ZITI_HOME-}" - if [[ "${ziti_home}" == "" ]]; then - echo -e " * ERROR: $(RED "ZITI_HOME is not set") " - return 1 - fi -cat > "${ZITI_HOME-}/${ZITI_EDGE_ROUTER_RAWNAME}.yaml" < "${output_file}" < "${ZITI_HOME}/${ZITI_EDGE_ROUTER_RAWNAME}.yaml" < "${output_file}" < "${ZITI_HOME-}/${router_name}.yaml" < "${output_file}" < "${ziti_home}/${router_name}.yaml" < "${output_file}" < "${ZITI_HOME}/identities.yml" < "${output_file}" < "${ZITI_PKI_OS_SPECIFIC}/cas.pem" cat "${ZITI_PKI_OS_SPECIFIC}/${ZITI_SIGNING_INTERMEDIATE_NAME}/certs/${ZITI_SIGNING_INTERMEDIATE_NAME}.cert" >> "${ZITI_PKI_OS_SPECIFIC}/cas.pem" -echo "wrote CA file to: ${ZITI_PKI_OS_SPECIFIC}/cas.pem" +echo "wrote CA file to: $(BLUE "${ZITI_PKI_OS_SPECIFIC}/cas.pem")" -cat > "${ziti_home}/controller.yaml" < "${output_file}" < "${systemd_file}" < "${output_file}" < "${systemd_file}" < "${output_file}" < "${launchd_file}" < "${output_file}" < Label - ziti-controller-${ZITI_BINARIES_VERSION} + ziti-controller-${controller_name} ProgramArguments - ./ziti-controller - + $ZITI_BIN_DIR/ziti-controller run - ./ctrl.with.edge.yml - - WorkingDirectory - ${ZITI_HOME} - KeepAlive - - SuccessfulExit - - - StandardOutPath - /Users/scarey/Library/Logs/ziti-controller-0.22.9.log - StandardErrorPath - /Users/scarey/Library/Logs/ziti-controller-0.22.9.log - - -HeredocForLaunchd - echo "Router launchd file written to: ${launchd_file}" -} -function createRouterLaunchdFile { - router_name="${1-}" - if [[ "${router_name}" == "" ]]; then - echo -e " * ERROR: $(RED "createRouterLaunchdFile requires parameter [router_name] to be supplied") " - return 1 - fi - - ziti_home="${ZITI_HOME-}" - if [[ "${ziti_home}" == "" ]]; then - echo -e " * ERROR: $(RED "ZITI_HOME is not set") " - return 1 - fi - - ziti_bin_dir="${ZITI_BIN_DIR-}" - if [[ "${ziti_bin_dir}" == "" ]]; then - echo -e " * ERROR: $(RED "ZITI_BIN_DIR is not set") " - return 1 - fi -launchd_file="${ziti_home}/ziti-router-${router_name}.launchd" -cat > "${launchd_file}" < - - - - Label - ziti-controller-0.22.9 - ProgramArguments - - ./ziti-controller - - run - ./ctrl.with.edge.yml + $ZITI_HOME/${controller_name}.yaml WorkingDirectory ${ZITI_HOME} @@ -1412,38 +1471,99 @@ cat > "${launchd_file}" < StandardOutPath - /Users/scarey/Library/Logs/ziti-controller-0.22.9.log + ${ZITI_HOME}/Logs/ziti-router-$ZITI_BINARIES_VERSION.log StandardErrorPath - /Users/scarey/Library/Logs/ziti-controller-0.22.9.log + ${ZITI_HOME}/Logs/ziti-router-$ZITI_BINARIES_VERSION.log HeredocForLaunchd - echo "Router launchd file written to: ${launchd_file}" + echo "Controller launchd file written to: $(BLUE "${output_file}")" + + showLaunchdMessage } +function createRouterLaunchdFile { + # Allow router name to be passed in as arg + router_name="${1-}" + if [[ "${router_name}" == "" ]]; then + + # If router name is not passed as arg, prompt user for input + echo -e "$(YELLOW "createRouterLaunchdFile requires a router name to be supplied") " + default_router_name="${ZITI_EDGE_ROUTER_RAWNAME}" + echo -en "Enter router name (${default_router_name}):" + read -r router_name + + # Accept the default if no name provided + if [[ "${router_name}" == "" ]]; then + router_name="${default_router_name}" + fi + fi + + # Make sure necessary env variables are set + if [ "$(checkEnvVariable ZITI_HOME ZITI_BIN_DIR)" ]; then + return 1 + fi + +output_file="${ziti_home}/ziti-router-${router_name}.plist" +cat > "${output_file}" < + + + + Label + ziti-router-$router_name + ProgramArguments + + $ZITI_BIN_DIR/ziti-router + run + $ZITI_HOME/ctrl.with.edge.yml + + WorkingDirectory + ${ZITI_HOME} + KeepAlive + + + PathState + + ${ZITI_HOME}/launchd-enabled + + + + StandardOutPath + ${ZITI_HOME}/Logs/ziti-router-$ZITI_BINARIES_VERSION.log + StandardErrorPath + ${ZITI_HOME}/Logs/ziti-router-$ZITI_BINARIES_VERSION.log + + +HeredocForLaunchd + echo "Router launchd file written to: $(BLUE "${output_file}")" + + showLaunchdMessage +} + +function showLaunchdMessage { + echo -e " " + echo -e "$(YELLOW "The generated launchd file is designed to keep the service alive while the file")" + echo -e "$(BLUE "${ZITI_HOME}/launchd-enabled") $(YELLOW "remains present.")" + echo -e "$(YELLOW "If this file is not present, the service will end")" +} function createZacSystemdFile { - ziti_home="${ZITI_HOME-}" - if [[ "${ziti_home}" == "" ]]; then - echo -e " * ERROR: $(RED "ZITI_HOME is not set") " + + if [ "$(checkEnvVariable ZITI_HOME )" ]; then return 1 fi - ziti_bin_dir="${ZITI_BIN_DIR-}" - if [[ "${ziti_bin_dir}" == "" ]]; then - echo -e " * ERROR: $(RED "ZITI_BIN_DIR is not set") " - return 1 - fi -systemd_file="${ziti_home}/ziti-console.service" -cat > "${systemd_file}" < "${output_file}" < Date: Thu, 9 Dec 2021 11:21:56 -0500 Subject: [PATCH 11/14] Update deps/changelog --- CHANGELOG.md | 7 +++++++ go.mod | 12 ++++++------ go.sum | 27 +++++++++++++-------------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa7272dcf..389cbeddb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# Release 0.24.2 + +## What's New + +* Bug fix: link verification could panic if link was established before control was finished establishing +* Enhancement: Improve logging around links in routers. Ensure we close both channels when closing a split link + # Release 0.24.1 ## What's New diff --git a/go.mod b/go.mod index 46c2c2016..e73bbdfda 100644 --- a/go.mod +++ b/go.mod @@ -34,10 +34,10 @@ require ( github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 github.com/michaelquigley/pfxlog v0.6.3 - github.com/openziti/edge v0.21.3 - github.com/openziti/fabric v0.17.2 - github.com/openziti/foundation v0.16.7 - github.com/openziti/sdk-golang v0.15.117 + github.com/openziti/edge v0.21.14 + github.com/openziti/fabric v0.17.7 + github.com/openziti/foundation v0.16.9 + github.com/openziti/sdk-golang v0.15.122 github.com/pborman/uuid v1.2.0 github.com/pkg/errors v0.9.1 github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 @@ -67,7 +67,7 @@ require ( github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211106181442-e4c1a74c66bd // indirect github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect github.com/biogo/store v0.0.0-20200525035639-8c94ae1e7c9c // indirect - github.com/cenkalti/backoff/v4 v4.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.1.2 // indirect github.com/cheekybits/genny v1.0.0 // indirect github.com/coreos/go-iptables v0.6.0 // indirect github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect @@ -123,7 +123,7 @@ require ( github.com/miekg/dns v1.1.43 // indirect github.com/miekg/pkcs11 v1.0.3 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect - github.com/mitchellh/mapstructure v1.4.2 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/natefinch/lumberjack v2.0.0+incompatible // indirect github.com/netfoundry/secretstream v0.1.2 // indirect github.com/nxadm/tail v1.4.8 // indirect diff --git a/go.sum b/go.sum index 9c6d235af..730dddf6a 100644 --- a/go.sum +++ b/go.sum @@ -138,8 +138,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= -github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -529,7 +529,7 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb-client-go/v2 v2.2.2/go.mod h1:fa/d1lAdUHxuc1jedx30ZfNG573oQTQmUni3N6pcW+0= -github.com/influxdata/influxdb-client-go/v2 v2.5.1/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU= +github.com/influxdata/influxdb-client-go/v2 v2.6.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= @@ -714,8 +714,8 @@ github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -765,15 +765,14 @@ github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e h1:ST9+54UtCr96S5 github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k= github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo= -github.com/openziti/edge v0.21.3 h1:/cPPmvSHjpCV2S99tukD7YSe4E+MXeHtedFs+0bqOHU= -github.com/openziti/edge v0.21.3/go.mod h1:s3U82m//n12qE5rb9Ja3NQY/ZhOTwRxT9kdAahEsGnU= -github.com/openziti/fabric v0.17.1/go.mod h1:6AGi2vTZckhZ5W6DfUml8ITUh+UTq1jJabwVNVglcX0= -github.com/openziti/fabric v0.17.2 h1:xjZhTx8LGBVKOboaCFbFZwmpOIpi18ODELnNH/IutfQ= -github.com/openziti/fabric v0.17.2/go.mod h1:6AGi2vTZckhZ5W6DfUml8ITUh+UTq1jJabwVNVglcX0= -github.com/openziti/foundation v0.16.7 h1:Ryuo4wp5CeXJAZYujbXfxuo6/GPpHnvJimESNTopRFY= -github.com/openziti/foundation v0.16.7/go.mod h1:DrzmWd4wka7/RlA37KTN2q+dz9dVSH6YJ9VP6xxf28w= -github.com/openziti/sdk-golang v0.15.117 h1:XFniHPcc03YLy2ZxRz2E7GhRdiWOonNiMQDA4rjvvig= -github.com/openziti/sdk-golang v0.15.117/go.mod h1:ZI3nT0vQ5UgkvK+7P9sGYWajZSMfvq1J4DZUMZYHmPA= +github.com/openziti/edge v0.21.14 h1:Hxl+ETLpbT020kkYgWVUxm48Pfr5nwUT5Q6u56VfXsc= +github.com/openziti/edge v0.21.14/go.mod h1:O5Yis5ZaBXeJgr2gTUJ1WAwItsvinMiPwplUwJbZuPc= +github.com/openziti/fabric v0.17.7 h1:wdXqlOuor/BL3jbypbQB2sv4T5oPmx97VkngSq5qunM= +github.com/openziti/fabric v0.17.7/go.mod h1:6ITQHTbVrvE0DHHnYkyx1XlnkKzwT+iU33hQxTnR29E= +github.com/openziti/foundation v0.16.9 h1:iAGPDESXRArGJQYBQSOif+fXfwYRxnvBh68tiXKB1g8= +github.com/openziti/foundation v0.16.9/go.mod h1:DrzmWd4wka7/RlA37KTN2q+dz9dVSH6YJ9VP6xxf28w= +github.com/openziti/sdk-golang v0.15.122 h1:RxFNpfsXb2wkLlvNpXUoBqABVkt/i8CnhDbk98VM6ig= +github.com/openziti/sdk-golang v0.15.122/go.mod h1:FROPdwoM1EkNxcttGtgvOZIJAHhaEe5RqSKF1Zr6aa0= github.com/oracle/oci-go-sdk v24.2.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI= github.com/orcaman/concurrent-map v0.0.0-20210106121528-16402b402231 h1:fa50YL1pzKW+1SsBnJDOHppJN9stOEwS+CRWyUtyYGU= From d9d17caf0be9a30d8c209eb2a6a011f339935524 Mon Sep 17 00:00:00 2001 From: gberl002 Date: Thu, 9 Dec 2021 14:29:46 -0500 Subject: [PATCH 12/14] Added confirmation request when overwriting a default file Fixed an issue with regex matching Fixed an issue with message not printing when checking env vars other minor fixes --- quickstart/docker/image/ziti-cli-functions.sh | 196 ++++++++++++++---- 1 file changed, 150 insertions(+), 46 deletions(-) diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index 878db6316..27e7e08a5 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -45,7 +45,9 @@ function zitiLogin { "${ZITI_BIN_DIR-}/ziti" edge login "${ZITI_EDGE_CONTROLLER_API}" -u "${ZITI_USER-}" -p "${ZITI_PWD}" -c "${ZITI_PKI_OS_SPECIFIC}/${ZITI_EDGE_CONTROLLER_ROOTCA_NAME}/certs/${ZITI_EDGE_CONTROLLER_INTERMEDIATE_NAME}.cert" } function cleanZitiController { - if [ "$(checkEnvVariable ZITI_HOME)" ]; then + checkEnvVariable ZITI_HOME + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi rm -rf "${ZITI_HOME}/db" @@ -148,7 +150,9 @@ function getLatestZitiVersion { function getLatestZiti { setupZitiHome - if [ "$(checkEnvVariable ZITI_HOME)" ]; then + checkEnvVariable ZITI_HOME + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi @@ -333,7 +337,7 @@ function ziti_expressConfiguration { echo -en "Would you like to clear existing Ziti variables and continue (y/N)? " read -r echo " " - if [[ "${REPLY}" =~ [Yy]$ ]]; then + if [[ "${REPLY}" == [Yy]* ]]; then echo -e "$(GREEN "Clearing existing Ziti variables and continuing with express install")" unsetZitiEnv "-s" else @@ -446,6 +450,7 @@ function decideToUseDefaultZitiHome { read -r yn case $yn in [yY]* ) + ZITI_HOME="${DEFAULT_ZITI_HOME_LOCATION}" break;; [Nn]* ) echo "" @@ -629,12 +634,24 @@ function createPrivateRouterConfig { # Accept the default if no name provided if [[ "${router_name}" == "" ]]; then + # Check for overwrite of default file router_name="${default_router_name}" + if [[ -f "${ZITI_HOME-}/${router_name}.yaml" ]]; then + echo -en "This will overwrite the existing file, continue (y/N)? " + read -r + echo " ${REPLY}" + if [[ "${REPLY}" == [^Yy]* ]]; then + echo -e "$(RED " --- Cancelling overwrite ---")" + return 1 + fi + fi fi fi # Make sure necessary env variables are set - if [ "$(checkEnvVariable ZITI_HOME ZITI_BIN_DIR)" ]; then + checkEnvVariable ZITI_HOME ZITI_BIN_DIR + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi @@ -708,7 +725,7 @@ forwarder: linkDialWorkerCount: 10 HereDocForEdgeRouter -echo "Controller configuration file written to: $(BLUE "${output_file}")" +echo -e "Controller configuration file written to: $(BLUE "${output_file}")" } function createPki { @@ -741,21 +758,31 @@ function createPki { } function createFabricRouterConfig { + # Allow router name to be passed in as arg router_name="${1-}" if [[ "${router_name}" == "" ]]; then - # If router name is not passed as arg, prompt user for input - echo -e "$(YELLOW "createFabricRouterConfig requires a router name to be supplied") " - echo -en "Enter router name:" - read -r router_name - # Accept the default if no name provided - if [[ "${router_name}" == "" ]]; then - echo -e " * ERROR: $(RED "createFabricRouterConfig requires a parameter [router_name] to be supplied") " - return 1 - fi + # If router name is not passed as arg, prompt user for input + echo -e "$(YELLOW "createEdgeRouterWssConfig requires a router name to be supplied") " + default_router_name="${ZITI_EDGE_ROUTER_RAWNAME}" + echo -en "Enter router name (${default_router_name}):" + read -r router_name + + # Accept the default if no name provided + if [[ "${router_name}" == "" ]]; then + # Check for overwrite of default file + router_name="${default_router_name}" + getFileOverwritePermission "${ZITI_HOME-}/${router_name}.yaml" + retVal=$? + if [[ "${retVal}" != 0 ]]; then + return 1 + fi + fi fi - if [ "$(checkEnvVariable ZITI_HOME)" ]; then + checkEnvVariable ZITI_HOME + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi @@ -829,7 +856,7 @@ forwarder: linkDialWorkerCount: 10 HereDocForEdgeRouter -echo "Fabric router configuration file written to: $(BLUE "${output_file}")" +echo -e "Fabric router configuration file written to: $(BLUE "${output_file}")" } function createEdgeRouterWssConfig { @@ -845,12 +872,20 @@ function createEdgeRouterWssConfig { # Accept the default if no name provided if [[ "${router_name}" == "" ]]; then + # Check for overwrite of default file router_name="${default_router_name}" + getFileOverwritePermission "${ZITI_HOME-}/${router_name}.yaml" + retVal=$? + if [[ "${retVal}" != 0 ]]; then + return 1 + fi fi fi # Make sure necessary env variables are set - if [ "$(checkEnvVariable ZITI_HOME ZITI_BIN_DIR)" ]; then + checkEnvVariable ZITI_HOME ZITI_BIN_DIR + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi @@ -924,7 +959,7 @@ forwarder: linkDialWorkerCount: 10 HereDocForEdgeRouter -echo "Edge router wss configuration file written to: $(BLUE "${output_file}")" +echo -e "Edge router wss configuration file written to: $(BLUE "${output_file}")" } # shellcheck disable=SC2120 @@ -941,12 +976,20 @@ function createEdgeRouterConfig { # Accept the default if no name provided if [[ "${router_name}" == "" ]]; then + # Check for overwrite of default file router_name="${default_router_name}" + getFileOverwritePermission "${ZITI_HOME-}/${router_name}.yaml" + retVal=$? + if [[ "${retVal}" != 0 ]]; then + return 1 + fi fi fi # Make sure necessary env variables are set - if [ "$(checkEnvVariable ZITI_HOME ZITI_BIN_DIR)" ]; then + checkEnvVariable ZITI_HOME ZITI_BIN_DIR + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi @@ -1020,7 +1063,7 @@ forwarder: linkDialWorkerCount: 10 HereDocForEdgeRouter -echo "edge router configuration file written to: $(BLUE "${output_file}")" +echo -e "edge router configuration file written to: $(BLUE "${output_file}")" } function createFabricIdentity { @@ -1034,7 +1077,7 @@ default: endpoint: tls:${ZITI_CONTROLLER_HOSTNAME}:${ZITI_FAB_MGMT_PORT} IdentitiesJsonHereDoc -echo "identities file written to: $(BLUE "${output_file}")" +echo -e "identities file written to: $(BLUE "${output_file}")" } function createControllerConfig { @@ -1050,12 +1093,20 @@ function createControllerConfig { # Accept the default if no name provided if [[ "${controller_name}" == "" ]]; then + # Check for overwrite of default file controller_name="${default_controller_name}" + getFileOverwritePermission "${ZITI_HOME-}/${controller_name}.yaml" + retVal=$? + if [[ "${retVal}" != 0 ]]; then + return 1 + fi fi fi # Make sure necessary env variables are set - if [ "$(checkEnvVariable ZITI_HOME )" ]; then + checkEnvVariable ZITI_HOME + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi @@ -1211,22 +1262,24 @@ web: HereDocForEdgeConfiguration - echo "Controller configuration file written to: $(BLUE "${output_file}")" + echo -e "Controller configuration file written to: $(BLUE "${output_file}")" } # shellcheck disable=SC2120 function ziti_createEnvFile { - if [ "$(checkEnvVariable ZITI_HOME)" ]; then + checkEnvVariable ZITI_HOME + retVal=$? + if [[ "${retVal}" != 0 ]]; then if decideToUseDefaultZitiHome; then # shellcheck disable=SC2155 export ZITI_NETWORK="$(hostname)" - ziti_home="${DEFAULT_ZITI_HOME_LOCATION}" + ZITI_HOME="${DEFAULT_ZITI_HOME_LOCATION}" else return 1 fi fi - export ZITI_HOME="${ziti_home}" + export ZITI_HOME="${ZITI_HOME}" if [[ "${ZITI_OSTYPE}" == "windows" ]]; then export ZITI_HOME_OS_SPECIFIC="$(cygpath -m "${ZITI_HOME}")" else @@ -1235,7 +1288,9 @@ function ziti_createEnvFile { export ENV_FILE="${ZITI_HOME}/${ZITI_NETWORK}.env" export ZITI_SHARED="${ZITI_HOME}" - if [ "$(checkEnvVariable ENV_FILE)" ]; then + checkEnvVariable ENV_FILE + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi @@ -1321,7 +1376,7 @@ echo " " fi heredoc -echo "env file written to: $(BLUE "${ENV_FILE}")" +echo -e "env file written to: $(BLUE "${ENV_FILE}")" } function waitForController { @@ -1352,16 +1407,24 @@ function createControllerSystemdFile { # Accept the default if no name provided if [[ "${controller_name}" == "" ]]; then - controller_name=default_controller_name + # Check for overwrite of default file + controller_name="${default_controller_name}" + getFileOverwritePermission "${ZITI_HOME-}/ziti-controller-${controller_name}.service" + retVal=$? + if [[ "${retVal}" != 0 ]]; then + return 1 + fi fi fi # Make sure necessary env variables are set - if [ "$(checkEnvVariable ZITI_HOME ZITI_BIN_DIR)" ]; then + checkEnvVariable ZITI_HOME ZITI_BIN_DIR + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi -output_file="${ZITI_HOME}/ziti-controller.service" +output_file="${ZITI_HOME}/ziti-controller-${controller_name}.service" cat > "${output_file}" < "${output_file}" < HeredocForLaunchd - echo "Controller launchd file written to: $(BLUE "${output_file}")" + echo -e "Controller launchd file written to: $(BLUE "${output_file}")" showLaunchdMessage } @@ -1495,16 +1574,24 @@ function createRouterLaunchdFile { # Accept the default if no name provided if [[ "${router_name}" == "" ]]; then + # Check for overwrite of default file router_name="${default_router_name}" + getFileOverwritePermission "${ZITI_HOME-}/ziti-router-${router_name}.plist" + retVal=$? + if [[ "${retVal}" != 0 ]]; then + return 1 + fi fi fi # Make sure necessary env variables are set - if [ "$(checkEnvVariable ZITI_HOME ZITI_BIN_DIR)" ]; then + checkEnvVariable ZITI_HOME ZITI_BIN_DIR + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi -output_file="${ziti_home}/ziti-router-${router_name}.plist" +output_file="${ZITI_HOME-}/ziti-router-${router_name}.plist" cat > "${output_file}" < @@ -1536,7 +1623,7 @@ cat > "${output_file}" < HeredocForLaunchd - echo "Router launchd file written to: $(BLUE "${output_file}")" + echo -e "Router launchd file written to: $(BLUE "${output_file}")" showLaunchdMessage } @@ -1545,12 +1632,14 @@ function showLaunchdMessage { echo -e " " echo -e "$(YELLOW "The generated launchd file is designed to keep the service alive while the file")" echo -e "$(BLUE "${ZITI_HOME}/launchd-enabled") $(YELLOW "remains present.")" - echo -e "$(YELLOW "If this file is not present, the service will end")" + echo -e "$(YELLOW "If this file is not present, the service will end.")" } function createZacSystemdFile { - if [ "$(checkEnvVariable ZITI_HOME )" ]; then + checkEnvVariable ZITI_HOME + retVal=$? + if [[ "${retVal}" != 0 ]]; then return 1 fi @@ -1572,7 +1661,7 @@ LimitNOFILE=65536 WantedBy=multi-user.target HeredocForSystemd - echo "ziti-console systemd file written to: $(BLUE "${output_file}")" + echo -e "ziti-console systemd file written to: $(BLUE "${output_file}")" } function setOs { @@ -1605,13 +1694,13 @@ function checkEnvVariable() { for arg do # Parameter expansion is different between shells - if [ -n "$ZSH_VERSION" ]; then - if [ -z "${(P)arg}" ]; then + if [[ -n "$ZSH_VERSION" ]]; then + if [[ -z "${(P)arg}" ]]; then echo -e " * ERROR: $(RED "${arg} is not set") " return 1 fi - elif [ -n "$BASH_VERSION" ]; then - if [ -z "${!arg}" ]; then + elif [[ -n "$BASH_VERSION" ]]; then + if [[ -z "${!arg}" ]]; then echo -e " * ERROR: $(RED "${arg} is not set") " return 1 fi @@ -1623,4 +1712,19 @@ function checkEnvVariable() { return 0 } +function getFileOverwritePermission() { + file_path="${1-}" + + if [[ -f "${file_path}" ]]; then + echo -en "This will overwrite the existing file, continue (y/N)? " + read -r + if [[ "${REPLY}" == [^Yy]* ]]; then + echo -e "$(RED " --- Cancelling overwrite ---")" + return 1 + fi + + return 0 + fi +} + set +uo pipefail From 4176352d16cd834414bc3a336a5a23df751a6865 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 9 Dec 2021 16:24:33 -0500 Subject: [PATCH 13/14] update docker files for zac --- quickstart/docker/docker-compose.yml | 15 + quickstart/docker/image/ziti-cli-functions.sh | 263 ++++++------------ .../docker/simplified-docker-compose.yml | 15 + 3 files changed, 115 insertions(+), 178 deletions(-) diff --git a/quickstart/docker/docker-compose.yml b/quickstart/docker/docker-compose.yml index 157b81b50..813dfef1c 100644 --- a/quickstart/docker/docker-compose.yml +++ b/quickstart/docker/docker-compose.yml @@ -94,6 +94,21 @@ services: networks: - zitiblue + ziti-console: + image: openziti/zac + environment: + - ZAC_SERVER_CERT_CHAIN=/openziti/pki/ziti-controller-intermediate/certs/ziti-controller-server.cert + - ZAC_SERVER_KEY=/openziti/pki/ziti-controller-intermediate/keys/ziti-controller-server.key -it + ports: + - "1408:1408" + - "8443:8443" + volumes: + - ziti-fs:/openziti + + networks: + - zitiblue + - zitired + networks: zitired: zitiblue: diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index 878db6316..fd866f605 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -45,11 +45,13 @@ function zitiLogin { "${ZITI_BIN_DIR-}/ziti" edge login "${ZITI_EDGE_CONTROLLER_API}" -u "${ZITI_USER-}" -p "${ZITI_PWD}" -c "${ZITI_PKI_OS_SPECIFIC}/${ZITI_EDGE_CONTROLLER_ROOTCA_NAME}/certs/${ZITI_EDGE_CONTROLLER_INTERMEDIATE_NAME}.cert" } function cleanZitiController { - if [ "$(checkEnvVariable ZITI_HOME)" ]; then + ziti_home="${ZITI_HOME-}" + if [[ "${ziti_home}" == "" ]]; then + echo -e " * ERROR: $(RED "ZITI_HOME is not set") " return 1 fi - rm -rf "${ZITI_HOME}/db" - mkdir "${ZITI_HOME}/db" + rm -rf "${ziti_home}/db" + mkdir "${ziti_home}/db" initializeController } function initializeController { @@ -63,26 +65,20 @@ function startZitiController { echo -e "ziti-controller started as process id: $pid. log located at: $(BLUE "${ZITI_HOME-}/ziti-edge-controller.log")" return $pid } - function stopZitiController { killall ziti-controller # shellcheck disable=SC2181 if [[ $? == 0 ]]; then echo "Controller stopped."; fi } - function startExpressEdgeRouter { "${ZITI_BIN_DIR}/ziti-router" run "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.yaml" > "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.log" 2>&1 & pid=$! echo -e "Express Edge Router started as process id: $pid. log located at: $(BLUE "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.log")" return $pid } - function stopAllEdgeRouters { - killall ziti-controller - # shellcheck disable=SC2181 - if [[ $? == 0 ]]; then echo "Router(s) stopped."; fi + killall ziti-router } - function checkHostsFile { ctrlexists=$(grep -c "${ZITI_CONTROLLER_HOSTNAME}" /etc/hosts) edgectrlexists=$(grep -c "${ZITI_EDGE_CONTROLLER_HOSTNAME}" /etc/hosts) @@ -117,8 +113,6 @@ function checkHostsFile { echo " " echo "add these entries to your hosts file, and rerun the script when ready" return 1 - else - echo -e "$(GREEN "Hosts file looks good")" fi } @@ -148,7 +142,8 @@ function getLatestZitiVersion { function getLatestZiti { setupZitiHome - if [ "$(checkEnvVariable ZITI_HOME)" ]; then + if [[ "${ZITI_HOME-}" == "" ]]; then + echo "ERROR: ZITI_HOME is not set!" return 1 fi @@ -164,7 +159,12 @@ function getLatestZiti { return 1 fi - export ZITI_BIN_DIR="${ziti_bin_root}/ziti-${ZITI_BINARIES_VERSION}" + ziti_bin_ver="${ZITI_BINARIES_VERSION-}" + if [[ "${ziti_bin_ver}" == "" ]]; then + echo "ERROR: ZITI_BINARIES_VERSION is not set!" + return 1 + fi + export ZITI_BIN_DIR="${ziti_bin_root}/ziti-${ziti_bin_ver}" ZITI_BINARIES_FILE_ABSPATH="${ZITI_HOME-}/ziti-bin/${ZITI_BINARIES_FILE}" if ! test -f "${ZITI_BINARIES_FILE_ABSPATH}"; then @@ -222,9 +222,10 @@ function checkPrereqs { echo " " echo " " return 1 - else - echo -e "$(GREEN "Prerequisites confirmed")" fi + echo "Let's get stated creating your local development network!" + echo "" + echo "" } function checkControllerName { @@ -236,12 +237,7 @@ function checkControllerName { } function unsetZitiEnv { - if [[ "${1-}" == "-s" ]]; then - # Silent... - for zEnvVar in $(set | grep -e "^ZITI_" | sort); do envvar="$(echo "${zEnvVar}" | cut -d '=' -f1)"; unset "${envvar}"; done - else - for zEnvVar in $(set | grep -e "^ZITI_" | sort); do envvar="$(echo "${zEnvVar}" | cut -d '=' -f1)"; echo unsetting "[${envvar}]${zEnvVar}"; unset "${envvar}"; done - fi + for zEnvVar in $(set | grep -e "^ZITI_" | sort); do envvar="$(echo "${zEnvVar}" | cut -d '=' -f1)"; echo unsetting "[${envvar}]${zEnvVar}"; unset "${envvar}"; done unset ZITIx_EXPRESS_COMPLETE } @@ -273,8 +269,7 @@ function setupZitiNetwork { echo -n "what a hostname looks like. A good choice is to actually use your system's hostname: " echo -e "$(BLUE "$(hostname)")" echo " " - echo -en "$(echo -ne "Network Name [$(BLUE "$(hostname)")]: ")" - read -r ZITI_NETWORK + read -rp "$(echo -ne "Network Name [$(BLUE "$(hostname)")]: ")" ZITI_NETWORK echo " " if checkControllerName; then : #clear to continue @@ -283,8 +278,8 @@ function setupZitiNetwork { fi echo "name: ${ZITI_NETWORK-}" else - echo "" - echo "============ FAILED TO SETUP NETWORK ============" + echo " " + echo "nah bro" return 1 fi echo " " @@ -296,7 +291,7 @@ function setupZitiNetwork { function setupZitiHome { if [[ "${ZITI_HOME-}" == "" ]]; then export ZITI_HOME="${HOME}/.ziti/quickstart/${ZITI_NETWORK-}" - echo -e "using default ZITI_HOME: $(BLUE "${ZITI_HOME}")" + echo "using default ZITI_HOME: ${ZITI_HOME}" fi } @@ -324,22 +319,14 @@ function generateEnvFile { export ENV_FILE="${ZITI_HOME-}/${ZITI_NETWORK-}.env" - echo -e "environment file sourced from: $(BLUE "${ENV_FILE}")" + echo -e "environment file created and sourced from: $(BLUE "${ENV_FILE}")" } function ziti_expressConfiguration { if [[ "${ZITIx_EXPRESS_COMPLETE-}" != "" ]]; then echo -e "$(RED " --- It looks like you've run an express install in this shell already. ---")" - echo -en "Would you like to clear existing Ziti variables and continue (y/N)? " - read -r - echo " " - if [[ "${REPLY}" =~ [Yy]$ ]]; then - echo -e "$(GREEN "Clearing existing Ziti variables and continuing with express install")" - unsetZitiEnv "-s" - else - echo -e "$(RED " --- Exiting express install ---")" - return 1 - fi + echo -e "$(RED " --- Please execute unsetZitiEnv to clear any variables already set. ---")" + return 1 fi export ZITIx_EXPRESS_COMPLETE="true" echo " " @@ -362,9 +349,6 @@ function ziti_expressConfiguration { if [[ "${ZITI_EDGE_ROUTER_HOSTNAME-}" != "" ]]; then echo "ZITI_EDGE_ROUTER_HOSTNAME OVERIDDEN: $ZITI_EDGE_ROUTER_HOSTNAME"; fi if [[ "${ZITI_EDGE_ROUTER_PORT-}" != "" ]]; then echo "ZITI_EDGE_ROUTER_PORT OVERIDDEN: $ZITI_EDGE_ROUTER_PORT"; fi - echo " " - echo " " - echo -e "******** Setting Up Environment ********" if [[ "${1-}" == "" ]]; then nw="$(hostname)" else @@ -373,7 +357,7 @@ function ziti_expressConfiguration { setupZitiNetwork "${nw}" setupZitiHome - echo "ZITI HOME SET TO: $(BLUE "${ZITI_HOME}")" + echo "ZITI HOME SET TO: ${ZITI_HOME}" if ! getLatestZiti "no"; then echo -e "$(RED "getLatestZiti failed")" @@ -385,16 +369,9 @@ function ziti_expressConfiguration { fi #checkHostsFile - echo " " - echo " " - echo -e "******** Setting Up Public Key Infrastructure ********" createPki - - echo " " - echo " " - echo -e "******** Setting Up Controller ********" - createControllerConfig "controller" - #createControllerSystemdFile controller + createControllerConfig + #createControllerSystemdFile initializeController startZitiController echo "waiting for the controller to come online to allow the edge router to enroll" @@ -402,9 +379,6 @@ function ziti_expressConfiguration { zitiLogin - echo " " - echo " " - echo -e "******** Setting Up Edge Routers ********" echo -e "---------- Creating an edge router policy allowing all identities to connect to routers with a $(GREEN "#public") attribute" "${ZITI_BIN_DIR-}/ziti" edge delete edge-router-policy allEdgeRouters > /dev/null "${ZITI_BIN_DIR-}/ziti" edge create edge-router-policy allEdgeRouters --edge-router-roles '#public' --identity-roles '#all' > /dev/null @@ -421,12 +395,12 @@ function ziti_expressConfiguration { "${ZITI_BIN_DIR-}/ziti" edge delete edge-router "${ZITI_EDGE_ROUTER_RAWNAME}" > /dev/null "${ZITI_BIN_DIR-}/ziti" edge create edge-router "${ZITI_EDGE_ROUTER_RAWNAME}" -o "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.jwt" -t -a "public"> /dev/null sleep 1 - echo "---------- Enrolling edge-router ${ZITI_EDGE_ROUTER_RAWNAME}...." + echo "---------- Enrolling edge-router ${ZITI_EDGE_ROUTER_RAWNAME}...." "${ZITI_BIN_DIR-}/ziti-router" enroll "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.yaml" --jwt "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.jwt" &> "${ZITI_HOME_OS_SPECIFIC}/${ZITI_EDGE_ROUTER_RAWNAME}.enrollment.log" echo "" - stopZitiController + killall ziti-controller echo "Edge Router enrolled. Controller stopped." echo "" @@ -442,8 +416,7 @@ function decideToUseDefaultZitiHome { do echo "ZITI_HOME has not been set. Do you want to use the default ZITI_HOME: ${DEFAULT_ZITI_HOME_LOCATION}" echo " " - echo -en "Select an action: " - read -r yn + read -rp "Select an action: " yn case $yn in [yY]* ) break;; @@ -470,8 +443,7 @@ function decideOperation { echo " 3.) Create Edge Router configuration - answer a few questions and an edge router config will be emitted" echo " 4.) Start a network with the provided name" echo " " - echo -en "Select an action: " - read -r yn + read -rp "Select an action: " yn fi case $yn in [1]* ) @@ -509,10 +481,6 @@ function expressInstall { #make sure the user has all the necessary commands to be successful checkPrereqs - echo "Let's get started creating your local development network!" - echo "" - echo "" - #prompt the user for input and do what they want/need decideOperation 1 "${1-}" } @@ -573,11 +541,13 @@ function pki_create_intermediate { fi echo " " } -function printUsage() { +function printUsage() +{ echo "Usage: ${1-} [cert to test] [ca pool to use]" } -function verifyCertAgainstPool() { +function verifyCertAgainstPool() +{ if [[ "" == "${1-}" ]] then printUsage "verifyCertAgainstPool" @@ -606,7 +576,8 @@ function verifyCertAgainstPool() { fi } -function showIssuerAndSubjectForPEM() { +function showIssuerAndSubjectForPEM() +{ echo "Displaying Issuer and Subject for cert pool:" echo " ${1-}" openssl crl2pkcs7 -nocrl -certfile "${1-}" | openssl pkcs7 -print_certs -text -noout | grep -E "(Subject|Issuer)" @@ -617,29 +588,18 @@ function createRouterPki { } function createPrivateRouterConfig { - # Allow router name to be passed in as arg router_name="${1-}" if [[ "${router_name}" == "" ]]; then - - # If router name is not passed as arg, prompt user for input - echo -e "$(YELLOW "createPrivateRouterConfig requires a router name to be supplied") " - default_router_name="${ZITI_EDGE_ROUTER_RAWNAME}" - echo -en "Enter router name (${default_router_name}):" - read -r router_name - - # Accept the default if no name provided - if [[ "${router_name}" == "" ]]; then - router_name="${default_router_name}" - fi - fi - - # Make sure necessary env variables are set - if [ "$(checkEnvVariable ZITI_HOME ZITI_BIN_DIR)" ]; then + echo -e " * ERROR: $(RED "createPrivateRouterConfig requires a parameter to be supplied") " return 1 fi -output_file="${ZITI_HOME-}/${router_name}.yaml" -cat > "${output_file}" < "${ZITI_HOME-}/${ZITI_EDGE_ROUTER_RAWNAME}.yaml" < "${output_file}" < "${ZITI_HOME}/${ZITI_EDGE_ROUTER_RAWNAME}.yaml" < "${output_file}" < "${ZITI_HOME-}/${router_name}.yaml" < "${output_file}" < "${ziti_home}/${router_name}.yaml" < "${output_file}" < "${ZITI_HOME}/identities.yml" < "${ZITI_PKI_OS_SPECIFIC}/cas.pem" cat "${ZITI_PKI_OS_SPECIFIC}/${ZITI_SIGNING_INTERMEDIATE_NAME}/certs/${ZITI_SIGNING_INTERMEDIATE_NAME}.cert" >> "${ZITI_PKI_OS_SPECIFIC}/cas.pem" -echo "wrote CA file to: $(BLUE "${ZITI_PKI_OS_SPECIFIC}/cas.pem")" +echo "wrote CA file to: ${ZITI_PKI_OS_SPECIFIC}/cas.pem" -output_file="${ZITI_HOME}/${controller_name}.yaml" -cat > "${output_file}" < "${ziti_home}/controller.yaml" < Date: Fri, 3 Dec 2021 16:25:26 -0500 Subject: [PATCH 14/14] Add support for inspect in ziti fabric and remove ziti-ops (moved to separate project) --- CHANGELOG.md | 2 + go.mod | 7 +- go.sum | 14 +- ziti-ops/logs/common.go | 323 ---------------------------- ziti-ops/logs/router_logs.go | 316 --------------------------- ziti-ops/main.go | 78 ------- ziti/cmd/ziti/cmd/fabric/inspect.go | 69 ++++++ ziti/cmd/ziti/cmd/fabric/root.go | 2 +- ziti/cmd/ziti/util/identities.go | 225 ++++++++++++------- ziti/cmd/ziti/util/rest.go | 13 +- 10 files changed, 240 insertions(+), 809 deletions(-) delete mode 100644 ziti-ops/logs/common.go delete mode 100644 ziti-ops/logs/router_logs.go delete mode 100644 ziti-ops/main.go create mode 100644 ziti/cmd/ziti/cmd/fabric/inspect.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 389cbeddb..621858f57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,9 @@ ## What's New * Bug fix: link verification could panic if link was established before control was finished establishing +* Bug fix: When checking edge terminator validity in the router, check terminator id as well the address * Enhancement: Improve logging around links in routers. Ensure we close both channels when closing a split link +* Enhancement: Add support for inspect in `ziti fabric`. Works the same as `ziti-fabric inspect` # Release 0.24.1 diff --git a/go.mod b/go.mod index e73bbdfda..dcb921c77 100644 --- a/go.mod +++ b/go.mod @@ -14,11 +14,10 @@ go 1.17 //replace github.com/michaelquigley/pfxlog => ../pfxlog -replace go.etcd.io/bbolt => github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e +//replace go.etcd.io/bbolt => github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e require ( github.com/Jeffail/gabs v1.4.0 - github.com/Jeffail/gabs/v2 v2.6.1 github.com/MakeNowJust/heredoc v1.0.0 github.com/MichaelMure/go-term-markdown v0.1.4 github.com/alecthomas/chroma v0.9.2 @@ -34,8 +33,8 @@ require ( github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 github.com/michaelquigley/pfxlog v0.6.3 - github.com/openziti/edge v0.21.14 - github.com/openziti/fabric v0.17.7 + github.com/openziti/edge v0.21.16 + github.com/openziti/fabric v0.17.9 github.com/openziti/foundation v0.16.9 github.com/openziti/sdk-golang v0.15.122 github.com/pborman/uuid v1.2.0 diff --git a/go.sum b/go.sum index 730dddf6a..a6a5c6ba1 100644 --- a/go.sum +++ b/go.sum @@ -66,7 +66,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Jeffail/gabs/v2 v2.6.1 h1:wwbE6nTQTwIMsMxzi6XFQQYRZ6wDc1mSdxoAN+9U4Gk= github.com/Jeffail/gabs/v2 v2.6.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= @@ -761,14 +760,12 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e h1:ST9+54UtCr96S5+Wa7LQtpGS6/xK7Z+KQXvOAtYgJlA= -github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k= github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo= -github.com/openziti/edge v0.21.14 h1:Hxl+ETLpbT020kkYgWVUxm48Pfr5nwUT5Q6u56VfXsc= -github.com/openziti/edge v0.21.14/go.mod h1:O5Yis5ZaBXeJgr2gTUJ1WAwItsvinMiPwplUwJbZuPc= -github.com/openziti/fabric v0.17.7 h1:wdXqlOuor/BL3jbypbQB2sv4T5oPmx97VkngSq5qunM= -github.com/openziti/fabric v0.17.7/go.mod h1:6ITQHTbVrvE0DHHnYkyx1XlnkKzwT+iU33hQxTnR29E= +github.com/openziti/edge v0.21.16 h1:IRlG6A7nuwu1KcT1LxeQHOPNEp6NPxHKV7Oo5cL5UyE= +github.com/openziti/edge v0.21.16/go.mod h1:scsApPeHqL58mza7r5T5AlvLwiZfVN3icygklKIX3fw= +github.com/openziti/fabric v0.17.9 h1:s8YmUehZXI6svwNJ01D3VyLr79AT/q470PPqT5q4qBg= +github.com/openziti/fabric v0.17.9/go.mod h1:U0oa6oD4alAiJepqPhzGRt5YZgs4aL79Lso/p2ItZqg= github.com/openziti/foundation v0.16.9 h1:iAGPDESXRArGJQYBQSOif+fXfwYRxnvBh68tiXKB1g8= github.com/openziti/foundation v0.16.9/go.mod h1:DrzmWd4wka7/RlA37KTN2q+dz9dVSH6YJ9VP6xxf28w= github.com/openziti/sdk-golang v0.15.122 h1:RxFNpfsXb2wkLlvNpXUoBqABVkt/i8CnhDbk98VM6ig= @@ -973,6 +970,9 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50 h1:ASw9n1EHMftwnP3Az4XW6e308+gNsrHzmdhd0Olz9Hs= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= diff --git a/ziti-ops/logs/common.go b/ziti-ops/logs/common.go deleted file mode 100644 index 61c0530cc..000000000 --- a/ziti-ops/logs/common.go +++ /dev/null @@ -1,323 +0,0 @@ -package logs - -import ( - "bufio" - "fmt" - "github.com/Jeffail/gabs/v2" - "github.com/openziti/foundation/util/stringz" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "os" - "regexp" - "sort" - "strings" - "time" -) - -type ParseContext struct { - path string - lineNumber int - eof bool - line string -} - -func ScanLines(ctx *ParseContext, callback func(ctx *ParseContext) error) error { - file, err := os.Open(ctx.path) - if err != nil { - return err - } - scanner := bufio.NewScanner(file) - for scanner.Scan() { - line := scanner.Text() - ctx.line = line - if err := callback(ctx); err != nil { - return errors.Wrapf(err, "error parsing %v on line %v", ctx.path, ctx.lineNumber) - } - ctx.lineNumber++ - } - ctx.eof = true - return callback(ctx) -} - -type JsonParseContext struct { - ParseContext - entry *gabs.Container -} - -func (self *JsonParseContext) RequiredString(path ...string) (string, error) { - v := self.entry.Search(path...) - if v == nil || v.Data() == nil { - return "", errors.Errorf("%v not found in log entry", strings.Join(path, ".")) - } - s, ok := v.Data().(string) - if !ok { - return "", errors.Errorf("%v is not a string", strings.Join(path, ".")) - } - return s, nil -} - -func (self *JsonParseContext) ParseJsonEntry() error { - input := self.line - idx := strings.IndexByte(self.line, '{') - if idx < 0 { - fmt.Printf("WARN: non-json line: %v", self.line) - return nil - } - if idx > 0 { - input = input[idx:] - } - entry, err := gabs.ParseJSON([]byte(input)) - if err != nil { - return err - } - self.entry = entry - return nil -} - -func ScanJsonLines(ctx *JsonParseContext, callback func(ctx *JsonParseContext) error) error { - return ScanLines(&ctx.ParseContext, func(*ParseContext) error { - if ctx.eof { - return callback(ctx) - } - if err := ctx.ParseJsonEntry(); err != nil { - return err - } - if ctx.entry != nil { - return callback(ctx) - } - return nil - }) -} - -type LogMatcher interface { - Matches(ctx *JsonParseContext) (bool, error) -} - -type LogFilter interface { - LogMatcher - Id() string - Label() string - Desc() string -} - -type filter struct { - LogMatcher - id string - label string - desc string -} - -func (self *filter) Id() string { - return self.id -} - -func (self *filter) Label() string { - return self.label -} - -func (self *filter) Desc() string { - return self.desc -} - -type JsonLogsParser struct { - bucketSize time.Duration - currentBucket time.Time - filters []LogFilter - bucketMatches map[LogFilter]int - unmatched int - maxUnmatchedLoggedPerBucket int - ignore []string -} - -func (self *JsonLogsParser) validate() error { - ids := map[string]int{} - for idx, k := range self.filters { - if v, found := ids[k.Id()]; found { - return errors.Errorf("duplicate filter id %v at indices %v and %v", k.Id(), idx, v) - } - ids[k.Id()] = idx - } - return nil -} - -func (self *JsonLogsParser) ShowCategories(*cobra.Command, []string) { - for _, filter := range self.filters { - fmt.Printf("%v (%v): %v\n", filter.Id(), filter.Label(), filter.Desc()) - } -} - -func (self *JsonLogsParser) examineLogEntry(ctx *JsonParseContext) error { - if ctx.eof { - self.dumpBucket() - return nil - } - if err := self.bucket(ctx); err != nil { - return err - } - - for _, filter := range self.filters { - match, err := filter.Matches(ctx) - if err != nil { - return err - } - - if match { - current := self.bucketMatches[filter] - self.bucketMatches[filter] = current + 1 - return nil - } - } - - self.unmatched++ - if self.unmatched <= self.maxUnmatchedLoggedPerBucket { - fmt.Printf("WARN: unmatched line: %v\n\n", ctx.line) - } - - return nil -} - -func (self *JsonLogsParser) bucket(ctx *JsonParseContext) error { - s, err := ctx.RequiredString("time") - if err != nil { - return err - } - t, err := time.Parse(time.RFC3339, s) - if err != nil { - return errors.Errorf("time is in an unexpected format: %v", s) - } - interval := t.Truncate(self.bucketSize) - if interval != self.currentBucket { - if !self.currentBucket.IsZero() { - self.dumpBucket() - } - self.currentBucket = interval - self.bucketMatches = map[LogFilter]int{} - self.unmatched = 0 - } - return nil -} - -func (self *JsonLogsParser) dumpBucket() { - var filters []LogFilter - for k := range self.bucketMatches { - if !stringz.Contains(self.ignore, k.Id()) { - filters = append(filters, k) - } - } - sort.Slice(filters, func(i, j int) bool { - return filters[i].Label() < filters[j].Label() - }) - if len(filters) == 0 && self.unmatched == 0 { - return - } - fmt.Printf("%v\n---------------------------------------------------\n", self.currentBucket.Format(time.RFC3339)) - for _, filter := range filters { - fmt.Printf(" %v (%v): %0000v\n", filter.Id(), filter.Label(), self.bucketMatches[filter]) - } - if self.unmatched > 0 { - fmt.Printf(" unmatched: %0000v\n", self.unmatched) - } - fmt.Println() -} - -func FieldStartsWith(field, substring string) LogMatcher { - return &EntryFieldStartsWithMatcher{ - field: field, - prefix: substring, - } -} - -type EntryFieldStartsWithMatcher struct { - field string - prefix string -} - -func (self *EntryFieldStartsWithMatcher) Matches(ctx *JsonParseContext) (bool, error) { - fieldValue, err := ctx.RequiredString(self.field) - if err != nil { - return false, err - } - return strings.HasPrefix(fieldValue, self.prefix), nil -} - -func FieldContains(field, substring string) LogMatcher { - return &EntryFieldContainsMatcher{ - field: field, - substring: substring, - } -} - -type EntryFieldContainsMatcher struct { - field string - substring string -} - -func (self *EntryFieldContainsMatcher) Matches(ctx *JsonParseContext) (bool, error) { - fieldValue, err := ctx.RequiredString(self.field) - if err != nil { - return false, err - } - return strings.Contains(fieldValue, self.substring), nil -} - -func FieldEquals(field, substring string) LogMatcher { - return &EntryFieldContainsMatcher{ - field: field, - substring: substring, - } -} - -type EntryFieldEqualsMatcher struct { - field string - value string -} - -func (self *EntryFieldEqualsMatcher) Matches(ctx *JsonParseContext) (bool, error) { - fieldValue, err := ctx.RequiredString(self.field) - if err != nil { - return false, err - } - return fieldValue == self.value, nil -} - -func AndMatchers(matchers ...LogMatcher) LogMatcher { - return &AndMatcher{matchers: matchers} -} - -type AndMatcher struct { - matchers []LogMatcher -} - -func (self *AndMatcher) Matches(ctx *JsonParseContext) (bool, error) { - for _, matcher := range self.matchers { - result, err := matcher.Matches(ctx) - if !result || err != nil { - return result, err - } - } - return true, nil -} - -func FieldMatches(field, expr string) LogMatcher { - regex, err := regexp.Compile(expr) - if err != nil { - panic(err) - } - return &EntryFieldMatchesMatcher{ - field: field, - regex: regex, - } -} - -type EntryFieldMatchesMatcher struct { - field string - regex *regexp.Regexp -} - -func (self *EntryFieldMatchesMatcher) Matches(ctx *JsonParseContext) (bool, error) { - fieldValue, err := ctx.RequiredString(self.field) - if err != nil { - return false, err - } - return self.regex.MatchString(fieldValue), nil -} diff --git a/ziti-ops/logs/router_logs.go b/ziti-ops/logs/router_logs.go deleted file mode 100644 index fceb62aea..000000000 --- a/ziti-ops/logs/router_logs.go +++ /dev/null @@ -1,316 +0,0 @@ -package logs - -import ( - "github.com/spf13/cobra" - "time" -) - -func NewLogsCommand() *cobra.Command { - logsCmd := &cobra.Command{ - Use: "logs", - Short: "commands related to analyzing various ziti component logs", - } - - parseRouterLogs := &ParseRouterLogs{} - parseRouterLogs.Init() - - parseRouterLogsCmd := &cobra.Command{ - Use: "router", - Short: "Parse router logs", - Args: cobra.ExactArgs(1), - RunE: parseRouterLogs.run, - } - - parseRouterLogsCmd.Flags().DurationVarP(&parseRouterLogs.bucketSize, "interval", "n", time.Hour, "Interval for which to aggregate log messages") - parseRouterLogsCmd.Flags().IntVarP(&parseRouterLogs.maxUnmatchedLoggedPerBucket, "max-unmatched", "u", 1, "Maximum unmatched log messages to output per bucket") - parseRouterLogsCmd.Flags().StringSliceVar(&parseRouterLogs.ignore, "ignore", []string{"IDLE", "CONF"}, "Filters to ignore") - - showRouterLogCategoriesCmd := &cobra.Command{ - Use: "categories", - Short: "Show router log entry categories", - Run: parseRouterLogs.ShowCategories, - } - - parseRouterLogsCmd.AddCommand(showRouterLogCategoriesCmd) - - logsCmd.AddCommand(parseRouterLogsCmd) - - return logsCmd -} - -type ParseRouterLogs struct { - JsonLogsParser -} - -func (self *ParseRouterLogs) Init() { - self.filters = getRouterLogFilters() -} - -func getRouterLogFilters() []LogFilter { - return []LogFilter{ - &filter{ - id: "IDLE", - label: "idle circuit scanner", - desc: "a circuit has been idle for at least one minute and the controller will be checked to see if the circuit is still valid", - LogMatcher: AndMatchers( - FieldContains("file", "forwarder/scanner.go"), - FieldContains("msg", " idle after "), - )}, - &filter{ - id: "CONF", - label: "circuit confirmation send", - desc: "controller has been notified of idle circuits and can respond if they are no longer valid", - LogMatcher: AndMatchers( - FieldContains("msg", "sent confirmation for "), - FieldContains("file", "forwarder/scanner.go"), - )}, - &filter{ - id: "TSCX", - label: "tunnel dial success", - desc: "a router embedded tunneler has made a successful connection to a server hosting an application", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "successful connection "), - FieldContains("file", "xgress_edge_tunnel/dialer.go"), - )}, - &filter{ - id: "DSTX", - label: "routing destination exists", - desc: "attempting to establish a circuit, but a previous dial attempt already established the egress connection", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "destination exists for "), - FieldContains("file", "handler_ctrl/route.go"), - )}, - &filter{ - id: "XGRF", - label: "xgress read failure", - desc: "read failure on the client or server side of the circuit; will cause the circuit to be torn down", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "read failed"), - FieldContains("file", "xgress/xgress.go"), - )}, - &filter{ - id: "XGWF", - label: "xgress write failure", - desc: "write failure on the client or server side of the circuit; will cause the circuit to be torn down", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "write failed"), - FieldContains("file", "xgress/xgress.go"), - )}, - &filter{ - id: "XGBF", - label: "xgress can't buffer", - desc: "while a circuit was being closed, data was received from the client or server", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "failure to buffer payload"), - FieldEquals("error", "payload buffer closed"), - FieldContains("file", "xgress/xgress.go"), - )}, - &filter{ - id: "RCFM", - label: "can't forward", - desc: "router can't forward a message most likely because the circuit is in the middle of being torn down", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "unable to forward"), - FieldContains("file", "handler_xgress/receive.go"), - )}, - &filter{ - id: "CSTO", - label: "circuit not started in time", - desc: "the terminating side of the circuit didn't receive a start from the initiating side", - LogMatcher: AndMatchers( - FieldEquals("msg", "xgress circuit not started in time, closing"), - FieldContains("file", "xgress/xgress.go"), - )}, - &filter{ - id: "TLSC", - label: "no tls certification provided", - desc: "a connection attempt was made to a TLS listener but no certificate was provided", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "error receiving hello from "), - FieldContains("msg", "tls: client didn't provide a certificate"), - FieldContains("file", "channel2/classic_listener.go"), - )}, - &filter{ - id: "LCYT", - label: "latency timeout", - desc: "a latency ping was sent, but no response was received within the timeout", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "latency timeout after "), - FieldContains("file", "metrics/latency.go"), - )}, - &filter{ - id: "CHRX", - label: "channel rx error", - desc: "channel read failed", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "rx error"), - FieldContains("msg", "connection reset by peer"), - FieldContains("file", "channel2/impl.go"), - )}, - &filter{ - id: "LNKS", - label: "dialing split channel link", - desc: "a link is being dialed to another router with separate connections for data and acknowledgements", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "dialing link with split payload/ack channels"), - FieldContains("file", "xlink_transport/dialer.go"), - )}, - &filter{ - id: "LNKR", - label: "controller requesting dial", - desc: "received a request from the controller to dial another router", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "received link connect request"), - FieldContains("file", "handler_ctrl/dial.go"), - )}, - &filter{ - id: "LNKD", - label: "dialing link", - desc: "dialing another router to establish a link", - LogMatcher: AndMatchers( - FieldEquals("msg", "dialing link"), - FieldContains("file", "handler_ctrl/dial.go"), - )}, - &filter{ - id: "LNKE", - label: "link established", - desc: "a link to another router has been established", - LogMatcher: AndMatchers( - FieldEquals("msg", "link established"), - FieldContains("file", "handler_ctrl/dial.go"), - )}, - &filter{ - id: "LNKP", - label: "dialing link payload channel", - desc: "dialing the link payload channel of a link", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "dialing payload channel for"), - FieldContains("file", "xlink_transport/dialer.go"), - )}, - &filter{ - id: "LNKK", - label: "dialing link ack channel", - desc: "dialing the link ack channel of a link", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "dialing ack channel for"), - FieldContains("file", "xlink_transport/dialer.go"), - )}, - &filter{ - id: "LNKC", - label: "link closed", - desc: "a router to router link was closed", - LogMatcher: AndMatchers( - FieldEquals("msg", "link closed"), - FieldContains("file", "handler_link/close.go"), - )}, - &filter{ - id: "FLTS", - label: "link fault sent", - desc: "the router notified the controller that a link failed", - LogMatcher: AndMatchers( - FieldEquals("msg", "transmitted link fault"), - FieldContains("file", "handler_link/close.go"), - )}, - &filter{ - id: "LNKA", - label: "link accepted", - desc: "another router has dialed this router and a link has been established", - LogMatcher: AndMatchers( - FieldStartsWith("msg", "accepted new link"), - FieldContains("file", "router/accepter.go"), - )}, - &filter{ - id: "RCNB", - label: "starting reconnect", - desc: "the router to controller control channel connection died and the router trying to reconnect", - LogMatcher: AndMatchers( - FieldContains("msg", "starting reconnection process"), - FieldContains("file", "channel2/reconnecting_impl.go"), - )}, - &filter{ - id: "RCNF", - label: "reconnect failed", - desc: "the router attempted to reconnect the control channel and failed", - LogMatcher: AndMatchers( - FieldContains("file", "channel2/reconnecting_dialer.go"), - FieldMatches("msg", "reconnection attempt.*failed"), - )}, - &filter{ - id: "RCNS", - label: "reconnect succeeded", - desc: "the router attempted to reconnect the control channel and succeeded", - LogMatcher: AndMatchers( - FieldEquals("msg", "reconnected"), - FieldContains("file", "channel2/reconnecting_impl.go"), - )}, - &filter{ - id: "RCNP", - label: "reconnect ping", - desc: "the router is checking the control channel to see if it needs to be reconnected", - LogMatcher: AndMatchers( - FieldContains("file", "channel2/reconnecting_impl.go"), - FieldContains("func", "pingInstance"), - )}, - &filter{ - id: "RCPF", - label: "reconnect ping failed", - desc: "the router control channel ping failed", - LogMatcher: AndMatchers( - FieldContains("msg", "unable to ping"), - FieldContains("file", "channel2/reconnecting_dialer.go"), - )}, - &filter{ - id: "HELO", - label: "received ctrl hello", - desc: "the controller sent us a hello message after a control channel was established or reconnected", - LogMatcher: AndMatchers( - FieldContains("msg", "received server hello"), - FieldContains("file", "handler_edge_ctrl/hello.go"), - )}, - &filter{ - id: "SSST", - label: "api session sync started", - desc: "The controller has started a full api session sync", - LogMatcher: AndMatchers( - FieldContains("file", "handler_edge_ctrl/apiSessionAdded.go"), - FieldMatches("msg", "api session.*starting"), - )}, - &filter{ - id: "SSCH", - label: "api session data received", - desc: "The controller sent a chunk of api session data", - LogMatcher: AndMatchers( - FieldContains("file", "handler_edge_ctrl/apiSessionAdded.go"), - FieldStartsWith("msg", "received api session sync chunk"), - )}, - &filter{ - id: "SSDN", - label: "api session sync finished", - desc: "The controller has finished a full api session sync", - LogMatcher: AndMatchers( - FieldContains("file", "handler_edge_ctrl/apiSessionAdded.go"), - FieldStartsWith("msg", "finished sychronizing api sessions"), - )}, - &filter{ - id: "CHAC", - label: "accepted connection", - desc: "a tcp connection has been accepted", - LogMatcher: AndMatchers( - FieldEquals("msg", "accepted connection"), - FieldContains("file", "transport/tcp/listener.go"), - )}, - } -} - -func (self *ParseRouterLogs) run(cmd *cobra.Command, args []string) error { - if err := self.validate(); err != nil { - return err - } - - ctx := &JsonParseContext{ - ParseContext: ParseContext{ - path: args[0], - }, - } - return ScanJsonLines(ctx, self.examineLogEntry) -} diff --git a/ziti-ops/main.go b/ziti-ops/main.go deleted file mode 100644 index 761043245..000000000 --- a/ziti-ops/main.go +++ /dev/null @@ -1,78 +0,0 @@ -//go:build all - -/* - Copyright NetFoundry, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package main - -import ( - "fmt" - "github.com/michaelquigley/pfxlog" - "github.com/openziti/fabric/build" - "github.com/openziti/ziti/common/version" - "github.com/openziti/ziti/ziti-ops/logs" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -var verbose bool -var logFormatter string - -func init() { - options := pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").NoColor() - pfxlog.GlobalInit(logrus.InfoLevel, options) - build.InitBuildInfo(version.GetCmdBuildInfo()) - - root.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose logging") - root.PersistentFlags().StringVar(&logFormatter, "log-formatter", "", "Specify log formatter [json|pfxlog|text]") - - root.AddCommand(&cobra.Command{ - Use: "version", - Short: "Show component version", - Run: func(cmd *cobra.Command, args []string) { - fmt.Println(version.GetBuildMetadata(verbose)) - }, - }) - - root.AddCommand(logs.NewLogsCommand()) -} - -var root = &cobra.Command{ - Use: "ziti-ops", - Short: "Ziti Ops Tools", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - if verbose { - logrus.SetLevel(logrus.DebugLevel) - } - - switch logFormatter { - case "pfxlog": - pfxlog.SetFormatter(pfxlog.NewFormatter(pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").StartingToday())) - case "json": - pfxlog.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02T15:04:05.000Z"}) - case "text": - pfxlog.SetFormatter(&logrus.TextFormatter{}) - default: - // let logrus do its own thing - } - }, -} - -func main() { - if err := root.Execute(); err != nil { - fmt.Printf("error: %s\n", err) - } -} diff --git a/ziti/cmd/ziti/cmd/fabric/inspect.go b/ziti/cmd/ziti/cmd/fabric/inspect.go new file mode 100644 index 000000000..677ebd840 --- /dev/null +++ b/ziti/cmd/ziti/cmd/fabric/inspect.go @@ -0,0 +1,69 @@ +package fabric + +import ( + "context" + "fmt" + "github.com/openziti/fabric/rest_client/inspect" + "github.com/openziti/fabric/rest_model" + "github.com/openziti/foundation/util/stringz" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" + "github.com/openziti/ziti/ziti/cmd/ziti/util" + "github.com/spf13/cobra" +) + +// newListCmd creates a command object for the "controller list" command +func newInspectCmd(p common.OptionsProvider) *cobra.Command { + listCmd := &ListCmd{Options: api.Options{CommonOptions: p()}} + return listCmd.newCobraCmd() +} + +type ListCmd struct { + api.Options +} + +func (self *ListCmd) newCobraCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "inspect", + Short: "Inspect runtime application values", + RunE: self.run, + Args: cobra.MinimumNArgs(2), + } + self.AddCommonFlags(cmd) + return cmd +} + +func (self *ListCmd) run(cmd *cobra.Command, args []string) error { + client, err := util.NewFabricManagementClient(self) + if err != nil { + return err + } + + inspectOk, err := client.Inspect.Inspect(&inspect.InspectParams{ + Request: &rest_model.InspectRequest{ + AppRegex: &args[0], + RequestedValues: args[1:], + }, + Context: context.Background(), + }) + + if err != nil { + return err + } + + result := inspectOk.Payload + if *result.Success { + fmt.Printf("\nResults: (%d)\n", len(result.Values)) + for _, value := range result.Values { + fmt.Printf("%v.%v\n", stringz.OrEmpty(value.AppID), stringz.OrEmpty(value.Name)) + fmt.Printf("%v\n\n", stringz.OrEmpty(value.Value)) + } + } else { + fmt.Printf("\nEncountered errors: (%d)\n", len(result.Errors)) + for _, err := range result.Errors { + fmt.Printf("\t%v\n", err) + } + } + + return nil +} diff --git a/ziti/cmd/ziti/cmd/fabric/root.go b/ziti/cmd/ziti/cmd/fabric/root.go index e48a30ddc..1061f9ebd 100644 --- a/ziti/cmd/ziti/cmd/fabric/root.go +++ b/ziti/cmd/ziti/cmd/fabric/root.go @@ -32,7 +32,7 @@ func NewFabricCmd(p common.OptionsProvider) *cobra.Command { fabricCmd.AddCommand(newAddIdentityCmd(p), newRemoveIdentityCmd(p)) fabricCmd.AddCommand(newCreateCommand(p), newListCmd(p), newUpdateCommand(p), newDeleteCmd(p)) - + fabricCmd.AddCommand(newInspectCmd(p)) return fabricCmd } diff --git a/ziti/cmd/ziti/util/identities.go b/ziti/cmd/ziti/util/identities.go index 44c1a5043..6eba87d3a 100644 --- a/ziti/cmd/ziti/util/identities.go +++ b/ziti/cmd/ziti/util/identities.go @@ -7,6 +7,7 @@ import ( "fmt" httptransport "github.com/go-openapi/runtime/client" "github.com/openziti/edge/rest_management_api_client" + fabric_rest_client "github.com/openziti/fabric/rest_client" "github.com/openziti/foundation/common/constants" "github.com/openziti/foundation/identity/identity" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" @@ -46,11 +47,13 @@ func (self *RestClientConfig) GetIdentity() string { } type RestClientIdentity interface { + NewTlsClientConfig() (*tls.Config, error) NewClient(timeout time.Duration, verbose bool) (*resty.Client, error) NewRequest(client *resty.Client) *resty.Request IsReadOnly() bool GetBaseUrlForApi(api API) (string, error) - NewEdgeManagementClient(clientOpts EdgeManagementClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) + NewEdgeManagementClient(clientOpts ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) + NewFabricManagementClient(clientOpts ClientOpts) (*fabric_rest_client.ZitiFabric, error) } func NewRequest(restClientIdentity RestClientIdentity, timeoutInSeconds int, verbose bool) (*resty.Request, error) { @@ -74,6 +77,21 @@ func (self *RestClientEdgeIdentity) IsReadOnly() bool { return self.ReadOnly } +func (self *RestClientEdgeIdentity) NewTlsClientConfig() (*tls.Config, error) { + rootCaPool := x509.NewCertPool() + + rootPemData, err := ioutil.ReadFile(self.CaCert) + if err != nil { + return nil, errors.Errorf("could not read session certificates [%s]: %v", self.CaCert, err) + } + + rootCaPool.AppendCertsFromPEM(rootPemData) + + return &tls.Config{ + RootCAs: rootCaPool, + }, nil +} + func (self *RestClientEdgeIdentity) NewClient(timeout time.Duration, verbose bool) (*resty.Client, error) { client := newClient() client.SetRootCertificate(self.CaCert) @@ -102,85 +120,12 @@ func (self *RestClientEdgeIdentity) GetBaseUrlForApi(api API) (string, error) { return "", errors.Errorf("unsupport api %v", api) } -func (self *RestClientEdgeIdentity) NewEdgeManagementClient(clientOpts EdgeManagementClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) { - respFunc := func(resp *http.Response, err error) { - if clientOpts.OutputResponseJson() { - if resp == nil || resp.Body == nil { - _, _ = fmt.Fprint(clientOpts.OutputWriter(), "\n") - return - } - - resp.Body = ioutil.NopCloser(resp.Body) - bodyContent, err := ioutil.ReadAll(resp.Body) - if err != nil { - _, _ = fmt.Fprintf(clientOpts.ErrOutputWriter(), "could not read response body: %v", err) - return - } - bodyStr := string(bodyContent) - _, _ = fmt.Fprint(clientOpts.OutputWriter(), bodyStr, "\n") - } - } - - reqFunc := func(request *http.Request) error { - if self.ReadOnly && !strings.EqualFold(request.Method, "get") { - return errors.New("this login is marked read-only, only GET operations are allowed") - } - if clientOpts.OutputRequestJson() { - if request == nil || request.Body == nil { - _, _ = fmt.Fprint(clientOpts.OutputWriter(), "\n") - return nil - } - - body, err := request.GetBody() - if err == nil { - _, _ = fmt.Fprintf(clientOpts.ErrOutputWriter(), "could not copy request body: %v", err) - return nil - } - bodyContent, err := ioutil.ReadAll(body) - if err != nil { - bodyStr := string(bodyContent) - _, _ = fmt.Fprint(clientOpts.OutputWriter(), bodyStr, "\n") - return nil - } - } - return nil - } - - httpClientTransport := &edgeTransport{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 10 * time.Second, - KeepAlive: 10 * time.Second, - }).DialContext, - - ForceAttemptHTTP2: true, - MaxIdleConns: 10, - IdleConnTimeout: 10 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - }, - ResponseFunc: respFunc, - RequestFunc: reqFunc, - } - - rootCaPool := x509.NewCertPool() - - rootPemData, err := ioutil.ReadFile(self.CaCert) +func (self *RestClientEdgeIdentity) NewEdgeManagementClient(clientOpts ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) { + httpClient, err := newRestClientTransport(clientOpts, self) if err != nil { - return nil, errors.Errorf("could not read session certificates [%s]: %v", self.CaCert, err) + return nil, err } - rootCaPool.AppendCertsFromPEM(rootPemData) - - httpClientTransport.TLSClientConfig = &tls.Config{ - RootCAs: rootCaPool, - } - - httpClient := &http.Client{ - Transport: httpClientTransport, - Timeout: 10 * time.Second, - } parsedHost, err := url.Parse(self.Url) if err != nil { return nil, err @@ -195,6 +140,26 @@ func (self *RestClientEdgeIdentity) NewEdgeManagementClient(clientOpts EdgeManag return rest_management_api_client.New(clientRuntime, nil), nil } +func (self *RestClientEdgeIdentity) NewFabricManagementClient(clientOpts ClientOpts) (*fabric_rest_client.ZitiFabric, error) { + httpClient, err := newRestClientTransport(clientOpts, self) + if err != nil { + return nil, err + } + + parsedHost, err := url.Parse(self.Url) + if err != nil { + return nil, err + } + + clientRuntime := httptransport.NewWithClient(parsedHost.Host, fabric_rest_client.DefaultBasePath, fabric_rest_client.DefaultSchemes, httpClient) + + clientRuntime.DefaultAuthentication = &EdgeManagementAuth{ + Token: self.Token, + } + + return fabric_rest_client.New(clientRuntime, nil), nil +} + type RestClientFabricIdentity struct { Url string `json:"url"` CaCert string `json:"caCert,omitempty"` @@ -203,6 +168,14 @@ type RestClientFabricIdentity struct { ReadOnly bool `json:"readOnly"` } +func (self *RestClientFabricIdentity) NewTlsClientConfig() (*tls.Config, error) { + id, err := identity.LoadClientIdentity(self.ClientCert, self.ClientKey, self.CaCert) + if err != nil { + return nil, errors.Wrap(err, "unable to load identity") + } + return id.ClientTLSConfig(), nil +} + func (self *RestClientFabricIdentity) NewClient(timeout time.Duration, verbose bool) (*resty.Client, error) { id, err := identity.LoadClientIdentity(self.ClientCert, self.ClientKey, self.CaCert) if err != nil { @@ -234,10 +207,26 @@ func (self *RestClientFabricIdentity) IsReadOnly() bool { return self.ReadOnly } -func (self *RestClientFabricIdentity) NewEdgeManagementClient(EdgeManagementClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) { +func (self *RestClientFabricIdentity) NewEdgeManagementClient(ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) { return nil, errors.New("fabric identities cannot be used to connect to the edge management API") } +func (self *RestClientFabricIdentity) NewFabricManagementClient(clientOpts ClientOpts) (*fabric_rest_client.ZitiFabric, error) { + httpClient, err := newRestClientTransport(clientOpts, self) + if err != nil { + return nil, err + } + + parsedHost, err := url.Parse(self.Url) + if err != nil { + return nil, err + } + + clientRuntime := httptransport.NewWithClient(parsedHost.Host, fabric_rest_client.DefaultBasePath, fabric_rest_client.DefaultSchemes, httpClient) + + return fabric_rest_client.New(clientRuntime, nil), nil +} + func LoadRestClientConfig() (*RestClientConfig, string, error) { config := &RestClientConfig{} @@ -370,3 +359,83 @@ func LoadSelectedRWIdentityForApi(api API) (RestClientIdentity, error) { } return id, nil } + +func newRestClientResponseF(clientOpts ClientOpts) func(*http.Response, error) { + return func(resp *http.Response, err error) { + if clientOpts.OutputResponseJson() { + if resp == nil || resp.Body == nil { + _, _ = fmt.Fprint(clientOpts.OutputWriter(), "\n") + return + } + + resp.Body = ioutil.NopCloser(resp.Body) + bodyContent, err := ioutil.ReadAll(resp.Body) + if err != nil { + _, _ = fmt.Fprintf(clientOpts.ErrOutputWriter(), "could not read response body: %v", err) + return + } + bodyStr := string(bodyContent) + _, _ = fmt.Fprint(clientOpts.OutputWriter(), bodyStr, "\n") + } + } +} + +func newRestClientRequestF(clientOpts ClientOpts, readOnly bool) func(*http.Request) error { + return func(request *http.Request) error { + if readOnly && !strings.EqualFold(request.Method, "get") { + return errors.New("this login is marked read-only, only GET operations are allowed") + } + if clientOpts.OutputRequestJson() { + if request == nil || request.Body == nil { + _, _ = fmt.Fprint(clientOpts.OutputWriter(), "\n") + return nil + } + + body, err := request.GetBody() + if err == nil { + _, _ = fmt.Fprintf(clientOpts.ErrOutputWriter(), "could not copy request body: %v", err) + return nil + } + bodyContent, err := ioutil.ReadAll(body) + if err != nil { + bodyStr := string(bodyContent) + _, _ = fmt.Fprint(clientOpts.OutputWriter(), bodyStr, "\n") + return nil + } + } + return nil + } +} + +func newRestClientTransport(clientOpts ClientOpts, clientIdentity RestClientIdentity) (*http.Client, error) { + httpClientTransport := &edgeTransport{ + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 10 * time.Second, + KeepAlive: 10 * time.Second, + }).DialContext, + + ForceAttemptHTTP2: true, + MaxIdleConns: 10, + IdleConnTimeout: 10 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + }, + ResponseFunc: newRestClientResponseF(clientOpts), + RequestFunc: newRestClientRequestF(clientOpts, clientIdentity.IsReadOnly()), + } + + tlsClientConfig, err := clientIdentity.NewTlsClientConfig() + if err != nil { + return nil, err + } + + httpClientTransport.TLSClientConfig = tlsClientConfig + + httpClient := &http.Client{ + Transport: httpClientTransport, + Timeout: 10 * time.Second, + } + return httpClient, nil +} diff --git a/ziti/cmd/ziti/util/rest.go b/ziti/cmd/ziti/util/rest.go index eb6ef54a1..7dd498213 100644 --- a/ziti/cmd/ziti/util/rest.go +++ b/ziti/cmd/ziti/util/rest.go @@ -29,6 +29,7 @@ import ( "github.com/go-openapi/strfmt" "github.com/openziti/edge/rest_management_api_client" "github.com/openziti/edge/rest_model" + fabric_rest_client "github.com/openziti/fabric/rest_client" "github.com/openziti/ziti/common/version" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" c "github.com/openziti/ziti/ziti/cmd/ziti/constants" @@ -766,14 +767,14 @@ func WrapIfApiError(err error) error { return err } -type EdgeManagementClientOpts interface { +type ClientOpts interface { OutputRequestJson() bool OutputResponseJson() bool OutputWriter() io.Writer ErrOutputWriter() io.Writer } -func NewEdgeManagementClient(clientOpts EdgeManagementClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) { +func NewEdgeManagementClient(clientOpts ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) { restClientIdentity, err := LoadSelectedIdentity() if err != nil { return nil, err @@ -781,6 +782,14 @@ func NewEdgeManagementClient(clientOpts EdgeManagementClientOpts) (*rest_managem return restClientIdentity.NewEdgeManagementClient(clientOpts) } +func NewFabricManagementClient(clientOpts ClientOpts) (*fabric_rest_client.ZitiFabric, error) { + restClientIdentity, err := LoadSelectedIdentity() + if err != nil { + return nil, err + } + return restClientIdentity.NewFabricManagementClient(clientOpts) +} + type EdgeManagementAuth struct { Token string }