diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 20bded73c..490c07905 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -91,7 +91,7 @@ jobs: name: Fablab Smoketest runs-on: ubuntu-20.04 outputs: - ziti-version: ${{ steps.get_version.outputs.ziti-version }} + ZITI_VERSION: ${{ steps.get_version.outputs.ZITI_VERSION }} steps: - name: Git Checkout uses: actions/checkout@v3 @@ -137,7 +137,7 @@ jobs: - name: Test Ziti Command env: - ZITI_ROOT: dist/ + ZITI_ROOT: dist/bin/ run: | $(go env GOPATH)/bin/simple-transfer create $(go env GOPATH)/bin/simple-transfer up @@ -146,7 +146,7 @@ jobs: - name: Test Ziti Command Teardown if: always() env: - ZITI_ROOT: dist/ + ZITI_ROOT: dist/bin/ run: | $(go env GOPATH)/bin/simple-transfer dispose $(go env GOPATH)/bin/simple-transfer clean @@ -158,7 +158,7 @@ jobs: runs-on: ubuntu-20.04 needs: [ mac-os-build, windows-build, fablab-smoketest ] outputs: - ziti-version: ${{ steps.get_version.outputs.ziti-version }} + ZITI_VERSION: ${{ steps.get_version.outputs.ZITI_VERSION }} steps: - name: Git Checkout uses: actions/checkout@v3 @@ -234,17 +234,17 @@ jobs: ZITI_VERSION=${ZITI_VERSION#v} if ! [[ "${ZITI_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then # fail the job because we could not obtain the current version from ziti-ci - echo "ERROR: ZITI_VERSION=${ZITI_VERSION}" + echo "ERROR: ZITI_VERSION=${ZITI_VERSION} is not a semver" exit 1 elif [[ "${GITHUB_REF}" =~ ^refs/heads/(release-v|main$) ]]; then # Set output parameters for release branches echo "DEBUG: ZITI_VERSION=${ZITI_VERSION}" - echo ::set-output name=ziti-version::${ZITI_VERSION} + echo ZITI_VERSION="${ZITI_VERSION}" >> $GITHUB_OUTPUT else # Append build / run number for non-release refs ZITI_VERSION="${ZITI_VERSION}-${GITHUB_RUN_ID}" echo "DEBUG: ZITI_VERSION=${ZITI_VERSION}" - echo ::set-output name=ziti-version::${ZITI_VERSION} + echo ZITI_VERSION="${ZITI_VERSION}" >> $GITHUB_OUTPUT fi - name: Publish to Artifactory @@ -278,7 +278,7 @@ jobs: env: SNAPSHOT_REPO: openziti/ziti-tunnel RELEASE_REPO: netfoundry/ziti-tunnel - ZITI_VERSION: ${{ steps.get_version.outputs.ziti-version }} + ZITI_VERSION: ${{ steps.get_version.outputs.ZITI_VERSION }} id: tagprep run: | # the Docker cross-build only runs on branches main or release-v* @@ -289,7 +289,7 @@ jobs: done DOCKER_TAGS=${DOCKER_TAGS#,} # drop leading comma char echo "DEBUG: DOCKER_TAGS=${DOCKER_TAGS}" - echo ::set-output name=tags::${DOCKER_TAGS} + echo DOCKER_TAGS="${DOCKER_TAGS}" >> $GITHUB_OUTPUT - name: Build & Push Multi-Platform Container Image to Hub if: github.repository_owner == 'openziti' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release-v')) @@ -302,7 +302,7 @@ jobs: DOCKER_BUILD_DIR=./ziti-tunnel/docker platforms: linux/amd64,linux/arm/v7,linux/arm64 push: true - tags: ${{ steps.tagprep.outputs.tags }} + tags: ${{ steps.tagprep.outputs.DOCKER_TAGS }} jenkins-smoketest: # BEGIN smoketest-job @@ -314,4 +314,4 @@ jobs: uses: ./.github/workflows/jenkins-smoketest.yml secrets: inherit with: - ziti-version: ${{ needs.publish.outputs.ziti-version }} + ziti-version: ${{ needs.publish.outputs.ZITI_VERSION }} diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 000000000..caa3d8ee8 --- /dev/null +++ b/BUILD.md @@ -0,0 +1,8 @@ + +# Build + +Please refer to [the local development README](./doc/002-local-dev.md) for build instructions. + +## Crossbuilds + +When you push to your repo fork then GitHub Actions will automatically crossbuild for several OSs and CPU architectures. You'll then be able to download the built artifacts from the GitHub UI. The easiest way to crossbuild the Linux exectuables locally is to build and run the crossbuild container. Please refer to [the crossbuild container README](../Dockerfile.linux-build.README) for those steps. For hints on crossbuilding for MacOS and Windows see [the main GitHub Actions workflow](../.github/workflows/main.yml) which defines the steps that are run when you push to GitHub. diff --git a/CHANGELOG.md b/CHANGELOG.md index f8449df12..75cf7d5ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,59 @@ +# Release 0.26.11 + +## What's New + +This is mainly a bugfix release. + +- Ziti CLI + - Bug Fixes (See Component Updates and Bug Fixes below) + - Added CLI flags for setting router tunneler capability + +## Ziti CLI + +### Added CLI flags for setting router tunneler capability +Ziti CLI `ziti create config router edge` now has two new flags; `--tunnelerMode` and `--lanInterface` +#### --tunnelerMode +The `--tunnelerMode` flag enables tunneling and sets the tunneler mode. Currently, there are `none`, `host` and `tproxy` +modes. The default tunneler mode is `host` mode, choosing `none` will disable tunnel capabilities for the router. + +Examples: +```shell +ziti create config router edge --routerName myRouter --tunnelerMode tproxy + +ziti create config router edge --routerName myRouter --tunnelerMode none +``` +#### --lanInterface +If using the `tproxy` tunneler mode, there is an optional `lanIf` section in the config to identify an interface to use. + +Example: +```shell +ziti create config router edge --routerName myRouter --tunnelerMode tproxy --lanInterface tun0 +``` + +## Component Updates and Bug Fixes + +* github.com/openziti/agent: [v1.0.4 -> v1.0.5](https://github.com/openziti/agent/compare/v1.0.4...v1.0.5) +* github.com/openziti/channel/v2: [v2.0.9 -> v2.0.12](https://github.com/openziti/channel/compare/v2.0.9...v2.0.12) +* github.com/openziti/edge: [v0.24.12 -> v0.24.36](https://github.com/openziti/edge/compare/v0.24.12...v0.24.36) + * [Issue #1217](https://github.com/openziti/edge/issues/1217) - Ziti Edge lists the edge router to be offline after recovering from an internet fluctuation + +* github.com/openziti/fabric: [v0.21.9 -> v0.21.17](https://github.com/openziti/fabric/compare/v0.21.9...v0.21.17) +* github.com/openziti/foundation/v2: [v2.0.6 -> v2.0.7](https://github.com/openziti/foundation/compare/v2.0.6...v2.0.7) +* github.com/openziti/identity: [v1.0.18 -> v1.0.20](https://github.com/openziti/identity/compare/v1.0.18...v1.0.20) +* github.com/openziti/runzmd: v1.0.3 (new) +* github.com/openziti/sdk-golang: [v0.16.135 -> v0.16.146](https://github.com/openziti/sdk-golang/compare/v0.16.135...v0.16.146) + * [Issue #328](https://github.com/openziti/sdk-golang/issues/328) - enrollment has no 'verbose' option for debugging + * [Issue #314](https://github.com/openziti/sdk-golang/issues/314) - Incorrect documentation for grpc-example + * [Issue #317](https://github.com/openziti/sdk-golang/issues/317) - No documenation for call example + * [Issue #311](https://github.com/openziti/sdk-golang/issues/311) - Chat Client and Server needs documentation + +* github.com/openziti/storage: [v0.1.25 -> v0.1.26](https://github.com/openziti/storage/compare/v0.1.25...v0.1.26) +* github.com/openziti/transport/v2: [v2.0.36 -> v2.0.38](https://github.com/openziti/transport/compare/v2.0.36...v2.0.38) +* github.com/openziti/metrics: [v1.1.4 -> v1.1.5](https://github.com/openziti/metrics/compare/v1.1.4...v1.1.5) +* github.com/openziti/ziti: [v0.26.10 -> v0.26.11](https://github.com/openziti/ziti/compare/v0.26.10...v0.26.11) + * [Issue 868](https://github.com/openziti/ziti/issues/868): `ZITI_EDGE_ROUTER_IP_OVERRIDE` does not override the edge router advertise hostname + * [Issue 882](https://github.com/openziti/ziti/issues/882): `ZITI_EDGE_ROUTER_RAWNAME` not stored in quickstart .env file + # Release 0.26.10 ## What's New diff --git a/Dockerfile.linux-build.README b/Dockerfile.linux-build.README new file mode 100644 index 000000000..63ccf9190 --- /dev/null +++ b/Dockerfile.linux-build.README @@ -0,0 +1,50 @@ +# Crossbuild Container for Building Linux Executables + +Running this container produces three executables for each Ziti component, one for each platform architecture: amd64, arm, arm64. You may instead build for one or more of these by specifying the architecture as a parameter to the `docker run` command as shown in the example below. + +## Local Development + +This article supports local development by providing a local containerized method for crossbuilding Linux executables. Alternatively, you may push to your GitHub repo fork to run [the main GitHub Actions workflow](./.github/workflows/main.yaml) (CI) which will crossbuild the binaries for MacOS, Windows, and Linux. Please refer to [the main article about local development](./doc/002-local-dev.md) for help getting up and running without Docker. + +## Build the Container Image + +You only need to build the container image once unless you change the Dockerfile or `./linux-build.sh` (the container's entrypoint). + +```bash +# find the latest Go distribution's semver +LATEST_GOLANG=$(curl -sSfL "https://go.dev/VERSION?m=text" | /bin/grep -Po '^go(\s+)?\K\d+\.\d+\.\d+$') +# build a container image named "zitibuilder" with the Dockerfile in the top-level of this repo +docker build \ + --tag=zitibuilder \ + --file=Dockerfile.linux-build \ + --build-arg latest_golang=${LATEST_GOLANG} \ + --build-arg uid=$UID \ + --build-arg gid=$GID . +``` + +## Run the Container to Build Executables for the Desired Architectures + +Executing the following `docker run` command will: + +1. Mount the top-level of this repo on the container's `/mnt` +2. Run `./linux-build.sh ${@}` inside the container +3. Deposit built executables in `./release` + +```bash +# build for all three architectures: amd64 arm arm64 +docker run \ + --rm \ + --name=zitibuilder \ + --volume=$PWD:/mnt \ + zitibuilder + +# build only amd64 +docker run \ + --rm \ + --name=zitibuilder \ + --volume=$PWD:/mnt \ + zitibuilder \ + amd64 +``` + +You will find the built artifacts in `./release`. diff --git a/README.md b/README.md index 6fed00227..d37dd257b 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,51 @@ # Ziti + Ziti represents the next generation of secure, open-source networking for your applications. Ziti has several components. -**Quick Reference** +## Quick Reference + * [Documentation](https://openziti.github.io/) -* [Developer Overview](https://github.com/openziti/ziti/blob/master/doc/001-overview.md) -* [Local Development](https://github.com/openziti/ziti/blob/master/doc/002-local-dev.md) -* [Local Deployment](https://github.com/openziti/ziti/blob/master/doc/003-local-deploy.md) -* [Release Notes](https://github.com/openziti/ziti/blob/master/CHANGELOG.md) +* [Developer Overview](./doc/001-overview.md) +* [Local Development Tutorial](./doc/002-local-dev.md) +* [Local Deployment Tutorial](./doc/003-local-deploy.md) +* [Controller PKI Tutorial](./doc/004-controller-pki.md) +* [Release Notes](./CHANGELOG.md) --- ## What is OpenZiti? + * The OpenZiti fabric provides a scalable, plugable, networking mesh with built in smart routing * The OpenZiti edge components provide a secure, Zero Trust entry point into your network * The OpenZiti SDKs allow you to integrate Ziti directly into your applications -* The OpenZiti tunnelers and proxies allow existing applications and networks to take advantage of a Ziti deployment +* The OpenZiti tunnelers and proxies allow existing applications and networks to take advantage of a Ziti deployment + +### Security Features -**Security Features** * Zero Trust and Application Segmentation * Dark Services and Routers * End to end encryption -**Performance and Reliability** -* A scalable mesh fabric with smart routing -* Support for load balancing services for both horizontal scale and failover setups +### Performance and Reliability + +* A scalable mesh fabric with smart routing +* Support for load balancing services for both horizontal scale and failover setups + +### Developer Focus -**Developer Focus** * [Open source code, available with the Apache 2.0 license](https://github.com/openziti) * Fully programmable REST management APIs * [SDKs for a variety of programming languages](https://openziti.github.io/ziti/clients/sdks) * [Application specific configuration store allowing centralized management of configuration allowing you to add structured configuration specific to your application](https://openziti.github.io/ziti/config-store/overview) -* An extensible fabric, allowing you to add your own - * load balancing algorithms - * interconnect protocols - * ingress and egress protocols - * metrics collections frameworks - * control and management plane messaging and semantics +* An extensible fabric, allowing you to add your own + * load balancing algorithms + * interconnect protocols + * ingress and egress protocols + * metrics collections frameworks + * control and management plane messaging and semantics + +### Easy Management -**Easy Management** * [A flexible and expressive policy model for managing access to services and edge routers](https://openziti.github.io/ziti/policies/overview) * A web based admin console * [Pre-built tunnelers and proxies for a variety of operating systems, including mobile](https://openziti.github.io/ziti/clients/tunneler) @@ -45,53 +53,60 @@ Ziti represents the next generation of secure, open-source networking for your a Let's break some of these buzzwords down. ### Zero Trust/Application Segmentation -Many networking security solutions act like a wall around an internal network. Once you are through the wall, you have access to everything inside. Zero trust solutions enforce not just access to a network, but access to individual applications within that network. + +Many networking security solutions act like a wall around an internal network. Once you are through the wall, you have access to everything inside. Zero trust solutions enforce not just access to a network, but access to individual applications within that network. Every client in a Ziti system must have an identity with provisioned certificates. The certificates are used to establish secure communications channels as well as for authentication and authorization of the associated identity. Whenever the client attempts to access a network application, Ziti will first ensure that the identity has access to the application. If access is revoked, open network connections will be closed. -This model enables Ziti systems to provide access to multiple applications while ensuring that clients only get access to those applications to which they have been granted access. +This model enables Ziti systems to provide access to multiple applications while ensuring that clients only get access to those applications to which they have been granted access. -In addition to requiring cert based authentication for clients, Ziti uses certificates to authorize communication between Ziti components. +In addition to requiring cert based authentication for clients, Ziti uses certificates to authorize communication between Ziti components. ### Dark Services and Routers + There are various levels of accessibility a network application/service can have. -1. Many network services are available to the world. The service then relies on authentication and authorization policies to prevent unwanted access. +1. Many network services are available to the world. The service then relies on authentication and authorization policies to prevent unwanted access. 1. Firewalls can be used to limit access to specific IP or ranges. This increases security at the cost of flexibility. Adding users can be complicated and users may not be able to easily switch devices or access the service remotely. 1. Services can be put behind a VPN or made only accessible to an internal network, but there are some downsides to this approach. 1. If you can access the VPN or internal network for any reason, all services in that VPN become more vulnerable to you. 1. VPNs are not usually appropriate for external customers or users. 1. For end users, VPNs add an extra step that needs to be done each time they want to access the service. -1. Services can be made dark, meaning they do not have any ports open for anyone to even try and connect to. +1. Services can be made dark, meaning they do not have any ports open for anyone to even try and connect to. -Making something dark can be done in a few ways, but the way it's generally handled in Ziti is that services reach out and establish one or more connections to the Ziti network fabric. Clients coming into the fabric can then reach the service through these connections after being authenticated and authorized. +Making something dark can be done in a few ways, but the way it's generally handled in Ziti is that services reach out and establish one or more connections to the Ziti network fabric. Clients coming into the fabric can then reach the service through these connections after being authenticated and authorized. Ziti routers, which make up the fabric, can also be dark. Routers located in private networks will usually be made dark. These routers will reach out of the private network to talk to the controller and to make connections to join the network fabric mesh. This allows the services and routers in your private networks to make only outbound connections, so no holes have to be opened for inbound traffic. -Services can be completely dark if they are implemented with a Ziti SDK. If this is not possible a Ziti tunneler or proxy can be colocated with the service. The service then only needs to allow connections from the local machine or network, depending on how close you colocate the proxy to the service. +Services can be completely dark if they are implemented with a Ziti SDK. If this is not possible a Ziti tunneler or proxy can be colocated with the service. The service then only needs to allow connections from the local machine or network, depending on how close you colocate the proxy to the service. ### End to End Encryption + If you take advantage of Ziti's developer SDKs and embed Ziti in your client and server applications, your traffic can be configured to be seamlessly encrypted from the client application to server application. If you prefer to use tunnelers or proxy applications, the traffic can be encrypted for you from machine to machine or private network to private network. Various combinations of the above are also supported. End-to-end encryption means that even if systems between the client and server are compromised, your traffic cannot be decrypted or tampered with. --- - + ## Getting started with OpenZiti If you are looking to jump right in feet first you can follow along with one of our [up-and-running quickstart -guides](https://openziti.github.io/ziti/quickstarts/quickstart-overview.html). These guides are designed to get an -overlay network quickly and allow you to run it all locally, use docker or host it anywhere. +guides](https://openziti.github.io/ziti/quickstarts/quickstart-overview.html). These guides are designed to get an +overlay network quickly and allow you to run it all locally, use Docker or host it anywhere. This environment is perfect for evaluators to get to know Ziti and the capabilities it offers. The environment was not designed for large scale deployment or for long-term usage. If you are looking for a managed service to help you run a -truly global, scalable network browse over to our website at http://netfoundry.io to learn more. +truly global, scalable network browse over [the NetFoundry web site](https://netfoundry.io) to learn more. + +## Build from Source + +Please refer to [the local development tutorial](./doc/002-local-dev.md) for build instructions. --- ## Adopters -Interested to see what companies are using OpenZiti? Check out [the list of projects and companies using OpenZiti here](./ADOPTERS.md). +Interested to see what companies are using OpenZiti? Check out [the list of projects and companies using OpenZiti here](./ADOPTERS.md). Interested in adding your project to the list? Add an issue to github or better yet feel free to add a pull request! Instructions for getting your project added are included [on the adopters list](./ADOPTERS.md) @@ -99,27 +114,28 @@ getting your project added are included [on the adopters list](./ADOPTERS.md) ## Support -We have a very active Discourse forum. Join the conversation! Help others if you can. If you want to ask a question or just check it out, +We have a very active Discourse forum. Join the conversation! Help others if you can. If you want to ask a question or just check it out, cruise on over to [the OpenZiti Discourse forum](https://openziti.discourse.group/). We love getting questions, jump in! --- ### Contributing + The Ziti project welcomes contributions including, but not limited to, code, documentation and bug reports. * All Ziti code is found on Github under the [OpenZiti](https://github.com/openziti) organization. - * [ziti](https://github.com/openziti/ziti): top level project which builds all Ziti executables - * [edge](https://github.com/openziti/edge): edge components and model which includes identity, polices and config - * [fabric](https://github.com/openziti/fabric): fabric project which includes core controller and router - * [foundation](https://github.com/openziti/foundation): project which contains library code used across multiple projects - * SDKs - * [ziti-sdk-c] (https://github.com/openziti/ziti-sdk-c): C SDK - * [sdk-golang] (https://github.com/openziti/sdk-golang): Go SDK - * [ziti-sdk-jvm] (https://github.com/openziti/ziti-sdk-jvm): SDK for JVM based languages - * [ziti-sdk-swift] (https://github.com/openziti/ziti-sdk-swift): Swift SDK - * [ziti-sdk-nodejs] (https://github.com/openziti/ziti-sdk-nodejs): NodeJS SDK - * [ziti-sdk-csharp] (https://github.com/openziti/ziti-sdk-csharp): C# SDK - * [ziti-doc](https://github.com/openziti/ziti-doc): Powers the static documentation site + * [ziti](https://github.com/openziti/ziti): top level project which builds all Ziti executables + * [edge](https://github.com/openziti/edge): edge components and model which includes identity, polices and config + * [fabric](https://github.com/openziti/fabric): fabric project which includes core controller and router + * [foundation](https://github.com/openziti/foundation): project which contains library code used across multiple projects + * SDKs + * [ziti-sdk-c] (https://github.com/openziti/ziti-sdk-c): C SDK + * [sdk-golang] (https://github.com/openziti/sdk-golang): Go SDK + * [ziti-sdk-jvm] (https://github.com/openziti/ziti-sdk-jvm): SDK for JVM based languages + * [ziti-sdk-swift] (https://github.com/openziti/ziti-sdk-swift): Swift SDK + * [ziti-sdk-nodejs] (https://github.com/openziti/ziti-sdk-nodejs): NodeJS SDK + * [ziti-sdk-csharp] (https://github.com/openziti/ziti-sdk-csharp): C# SDK + * [ziti-doc](https://github.com/openziti/ziti-doc): Powers the static documentation site Ziti was developed and open sourced by [Netfoundry, Inc](https://netfoundry.io). NetFoundry continues to fund and -contribute to OpenZiti. +contribute to OpenZiti. diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 000000000..4a1075eec --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,13 @@ +# Releasing Ziti + +Release happen by merging from the release-next branch to main. + +## Release pre-requisites + +1. Make sure you have a clean build in GitHub Actions. +2. Make sure you have a clean build in Jenkins smoketest (until smoketest is superceded by fablab smoke in GH) +3. Make sure CHANGELOG.md is up to date + 1. You can use `ziti-ci build-release-notes` to generate ziti library version updates and issues fixed, + as long as the git commit has `fixed #` (or fixes, closes, closed, etc) +4. Create a PR to merge release-next to main, once it's approved you can merge and the release will happen. + diff --git a/doc/001-overview.md b/doc/001-overview.md index 4b3368c33..577e207f8 100644 --- a/doc/001-overview.md +++ b/doc/001-overview.md @@ -84,3 +84,7 @@ networks. | ziti-tunnel | Provides the ability to intercept traffic to route traffic across Ziti| All of the above binaries are cross platform compatible, except ziti-tunnel which is currently Linux only. + +## Further Exploration + +Continue your OpenZiti exploration in [the next article about getting set up for local development](./002-local-dev.md) and building the apps from source. diff --git a/doc/002-local-dev.md b/doc/002-local-dev.md index 8881718cf..84bb191a0 100644 --- a/doc/002-local-dev.md +++ b/doc/002-local-dev.md @@ -1,241 +1,96 @@ # Overview -This README aims to allow the setup of a development local environment as quick as possible. It uses predefined -configuration files that are maintained with the source code as well as Docker to run ancillary services (such as databases). +This local development README guides you to install the Ziti stack built from the currently checked out source branch in this repo without any downloads, containers, scripts, or magic. -## Dependencies +## Minimum Go Version -You may verify the currently-required version of Go with this command, or by peeking inside the file named `go.mod`. +You will need to [install a version of Go](https://go.dev/) that is as recent as the version used by this project. Find the current minimum version by running this command to inspect `go.mod`. ```bash -$ /bin/grep -Po '^go\s+\K\d+\.\d+$' go.mod -1.17 +grep -Po '^go\s+\K\d+\.\d+$' go.mod ``` -## Debugging +## Build and Install All Applications -This guide can be used to run all of the Ziti applications via command line or in the debugger of an IDE. - -## Get Started - -### Checkout & Build - -1. Checkout the `ziti` repository from `github.com/openziti/ziti` - - `git clone https://github.com/openziti/ziti.git` -2. Change into the `ziti` dirrectory - - `cd ziti` -3. Build all commands - - `go install ./...` -4. Build one command - - ```bash - ZITI_CMD=ziti-tunnel - rm -f ./build/${ZITI_CMD} \ - && mkdir -p ./build \ - && go build -o ./build/${ZITI_CMD} ./${ZITI_CMD}/cmd/${ZITI_CMD}/ \ - && ls -lARh ./build/${ZITI_CMD} - ``` - -### Multi-Platform Linux Builder Container - -The purpose of this container is to document the process of building locally the Linux executables in the same way as the GitHub Actions workflow (CI) which automation is not accessible to downstream contributors. By default, this produces three executables for each Ziti component, one for each platform architecture: amd64, arm, arm64. You may instead build for one or more of these by specifying the architecture as a parameter to the `docker run` command as shown below. - -#### Build the Container Image - -You only need to build the container image once unless you change the Dockerfile or `./linux-build.sh` (the container's entrypoint). +This repo contains several Go applications. The easiest way to build and install all to `${GOPATH}/bin` is: ```bash -# find the latest Go distribution's semver -LATEST_GOLANG=$(curl -sSfL "https://go.dev/VERSION?m=text" | /bin/grep -Po '^go(\s+)?\K\d+\.\d+\.\d+$') -# build a container image named "zitibuilder" with the Dockerfile in the top-level of this repo -docker build \ - --tag=zitibuilder \ - --file=Dockerfile.linux-build \ - --build-arg latest_golang=${LATEST_GOLANG} \ - --build-arg uid=$UID \ - --build-arg gid=$GID . +# build and install all apps +go install ./... ``` -#### Run the Container to Build Executables for the Desired Architectures - -Executing the following `docker run` command will: -1. Mount the top-level of this repo on the container's `/mnt` -2. Run `./linux-build.sh ${@}` inside the container -3. Deposit built executables in `./release` +If you add `${GOPATH}/bin` to your executable search `${PATH}` then you may immediately run the newly-built binaries. For example, ```bash -# build for all three architectures: amd64 arm arm64 -docker run \ - --rm \ - --name=zitibuilder \ - --volume=$PWD:/mnt \ - zitibuilder - -# build only amd64 -docker run \ - --rm \ - --name=zitibuilder \ - --volume=$PWD:/mnt \ - zitibuilder \ - amd64 +$ ziti-controller version +v0.0.0 ``` -You will find the built artifacts in `./release`. +The remainder of this article will assume you have installed all apps to be available in your `PATH`. + +## Build Applications Individually + +### `ziti` CLI ```bash -$ tree ./release -./release -├── amd64 -│   └── linux -│   ├── ziti -│   ├── ziti-controller -│   ├── ziti-router -│   └── ziti-tunnel -├── arm -│   └── linux -│   ├── ziti -│   ├── ziti-controller -│   ├── ziti-router -│   └── ziti-tunnel -└── arm64 - └── linux - ├── ziti - ├── ziti-controller - ├── ziti-router - └── ziti-tunnel +# build the binary without installing in GOPATH +go build -o ./build/ziti ./ziti/cmd/ziti/ +# execute the binary +./build/ziti version ``` -### Initializing the Controller -Before you can run the controller you have to initialize it's database with an administrative user. Assuming you want to run with the edge enabled, this can be done using as follows: +### `ziti-controller` ```bash -ziti-controller edge init etc/ctrl.with.edge.yml -u -p +# build the binary without installing in GOPATH +go build -o ./build/ziti-controller ./ziti-controller/ +# execute the binary +./build/ziti-controller version ``` -Example: +### `ziti-router` ```bash -ziti-controller edge init etc/ctrl.with.edge.yml -u admin -p o93wjh5n +# build the binary without installing in GOPATH +go build -o ./build/ziti-router ./ziti-router/ +# execute the binary +./build/ziti-router version ``` -### Starting the Controller +## Run a Local Ziti Stack -If you wish to start the controller with the Ziti Fabric and Ziti Edge enabled: +Let's get a local Ziti stack up and running now that you have built and installed all the Ziti apps in this repo. + +### Initialize the Go Workspace + +This is optional. You may skip initializing a Go workspace if you use release builds from other Go modules that this project depends upon e.g. `openziti/edge`, `openziti/fabric`. + +A Go workspace is the best way to use the checked out copy of other modules' source instead of downloading releases from GitHub. + +For each Ziti module you wish to develop (modify) you will need to add it to your workspace. + +For this example, we'll only add the `edge` module. ```bash -ziti-controller run etc/ctrl.with.edge.yml +go work init +go work use . +go work use ../edge # assumes openziti/edge is checked out in sibling dir "edge" ``` -If you wish to start the Ziti Fabric standalone: +This produces a `go.work` file. ```bash -ziti-controller run etc/ctrl.yml +$ cat go.work +go 1.19 + +use ( + . + ../edge +) ``` -Please note that if you start the controller without the Ziti Edge enabled, the Ziti SDK, and edge router functionality -will not be usable. The controller can be started and stopped both ways without issue. - -### Starting Routers - -The Ziti Fabric requires at least one router (fabric router or edge router). There are four predefined configuration files -for running routers in `etc/` named `001.yml` to `004.yml`. - -Each configuration file refers to certificate and private keys kept in `etc/ca/intermediate/certs` and -`etc/ca/intermediate/private/`. The steps for starting the router is to first register the router then -start it. - -Register: - -```bash -ziti-fabric create router etc/ca/intermediate/certs/XXX-client.cert.pem -``` - -Where `XXX` is replaced with `001` through `004`. - -Run: - -```bash -ziti-router run etc/XXX.yml -``` - -Where `XXX` is replaced with `001` through `004`. - -### Starting Router As An Edge Router - -Edge routers are routers that have the Edge functionality enabled and allow Ziti SDK enabled application to connect to -Ziti. Starting an edge eouter requires that the controller be running with the Edge functionality -enabled. This requires the use of the `ctrl.with.edge.yml` configuration to run the controller (see example above). - -To start an edge router the Edge REST API will be used to prime the enrollment process and the -`ziti-router enroll` command will be used to finalize the process. The enrollment command will handle adding the fabric -and edge router entries necessary. Using the `ziti-fabric create router` command should not and can not be run. - - -There is only one example configuration file for an edge router: -`etc/edge.router.yml`. Additional configuration files can be created by copying and altering the -file. Specifically the identity section needs to point to unique file locations that do not collide with other identity -file and the listening ports need to not be in use. - -### Authenticate w/ the Ziti Edge API - -Please note that this is not a complete API reference and all of these request have analogous commands in the Ziti CLI via the `ziti` binary. - -```http -POST /authenticate?method=password -``` - -```json -{ - "username": "admin", - "password": "admin" -} -``` - -Authentication will return a session token that should be supplied either as a cookie (also returned) or a HTTP header -called `zt-session`. All subsequent requests will either need to set the HTTP set `zt-session` or provide the cookie in -every request. - -### Create An Edge Router - -```http -POST /edge-routers -``` - -```json -{ - "name": "My Edge Router", -} -``` - -### Retrieve the Edge Router Enrollment Token - -```http -GET /edge-routers/ -``` - -...where `id` is provided in the response to creating an edge router. It can be re-retrieved by listing the existing -edge routers via `GET /edge-routers`. The response from retrieving a edge router should contain an enrollment JWT in the -`enrollmentJwt` field. Retain the enrollment JWT in a text file named `enrollment.jwt`. - -### Enroll the Edge Router - -```bash -ziti-router enroll --jwt etc/edge.router.yml -``` - -...where `path to enrollment.jwt` is the enrollment JWT for the edge router. - -### Start Ziti Edge Router - -```bash -ziti-router run etc/edge.router.yml -``` +You will need to be aware of the checked out revision in each module because it is used to satisfy imports at a higher precedence than pinned versions in `go.mod`. That is, you may change the version of `edge` that is imported by this module at build time by checking out a different version in the adjacent `edge` repo. ## Further Exploration -At this point the controller should be running with some number of routers running. It is now possible -to explore the Ziti Fabric capabilities via the `ziti-fabric` executable. - -If the controller was started with the Edge functionality enabled the Ziti Edge API can be explored. A POSTMAN collection -can be found in `github.com/openziti/edge/controller/postman` and the Ziti SDK can be found in -`netfoundry/sdk-golang`. Additionally the `ziti-enroller` and `ziti-tunnel` command in this repository contain reference implementations. +Continue your OpenZiti exploration in [the next article about running an OpenZiti stack locally for development](./003-local-deploy.md). diff --git a/doc/003-local-deploy.md b/doc/003-local-deploy.md index 6128be466..5b0e16d15 100644 --- a/doc/003-local-deploy.md +++ b/doc/003-local-deploy.md @@ -1,503 +1,117 @@ # Overview -This document covers how to deploy Ziti from the ground up on a single local machine. After following this guide, it -should be possible to extrapolate the setup to multiple machines. This setup includes both the Fabric and optional -Edge components: +This local deployment README guides you to set up a running local Ziti stack. If you have not already built the apps in this repo you may go back to [the previous tutorial about getting set up for local development](./002-local-dev.md) for build instructions. The remainder of the tutorial will assume you have installed all the apps so they can be found in your shell's executable search `PATH`. -- 1x Ziti Controller + Edge -- 1x Ziti Edge Router -- 1x Ziti Router -- 1x Ziti Tunneler -- 1x Ziti Service (a demo netcat service) +You will configure and run: -It will also include provisioning and running a Ziti Tunneler with a demo netcat service. The services will use Ziti -router egress. The full connection will be: +- `ziti-controller` with the provided demo certificate authority in `./etc/ca` +- `ziti-router` as an edge router - SDK -> Edge Router -> Router -> Service +## A Note About Windows -It is also possible to host a service and thus avoid egress through a router: +These commands require a running BASH shell. Windows users will need to use WSL, [cygwin](https://www.cygwin.com/), a Linux virtual machine, or some other environment that supports BASH. The easiest thing might just be to use the shell that comes with [git bashfor windows](https://gitforwindows.org/). WSL is maturing more and more: [Mintty and WSL](https://github.com/mintty/wsltty). - Client SDK -> Edge Router -> Routers (0...1) -> Edge Router -> Server SDK +Also note that commands for `ziti`, `ziti-controller`, and `ziti-router` may need to have the `.exe` suffix appended to the example commands. -This document will guide the former. +## Initialize the Environment -For binaries, this guide provides instructions to build them for your local environment. It is also possible to acquire -pre-built binaries from the [NetFoundry Artifactory repository](https://netfoundry.jfrog.io/netfoundry/webapp/#/artifacts/browse/tree/General/ziti-release/ziti-all) -which does require a NetFoundry login. Extract the contents an use the binaries for your platform - ensuring that they -are on your path. +The remainder of this local development tutorital will instruct you to run terminal commands with current working directory of the top-level of this checked-out repo. The generated configuration files will use filesystem paths that are relative to this directory. -## Build Requirements +Go ahead and create a `./db` directory. Git is configured to ignore this directory and it will house the tutorial files. You may delete this directory to reset the tutorial. -If building your own binaries +```bash +mkdir -p ./db +``` -- A Golang environment (1.12 or later) -- A NetFoundry email address tied to a Bitbucket account with SSH keys +## Initialize the Controller -## Quick steps to a Building Binaries +Before you can run the controller will initialize its configuration and database. We'll use the demo CA that's checked in to this repo in `./etc/ca`. -It is not possible to simply use `go get bitbucket.org/netfoundry/ziti` as `go get` does not support specifying an -identity file (i.e. SSH keys). Instead the repo must first be retrieved by `git clone`. +```bash +ZITI_HOME=. \ +ZITI_CTRL_LISTENER_ADDRESS=127.0.0.1 \ +ZITI_CTRL_EDGE_LISTENER_HOST_PORT=127.0.0.1:1280 \ +ZITI_EDGE_CTRL_ADVERTISED_HOST_PORT=127.0.0.1:1280 \ +ZITI_CTRL_IDENTITY_CERT=./etc/ca/intermediate/certs/ctrl-client.cert.pem \ +ZITI_CTRL_IDENTITY_SERVER_CERT=./etc/ca/intermediate/certs/ctrl-server.cert.pem \ +ZITI_CTRL_IDENTITY_KEY=./etc/ca/intermediate/private/ctrl.key.pem \ +ZITI_CTRL_IDENTITY_CA=./etc/ca/intermediate/certs/ca-chain.cert.pem \ +ZITI_SIGNING_CERT=./etc/ca/intermediate/certs/intermediate.cert.pem \ +ZITI_SIGNING_KEY=./etc/ca/intermediate/private/intermediate.key.decrypted.pem \ + ziti create config controller \ + --output ./db/ctrl-config.yml +``` -### Linux/MacOS +```bash +ziti-controller edge init ./db/ctrl-config.yml -u ADMIN_NAME -p ADMIN_PW +``` - repo_dir=~/repos/nf - mkdir ${repo_dir} - cd ${repo_dir} - git clone git@bitbucket.org:netfoundry/ziti.git - cd ziti - export GOPATH=$(pwd)/build - go install ./fabric/... ./edge/... ./cli/... +## Run the Controller -### Windows +Edge SDKs will connect to the running controller to authenticate and request a session. Leave the controller running in a terminal so that you may inspect the log messages. - set repo_dir=%userprofile%\repos\nf - mkdir %repo_dir% - cd /d %repo_dir% - git clone git@bitbucket.org:netfoundry/ziti.git - cd /d %repo_dir%\ziti - set GOPATH=%cd%\build - go install ./fabric/... ./edge/... ./cli/... +```bash +ziti-controller run ./db/ctrl-config.yml +``` -After you have cloned your repository and ensured it can build, change to $GOPATH or -%GOPATH% and execute `bin/ziti`. If everything is working properly you should be greeted -with the ziti command line help. +## Login to the Controller -## Setting up your first environment +You will need a new terminal with current directory set to the top-level of this repo.This login step will save a session token in the `ziti` CLI's configuration cache. -Now that you have ziti cloned and compiling, the next step is to get your very first -environment running. These steps will bring you through setting up your first environment -with ziti. We will: +```bash +ziti edge login -u ADMIN_NAME -p ADMIN_PW +``` -- [Requirements](#Requirements) -- [Establish Environment Variables](#Establish-Environment-Variables) -- [Create A Certificate Authority](#Create A Certificate Authority) -- [Configure & Run A Ziti Controller](#Configure-&-Run-A-Ziti-Controller) -- [Configure & Run A Ziti Router](#Configure-&-Run-A-Ziti-Router) -- [Configure & Run A Ziti Edge Router](#Configure-&-Run-A-Ziti-Edge-Router) -- [Configure A Service & Ziti Tunneler](#Configure-A-Service-&-Ziti-Tunneler) -- [Configuring a hosted service](#Configuring-A-Hosted-Service) +Subsequent `ziti` CLI commands will automatically re-use this session token. You'll need to perform this login step again when the token expires. -## Requirements +## Initialize an Edge Router -### Required Tooling +Request an enrollment token from the controller for router01. -- A bash shell -- nc (netcat) +```bash +ziti edge create edge-router router01 \ + --jwt-output-file /tmp/router01.jwt \ + --tunneler-enabled +``` -### A note on Windows +Generate a configuration file for router01. -These commands all require a running bash shell. Windows users this means you'll need to use -WSL, [cygwin](https://www.cygwin.com/), a Linux virtual machine, or some other environment that supports a bash compliant -shell. The easiest thing might just be to use the shell that comes with [git bashfor windows](https://gitforwindows.org/). -WSL is maturing more and more: [Mintty and WSL](https://github.com/mintty/wsltty). +```bash +ZITI_HOME=./db \ +ZITI_CTRL_ADVERTISED_ADDRESS=127.0.0.1 \ +ZITI_EDGE_ROUTER_RAWNAME=localhost \ + ziti create config router edge \ + --routerName router01 \ + --output ./db/router01-config.yml +``` -Also note that commands for `ziti`, `ziti-fabric`, `ziti-controller`, and `ziti-router` may need to have the `.exe` -suffix added into the command provided in this document. +Enroll router01 by presenting the token to the controller to receive a certificate in the filesystem location specified in the configuration file. -### Hosts File +```bash +ziti-router enroll --jwt /tmp/router01.jwt ./db/router01-config.yml +``` -This document assumes that the following hostnames will resolve on your local system: +## Run the Edge Router -- up-and-running-ctrl.ziti.netfoundry.io -- up-and-running-er01.ziti.netfoundry.io -- up-and-running-r01.ziti.netfoundry.io +Edge SDKs will connect to the running edge router to connect to services. Leave the router process running in a terminal so you can monitor the log messages while you continue the tutorial in a new terminal. -This means that temporarily adding these to your system hosts file (outlined below) is required for this guide. +```bash +ziti-router run ./db/router01-config.yml +``` -- Windows: `windows: %windir%\system32\drivers\etc\hosts` -- Linux: `/etc/hosts` +## Create Your First Service - 127.0.0.1 up-and-running-ctrl.ziti.netfoundry.io - 127.0.0.1 up-and-running-er01.ziti.netfoundry.io - 127.0.0.1 up-and-running-r01.ziti.netfoundry.io +A service is an entity that stores metadata about a server application. The `ziti` CLI has an interactive tutorial to step you through creating your first service. -If you are deploying on multiple machines with their own resolvable hostnames, this is not required. However, it will -be necessary to alter the Environment Variable DNS San values to match your environment. Also, all generated Ziti -Identities (server, client, and private keys), configuration files, and binaries will need to be copied to the correct -hosts. +When prompted, select your running edge router `router01`. -## Establish Environment Variables +```bash +ziti edge tutorial first-service +``` -The environment variables ZITI_HOME and ZITI_NETWORK will be used to boostrap an environment configuration file and -directory structure to hold the various certificate, private keys, configuration files, and enrollment tokens that will -be generated in this guide. This will help keep them separated on your file system for easy deletion later. +If you prefer, you may read [the first-service tutorial as a web site](../ziti/cmd/ziti/cmd/tutorial/tutorials/first-service.md) -After these are defined an environment folder and 'env' file will be generated that can easily reset these values. +## Further Exploration -1. Define the boot strap environment variables - - export ZITI_NETWORK=up-and-running - export ZITI_HOME=~/.ziti - - For Windows users: if a bash shell is being used some absolute paths may not work (i.e. /mnt/c/myziti). Using paths -that start with `~` are generally safer. Using `.` will make configuration files and `env` files sensitive to the -current working directory, but should work as long as the correct current working directory is maintained. - -1. Generate the base directory structure and `env` file - - mkdir -p $ZITI_HOME - - echo -e "export ZITI_HOME=${ZITI_HOME}\n\ - export ZITI_NETWORK=${ZITI_NETWORK}\n\ - export ZITI_ID=\"\${ZITI_HOME}/identities.yml\"\n\ - export ZITI_CA_NAME=\"\${ZITI_NETWORK}\"\n\ - export ZITI_PKI=\"\${ZITI_HOME}/pki\"\n\ - export ZITI_CA_FILE=\"\${ZITI_PKI}/\${ZITI_CA_NAME}/certs/\${ZITI_CA_NAME}.cert\"\n\ - export ZITI_CTRL_HOSTNAME=\"\${ZITI_NETWORK}-ctrl.ziti.netfoundry.io\"\n\ - export ZITI_ER01_HOSTNAME=\"\${ZITI_NETWORK}-er01.ziti.netfoundry.io\"\n\ - export ZITI_R01_HOSTNAME=\"\${ZITI_NETWORK}-r01.ziti.netfoundry.io\"\n\ - export ZITI_EDGE_API_PORT=1280\n\ - export ZITI_EDGE_API_HOSTNAME=\"\${ZITI_CTRL_HOSTNAME}:\${ZITI_EDGE_API_PORT}\"\n\ - mkdir -p \$ZITI_HOME/db - mkdir -p \$ZITI_PKI - " > ${ZITI_HOME}/env - - This file generated by the above snippet can be sourced any time to switch between working with multiple environments - generated by this document or when starting new terminal windows. - - Source the newly created `env` file: `source ${ZITI_HOME}/env` or if the defaults were used `source .ziti/env` - - - `ZITI_HOME` - The root directory that should be consider the "HOME" directory (defaults to ~ if not set) - - `ZITI_NETWORK` - The name of the network being worked with, this value is used as the basis for other file names. Should not contain spaces - - `ZITI_PKI` - The location of the PKI used by `ziti pki` via the `--pki-root` option - - `ZITI_CA_NAME` - The name of the signing CA that will be used for certificate generation and controller configuration. Defaults to the name of the network. - - `ZITI_CA_FILE` - Location of the CA signing cert for ease of use using `ziti` CLI commands - - `ZITI_CTRL_HOSTNAME` - DNS SANs for controller certificate generation, should match hosts file changes - - `ZITI_ER01_HOSTNAME` - DNS SANs for edge router configuration, should match hosts file changes - - `ZITI_R01_HOSTNAME` - DNS SANs for router certificate generation, should match hosts file changes - - `ZITI_EDGE_API_PORT` - The port the Edge API will be available on - - `ZITI_EDGE_API_HOSTNAME` - The hostname/port combination for the Ziti Edge API, used with `ziti edge controller` commands - -## Create A Certificate Authority - -All communication between Ziti components is secured using mutual TLS. In order to get a ziti environment running a -certificate authority is required. This document guides the reader through creating a Root Certificate Authority -(Root CA). It does not cover setups that should utilize Intermediate Certificate Authorities for production environments. - -The `ziti` CLI will be significantly streamline and reduce the prerequisite knowledge required to generate -a Root CA and signed certificates for client and server usage. Specifically the `ziti pki` command do most of the heavy -lifting. - -1. Ensure that the `env` file is sourced if you are using a new terminal. - -1. Create the CA - - ziti pki create ca --pki-root="${ZITI_PKI}" --ca-file="${ZITI_CA_NAME}" - - Additional certificate common name and subject fields can be set as needed. Run `ziti pki create ca -h` for options. - -1. (Optional) Verify the output - - ls -l $ZITI_PKI/$ZITI_CA_NAME - - Example: - - total 0 - drwxr-xr-x 1 cd cd 512 Jan 28 16:39 certs - drwx------ 1 cd cd 512 Jan 28 16:39 crls - drwx------ 1 cd cd 512 Jan 28 16:39 keys - -rw-r--r-- 1 cd cd 3 Jan 28 16:39 crlnumber - -rw-r--r-- 1 cd cd 162 Jan 28 16:39 index.txt - -rw-r--r-- 1 cd cd 20 Jan 28 16:39 index.txt.attr - -rw-r--r-- 1 cd cd 3 Jan 28 16:39 serial - -## Configure-&-Run-A-Ziti-Controller - -The following steps outline how to configure and start the Ziti Controller. - -1. Ensure that the `env` file is sourced if you are using a new terminal. - -1. Generate the controller Ziti Identity (server, client, and private key) - - Server - - ziti pki create server --pki-root=$ZITI_PKI --ca-name $ZITI_CA_NAME \ - --server-file "${ZITI_NETWORK}-ctrl-server" \ - --dns "${ZITI_CTRL_HOSTNAME}" --ip "127.0.0.1" \ - --server-name "${ZITI_NETWORK} Controller" - - Client - - ziti pki create client --pki-root=$ZITI_PKI --ca-name ${ZITI_CA_NAME} \ - --client-file "${ZITI_NETWORK}-ctrl-client" \ - --key-file "${ZITI_NETWORK}-ctrl-server" \ - --client-name "${ZITI_NETWORK} Controller" - - Note: The client cert uses the controller server key as specified by `--key-file`. - - Additional certificate common name and subject fields can be set as needed. Run `ziti pki create server -h` or - `ziti pki create client -h` for options. - - The Ziti Identity files are output in the following locations - - $ZITI_PKI/$ZITI_CA_NAME/certs/${ZITI_NETWORK}-ctrl-server.cert - $ZITI_PKI/$ZITI_CA_NAME/certs/${ZITI_NETWORK}-ctrl-client.cert - $ZITI_PKI/$ZITI_CA_NAME/keys/${ZITI_NETWORK}-ctrl-server.key - -1. Generate the controller configuration file - - echo " - v: 3 - db: $ZITI_HOME/db/ctrl.db - - identity: - cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-ctrl-client.cert - server_cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-ctrl-server.cert - key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}-ctrl-server.key - ca: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}.cert - - ctrl: - listener: tls:127.0.0.1:6262 - - mgmt: - listener: tls:127.0.0.1:10000 - edge: - api: - listener: 0.0.0.0:1280 - advertise: ${ZITI_EDGE_API_HOSTNAME} - sessionTimeoutMinutes: 30 - enrollment: - signingCert: - cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}.cert - key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}.key - edgeIdentity: - durationMinutes: 5 - edgeRouter: - durationMinutes: 5 - " > $ZITI_HOME/controller.yaml - -1. Initialize the database if this is the first time you are going to start the controller - - # if needed, initialize the controller - ziti-controller edge init $ZITI_HOME/controller.yaml -u admin -p admin - - # run the controller - ziti-controller run $ZITI_HOME/controller.yaml - - Note that running this command will commandeer your current terminal. Use `screen` or multiple terminals by using - `source` on the `env` file. - -## Configure & Run A Ziti Router - -This section outlines the steps necessary to configure and connect a router to the Ziti Controller. The router will be -named `r01` which is represented in the Common Name field of the certificates for the router. Routers join a controller -and create a mesh to provide long-haul transport. - -To enroll a Ziti Router, the command line utility `ziti-fabric` will be used that requires its own Ziti Identity in order -to connect to and control the fabric. - -To configure more routers, repeat steps 3+ from below but be sure to - -- alter the `--server-name`, `--client-name`, and `--dns` parameters in all commands -- update the hosts file with any new hostnames - -1. The `ziti-fabric` command will be used to manage the fabric, a Ziti Identity must be generated to do that: - - ziti pki create client --pki-root="${ZITI_PKI}" --ca-name="${ZITI_CA_NAME}" \ - --client-file="${ZITI_NETWORK}-dotzeet" \ - --client-name "${ZITI_NETWORK} Management" - -1. Generate an `identities.json` file that references the Ziti Identity: - - echo " - --- - default: - caCert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}.cert - cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-dotzeet.cert - key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}-dotzeet.key - endpoint: tls:127.0.0.1:10000 - " > $ZITI_HOME/identities.yml - -1. Verify the identity works: - - ziti-fabric list routers - - Note: If 127.0.0.1 was not included in the controller cert, use the `-e` flag to set the address to the controller - (`ziti-fabric -e "tls:up-and-running-ctrl.ziti.netfoundry.io:10000" list routers` ) on this an all future - `ziti-fabric` command. - -1. Generate the Ziti Router identity - - Server - - ziti pki create server --pki-root=$ZITI_PKI --ca-name ${ZITI_CA_NAME} \ - --server-file "${ZITI_NETWORK}-r01-server" \ - --dns "${ZITI_R01_HOSTNAME}" --ip 127.0.0.1 \ - --server-name r01 - - Client - - ziti pki create client --pki-root=$ZITI_PKI --ca-name ${ZITI_CA_NAME} \ - --client-file "${ZITI_NETWORK}-r01-client" \ - --key-file "${ZITI_NETWORK}-r01-server" \ - --client-name r01 - -1. Generate the router configuration file: - - echo "v: 2 - - identity: - cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-r01-client.cert - server_cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-r01-server.cert - key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}-r01-server.key - ca: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-r01-server.chain.pem - - ctrl: - endpoint: tls:${ZITI_CTRL_HOSTNAME}:6262 - - link: - listener: quic:127.0.0.1:6002 - - listeners: - - binding: transport - address: tls:0.0.0.0:7002 - " > $ZITI_HOME/r01.yaml - -1. Enroll the Ziti Router identity with the controller - - ziti-fabric create router "${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-r01-client.cert" - - Verify: - - ziti-fabric list routers - - Should show 1 router named `r01`. - -1. Start the router: - - ziti-router run $ZITI_HOME/r01.yaml - - Note that running this command will commandeer your current terminal. Use `screen` or multiple terminals by using - `source` on the `env` file. - -## Configure & Run A Ziti Edge Router - -A Ziti Edge Router allows the Ziti SDK to ingress to a Ziti overlay network. A Ziti Edge Router is a Ziti Router that has the `edge` -section of the configuration defined and has gone through the Edge Router Enrollment process instead of the Ziti Router -enrollment process. Ziti Edge Routers and Ziti Routers are run from the same binary `ziti-router`. - -Ensure that the `env` file is sourced if you are using a new terminal. - -1. Authenticate w/ the controller if not authenticated - - #update username / password if the default admin password has been updated - ziti edge controller login ${ZITI_EDGE_API_HOSTNAME} -u admin -p admin -c ${ZITI_CA_FILE} - -1. Create a cluster - - ziti edge controller create cluster cluster01 - -1. Create a edge router and output the JWT to a file: - - ziti edge controller create edge-router er01 cluster01 -o $ZITI_HOME/er01.jwt - -1. Create the edge router configuration file - - echo " - v: 2 - - identity: - cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-er01-client.cert - server_cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-er01-server.cert - key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}-er01-server.key - ca: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-er01-server.chain.cert - - ctrl: - endpoint: tls:${ZITI_CTRL_HOSTNAME}:6262 - - edge: - csr: - country: US - province: NC - locality: Charlotte - organization: NetFoundry - organizationalUnit: Ziti - sans: - dns: - - ${ZITI_NETWORK}-er01.ziti.netfoundry.io - ip: - - "127.0.0.1" - - dialers: - - binding: udp - - binding: transport - - listeners: - - binding: edge - address: tls:0.0.0.0:3022 - options: - advertise: ${ZITI_NETWORK}-er01.ziti.netfoundry.io:3022 - - binding: transport - address: tls:0.0.0.0:7099 - " > $ZITI_HOME/er01.yaml - -1. Complete the enrollment process with the controller - - ziti-router enroll $ZITI_HOME/er01.yaml --jwt $ZITI_HOME/er01.jwt - -1. Start the edge router: - - ziti-router run $ZITI_HOME/er01.yaml - - Note that running this command will commandeer your current terminal. Use `screen` or multiple terminals by using - `source` on the `env` file. - -## Configure A Service & Ziti Tunneler - -1. Authenticate w/ the controller if not authenticated - - #update username / password if the default admin password has been updated - ziti edge controller login ${ZITI_EDGE_API_HOSTNAME} -u admin -p admin -c ${ZITI_CA_FILE} - -1. Create a service that will facilitate connecting to a local netcat server listening on port 7256 and that egresses -the Ziti Fabric on our "r01" router - - ziti edge controller create service netcat7256 localhost 7256 r01 tcp://localhost:7256 - -1. Create a Ziti Edge Identity for the Ziti Tunneler process - - ziti edge controller create identity device identity01 -o $ZITI_HOME/identity01.jwt - -1. Create an AppWan to associate the Ziti Tunneler identity (identity01) to the service (netcat7256) - - ziti edge controller create app-wan appwan01 -s netcat7256 -i identity01 - -1. Enroll the Ziti Tunneler's identity - - ziti-enroller --jwt $ZITI_HOME/identity01.jwt -o $ZITI_HOME/identity01.json - -1. Start the Ziti Tunneler in proxy mode - - ziti-tunnel proxy netcat7256:8145 -i $ZITI_HOME/identity01.json - -1. Start the netcat server - - nc -k -n 127.0.0.1 -l 7256 - -1. Start the netcat client that will connect to the Ziti Tunnel proxy - - nc -v 127.0.0.1 8145 - -## Configuring A Hosted Service - -Services can also be hosted by another SDK. For this to work a second Ziti Tunneler can be setup to act as the host. The -exact details of this are beyond this document but the high level steps are outlined below: - -1. Create a new Ziti Identity via `ziti edge controller identity create` to allow another Ziti Tunneler to run -1. Enroll the Ziti Identitiy via `ziti-enroller` -1. Add the new Ziti Identity to the hosts of a new service or an existing service -1. Start the new Ziti Tunneler - -Example Hosted Service - - ziti edge controller create service \ - --hosted - --hosted-ids - --tags tunneler.dial.addr=
- -Example: - - ziti edge controller create service postgresql pg 5432 \- - --hosted - --hosted-ids 40c025cb-bc92-4a54-b55f-1429412f2644 - -tags tunneler.dial.addr=tcp:127.0.0.1:5432 +- The [Go SDK examples](https://github.com/openziti/sdk-golang/tree/main/example#readme) illustrate embedding OpenZiti in both client and server applications. +- You may wish to [know more about controller PKI](./004-controller-pki.md). diff --git a/doc/004-controller-pki.md b/doc/004-controller-pki.md new file mode 100644 index 000000000..3cad1a0d7 --- /dev/null +++ b/doc/004-controller-pki.md @@ -0,0 +1,414 @@ +# Overview + +This tutorial covers composing the controller PKI and minimal controller and router configs from scratch. [The previous tutorial](./003-local-deploy.md) guided you to run a controller with the demo PKI checked in to this repo under `./etc/ca` and with annotated and complete controller and router configs generated with the `ziti create config` command. + +You will configure: + +- 1x Ziti Controller + Edge +- 1x Ziti Fabric Router +- 1x Ziti Edge Router +- 1x Ziti Tunneler +- 1x Ziti Service (a demo netcat service) + +It will also include provisioning and running a Ziti Tunneler with a demo netcat service. The services will use Ziti +router egress. The full connection will be: + + SDK -> Edge Router -> Router -> Service + +## A Note About Windows + +These commands require a running BASH shell. Windows users will need to use WSL, [cygwin](https://www.cygwin.com/), a Linux virtual machine, or some other environment that supports BASH. The easiest thing might just be to use the shell that comes with [git bashfor windows](https://gitforwindows.org/). WSL is maturing more and more: [Mintty and WSL](https://github.com/mintty/wsltty). + +Also note that commands for `ziti`, `ziti-controller`, and `ziti-router` may need to have the `.exe` suffix appended to the example commands. + +## Hosts File + +This document assumes that the following hostnames will resolve on your local system: + +- up-and-running-ctrl.ziti.netfoundry.io +- up-and-running-er01.ziti.netfoundry.io +- up-and-running-r01.ziti.netfoundry.io + +This means that temporarily adding these to your system hosts file (outlined below) is required for this guide. + +- Windows: `windows: %windir%\system32\drivers\etc\hosts` +- Linux: `/etc/hosts` + + 127.0.0.1 up-and-running-ctrl.ziti.netfoundry.io + 127.0.0.1 up-and-running-er01.ziti.netfoundry.io + 127.0.0.1 up-and-running-r01.ziti.netfoundry.io + +If you are deploying on multiple machines with their own resolvable hostnames, this is not required. However, it will +be necessary to alter the Environment Variable DNS San values to match your environment. Also, all generated Ziti +Identities (server, client, and private keys), configuration files, and binaries will need to be copied to the correct +hosts. + +## Establish Environment Variables + +The environment variables ZITI_HOME and ZITI_NETWORK will be used to boostrap an environment configuration file and directory structure to hold the various certificate, private keys, configuration files, and enrollment tokens that will be generated in this guide. This will help keep them separated on your file system for easy deletion later. + +After these are defined an environment folder and 'env' file will be generated that can easily reset these values. + +1. Define the boot strap environment variables + + ```bash + export ZITI_NETWORK=up-and-running + export ZITI_HOME=~/.ziti + ``` + + For Windows users: if a bash shell is being used some absolute paths may not work (i.e. /mnt/c/myziti). Using paths that start with `~` are generally safer. Using `.` will make configuration files and `env` files sensitive to the current working directory, but should work as long as the correct current working directory is maintained. + +1. Generate the base directory structure and `env` file + + ```bash + mkdir -p $ZITI_HOME + + cat < ${ZITI_HOME}/env + export ZITI_HOME=${ZITI_HOME} + export ZITI_NETWORK=${ZITI_NETWORK} + export ZITI_ID="${ZITI_HOME}/identities.yml" + export ZITI_CA_NAME="${ZITI_NETWORK}" + export ZITI_PKI="${ZITI_HOME}/pki" + export ZITI_CA_FILE="${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_CA_NAME}.cert" + export ZITI_CTRL_HOSTNAME="${ZITI_NETWORK}-ctrl.ziti.netfoundry.io" + export ZITI_ER01_HOSTNAME="${ZITI_NETWORK}-er01.ziti.netfoundry.io" + export ZITI_R01_HOSTNAME="${ZITI_NETWORK}-r01.ziti.netfoundry.io" + export ZITI_EDGE_API_PORT=1280 + export ZITI_EDGE_API_HOSTNAME="${ZITI_CTRL_HOSTNAME}:${ZITI_EDGE_API_PORT}" + mkdir -p $ZITI_HOME/db + mkdir -p $ZITI_PKI + SHELL + ``` + + This file generated by the above snippet can be sourced any time to switch between working with multiple environments + generated by this document or when starting new terminal windows. + + Source the newly created `env` file: `source ${ZITI_HOME}/env` or if the defaults were used `source .ziti/env` + + - `ZITI_HOME` - The root directory that should be consider the "HOME" directory (defaults to ~ if not set) + - `ZITI_NETWORK` - The name of the network being worked with, this value is used as the basis for other file names. Should not contain spaces + - `ZITI_PKI` - The location of the PKI used by `ziti pki` via the `--pki-root` option + - `ZITI_CA_NAME` - The name of the signing CA that will be used for certificate generation and controller configuration. Defaults to the name of the network. + - `ZITI_CA_FILE` - Location of the CA signing cert for ease of use using `ziti` CLI commands + - `ZITI_CTRL_HOSTNAME` - DNS SANs for controller certificate generation, should match hosts file changes + - `ZITI_ER01_HOSTNAME` - DNS SANs for edge router configuration, should match hosts file changes + - `ZITI_R01_HOSTNAME` - DNS SANs for router certificate generation, should match hosts file changes + - `ZITI_EDGE_API_PORT` - The port the Edge API will be available on + - `ZITI_EDGE_API_HOSTNAME` - The hostname/port combination for the Ziti Edge API, used with `ziti edge` commands + +## Create A Certificate Authority + +All communication between Ziti components is secured using mutual TLS. In order to get a ziti environment running a certificate authority is required. This document guides the reader through creating a Root Certificate Authority (Root CA). It does not cover setups that should utilize Intermediate Certificate Authorities for production environments. + +The `ziti` CLI will be significantly streamline and reduce the prerequisite knowledge required to generate a Root CA and signed certificates for client and server usage. Specifically the `ziti pki` command will do most of the heavy lifting. + +1. Ensure that the `env` file is sourced if you are using a new terminal. + +1. Create the CA + + ```bash + ziti pki create ca --pki-root="${ZITI_PKI}" --ca-file="${ZITI_CA_NAME}" + ``` + + Additional certificate common name and subject fields can be set as needed. Run `ziti pki create ca -h` for options. + +1. (Optional) Verify the output + + ```bash + ls -l $ZITI_PKI/$ZITI_CA_NAME + ``` + + Example: + + ```bash + total 0 + drwxr-xr-x 1 cd cd 512 Jan 28 16:39 certs + drwx------ 1 cd cd 512 Jan 28 16:39 crls + drwx------ 1 cd cd 512 Jan 28 16:39 keys + -rw-r--r-- 1 cd cd 3 Jan 28 16:39 crlnumber + -rw-r--r-- 1 cd cd 162 Jan 28 16:39 index.txt + -rw-r--r-- 1 cd cd 20 Jan 28 16:39 index.txt.attr + -rw-r--r-- 1 cd cd 3 Jan 28 16:39 serial + ``` + +## Configure and Run a Controller + +The following steps outline how to configure and start the Ziti Controller. + +1. Ensure that the `env` file is sourced if you are using a new terminal. + +1. Generate the controller Ziti Identity (server, client, and private key) + + Server + + ```bash + ziti pki create server \ + --pki-root=$ZITI_PKI \ + --ca-name $ZITI_CA_NAME \ + --server-file "${ZITI_NETWORK}-ctrl-server" \ + --dns "${ZITI_CTRL_HOSTNAME}" \ + --ip "127.0.0.1" \ + --server-name "${ZITI_NETWORK} Controller" + ``` + + Client + + ```bash + ziti pki create client \ + --pki-root=$ZITI_PKI \ + --ca-name ${ZITI_CA_NAME} \ + --client-file "${ZITI_NETWORK}-ctrl-client" \ + --key-file "${ZITI_NETWORK}-ctrl-server" \ + --client-name "${ZITI_NETWORK} Controller" + ``` + + Note: The client cert uses the controller server key as specified by `--key-file`. + + Additional certificate common name and subject fields can be set as needed. Run `ziti pki create server -h` or + `ziti pki create client -h` for options. + + The Ziti Identity files are output in the following locations + + ```bash + $ZITI_PKI/$ZITI_CA_NAME/certs/${ZITI_NETWORK}-ctrl-server.cert + $ZITI_PKI/$ZITI_CA_NAME/certs/${ZITI_NETWORK}-ctrl-client.cert + $ZITI_PKI/$ZITI_CA_NAME/keys/${ZITI_NETWORK}-ctrl-server.key + ``` + +1. Generate the controller configuration file + + ```bash + cat < $ZITI_HOME/controller.yaml + v: 3 + db: $ZITI_HOME/db/ctrl.db + + identity: + cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-ctrl-client.cert + server_cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-ctrl-server.cert + key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}-ctrl-server.key + ca: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}.cert + + ctrl: + listener: tls:127.0.0.1:6262 + + mgmt: + listener: tls:127.0.0.1:10000 + edge: + api: + listener: 0.0.0.0:1280 + advertise: ${ZITI_EDGE_API_HOSTNAME} + sessionTimeoutMinutes: 30 + enrollment: + signingCert: + cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}.cert + key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}.key + edgeIdentity: + durationMinutes: 5 + edgeRouter: + durationMinutes: 5 + YAML + ``` + +1. Initialize the database if this is the first time you are going to start the controller + + ```bash + # if needed, initialize the controller + ziti-controller edge init $ZITI_HOME/controller.yaml -u admin -p admin + + # run the controller + ziti-controller run $ZITI_HOME/controller.yaml + ``` + + Note that running this command will commandeer your current terminal. Use `screen` or multiple terminals by using + `source` on the `env` file. + +## Configure and Run a Fabric Router + +This section outlines the steps necessary to configure and connect a router to the Ziti Controller. The router will be +named `r01` which is represented in the Common Name field of the certificates for the router. Routers join a controller +and create a mesh to provide long-haul transport. + +To enroll a Ziti Router, the command line utility `ziti fabric` will be used that requires its own Ziti Identity in order +to connect to and control the fabric. + +1. The `ziti fabric` command will be used to manage the fabric, a Ziti Identity must be generated to do that: + + ```bash + ziti pki create client \ + --pki-root="${ZITI_PKI}" \ + --ca-name="${ZITI_CA_NAME}" \ + --client-file="${ZITI_NETWORK}-dotzeet" \ + --client-name "${ZITI_NETWORK} Management" + ``` + +1. Generate a fabric identity that references the Ziti Identity: + + ```bash + ziti fabric add-identity \ + --cli-identity "${ZITI_NETWORK} Management" \ + --ca-cert ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}.cert \ + --client-cert ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-dotzeet.cert \ + --client-key ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}-dotzeet.key + ``` + +1. Login + + ```bash + ziti edge login --cli-identity "${ZITI_NETWORK} Management" + ``` + +1. Verify the identity works: + + ```bash + ziti fabric list routers + ``` + +1. Generate the Ziti Router identity + + Server + + ```bash + ziti pki create server \ + --pki-root=$ZITI_PKI \ + --ca-name ${ZITI_CA_NAME} \ + --server-file "${ZITI_NETWORK}-r01-server" \ + --dns "${ZITI_R01_HOSTNAME}" \ + --ip 127.0.0.1 \ + --server-name r01 + ``` + + Client + + ```bash + ziti pki create client \ + --pki-root=$ZITI_PKI \ + --ca-name ${ZITI_CA_NAME} \ + --client-file "${ZITI_NETWORK}-r01-client" \ + --key-file "${ZITI_NETWORK}-r01-server" \ + --client-name r01 + ``` + +1. Generate the router configuration file: + + ```bash + cat < $ZITI_HOME/r01.yaml + v: 2 + + identity: + cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-r01-client.cert + server_cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-r01-server.cert + key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}-r01-server.key + ca: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-r01-server.chain.pem + + ctrl: + endpoint: tls:${ZITI_CTRL_HOSTNAME}:6262 + + link: + listener: quic:127.0.0.1:6002 + + listeners: + - binding: transport + address: tls:0.0.0.0:7002 + YAML + ``` + +1. Enroll the Ziti Router identity with the controller + + ```bash + ziti fabric create router "${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-r01-client.cert" + ``` + + Verify: + + ```bash + ziti fabric list routers + ``` + + Should show 1 router named `r01`. + +1. Start the router: + + ```bash + ziti-router run $ZITI_HOME/r01.yaml + ``` + + Note that running this command will commandeer your current terminal. Use `screen` or multiple terminals by using + `source` on the `env` file. + +## Configure and Run an Edge Router + +A Ziti Edge Router allows the Ziti SDK to ingress to a Ziti overlay network. A Ziti Edge Router is a Ziti Router that has the `edge` +section of the configuration defined and has gone through the Edge Router Enrollment process instead of the Ziti Router +enrollment process. Ziti Edge Routers and Ziti Routers are run from the same binary `ziti-router`. + +Ensure that the `env` file is sourced if you are using a new terminal. + +1. Authenticate w/ the controller if not authenticated + + ```bash + #update username / password if the default admin password has been updated + ziti edge login ${ZITI_EDGE_API_HOSTNAME} -u admin -p admin + ``` + +1. Create a edge router and output the JWT to a file: + + ```bash + ziti edge create edge-router er01 cluster01 -o $ZITI_HOME/er01.jwt + ``` + +1. Create the edge router configuration file + + ```bash + cat < $ZITI_HOME/er01.yaml + v: 2 + + identity: + cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-er01-client.cert + server_cert: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-er01-server.cert + key: ${ZITI_PKI}/${ZITI_CA_NAME}/keys/${ZITI_NETWORK}-er01-server.key + ca: ${ZITI_PKI}/${ZITI_CA_NAME}/certs/${ZITI_NETWORK}-er01-server.chain.cert + + ctrl: + endpoint: tls:${ZITI_CTRL_HOSTNAME}:6262 + + edge: + csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + sans: + dns: + - ${ZITI_NETWORK}-er01.ziti.netfoundry.io + ip: + - "127.0.0.1" + + dialers: + - binding: udp + - binding: transport + + listeners: + - binding: edge + address: tls:0.0.0.0:3022 + options: + advertise: ${ZITI_NETWORK}-er01.ziti.netfoundry.io:3022 + - binding: transport + address: tls:0.0.0.0:7099 + YAML + ``` + +1. Complete the enrollment process with the controller + + ```bash + ziti-router enroll $ZITI_HOME/er01.yaml --jwt $ZITI_HOME/er01.jwt + ``` + +1. Start the edge router: + + ```bash + ziti-router run $ZITI_HOME/er01.yaml + ``` + + Note that running this command will commandeer your current terminal. Use `screen` or multiple terminals by using + `source` on the `env` file. diff --git a/go.mod b/go.mod index 1b1ce8b8c..cbc74e96d 100644 --- a/go.mod +++ b/go.mod @@ -6,13 +6,11 @@ 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 github.com/blang/semver v3.5.1+incompatible github.com/fatih/color v1.13.0 github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa github.com/go-acme/lego/v4 v4.2.0 - github.com/go-openapi/runtime v0.24.1 + github.com/go-openapi/runtime v0.24.2 github.com/go-openapi/strfmt v0.21.3 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/protobuf v1.5.2 @@ -21,30 +19,30 @@ require ( github.com/jedib0t/go-pretty/v6 v6.4.0 github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 github.com/michaelquigley/pfxlog v0.6.9 - github.com/openziti/agent v1.0.4 - github.com/openziti/channel/v2 v2.0.9 - github.com/openziti/edge v0.24.12 - github.com/openziti/fabric v0.21.9 - github.com/openziti/foundation/v2 v2.0.6 - github.com/openziti/identity v1.0.18 - github.com/openziti/sdk-golang v0.16.135 - github.com/openziti/storage v0.1.25 - github.com/openziti/transport/v2 v2.0.36 + github.com/openziti/agent v1.0.5 + github.com/openziti/channel/v2 v2.0.12 + github.com/openziti/edge v0.24.36 + github.com/openziti/fabric v0.21.17 + github.com/openziti/foundation/v2 v2.0.7 + github.com/openziti/identity v1.0.20 + github.com/openziti/runzmd v1.0.3 + github.com/openziti/sdk-golang v0.16.146 + github.com/openziti/storage v0.1.26 + github.com/openziti/transport/v2 v2.0.38 github.com/openziti/xweb/v2 v2.0.2 github.com/openziti/ziti-db-explorer v1.1.1 github.com/pborman/uuid v1.2.0 github.com/pkg/errors v0.9.1 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 github.com/russross/blackfriday v1.5.2 - github.com/shirou/gopsutil/v3 v3.22.9 + github.com/shirou/gopsutil/v3 v3.22.10 github.com/sirupsen/logrus v1.9.0 - github.com/spf13/cobra v1.6.0 + github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.10.0 - github.com/stretchr/testify v1.8.0 - github.com/valyala/fasttemplate v1.2.1 + github.com/stretchr/testify v1.8.1 go.etcd.io/bbolt v1.3.6 - golang.org/x/net v0.0.0-20220923203811-8be639271d50 + golang.org/x/net v0.2.0 google.golang.org/grpc v1.42.0 google.golang.org/protobuf v1.28.1 gopkg.in/AlecAivazis/survey.v1 v1.8.7 @@ -56,7 +54,9 @@ require ( require ( github.com/AppsFlyer/go-sundheit v0.5.0 // indirect + github.com/MichaelMure/go-term-markdown v0.1.4 // indirect github.com/MichaelMure/go-term-text v0.3.1 // indirect + github.com/alecthomas/chroma v0.10.0 // indirect github.com/andybalholm/brotli v1.0.4 // indirect github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211106181442-e4c1a74c66bd // indirect github.com/armon/go-metrics v0.3.10 // indirect @@ -66,12 +66,11 @@ require ( github.com/c-bata/go-prompt v0.2.6 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/coreos/go-iptables v0.6.0 // indirect - github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3 // indirect github.com/dineshappavoo/basex v0.0.0-20170425072625-481a6f6dc663 // indirect github.com/disintegration/imaging v1.6.2 // indirect - github.com/dlclark/regexp2 v1.4.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/ef-ds/deque v1.0.4 // indirect github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75 // indirect @@ -89,7 +88,7 @@ require ( github.com/go-openapi/validate v0.22.0 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect - github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098 // indirect + github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/mux v1.8.0 // indirect @@ -108,8 +107,8 @@ require ( github.com/kataras/go-events v0.0.3-0.20201007151548-c411dc70c0a6 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kr/pty v1.1.8 // indirect - github.com/kyokomi/emoji/v2 v2.2.8 // indirect - github.com/lucasb-eyer/go-colorful v1.0.3 // indirect + github.com/kyokomi/emoji/v2 v2.2.10 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/lucsky/cuid v1.2.1 // indirect github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect github.com/magiconair/properties v1.8.5 // indirect @@ -131,10 +130,10 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openziti/dilithium v0.3.3 // indirect github.com/openziti/jwks v1.0.2 // indirect - github.com/openziti/metrics v1.1.4 // indirect + github.com/openziti/metrics v1.1.5 // indirect github.com/openziti/x509-claims v1.0.3 // indirect github.com/orcaman/concurrent-map/v2 v2.0.0 // indirect - github.com/parallaxsecond/parsec-client-go v0.0.0-20220111122524-cb78842db373 // indirect + github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -148,24 +147,24 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect - github.com/tklauser/go-sysconf v0.3.10 // indirect - github.com/tklauser/numcpus v0.5.0 // indirect + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.mongodb.org/mongo-driver v1.10.0 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect - golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect - golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 // indirect - golang.org/x/mod v0.5.1 // indirect + golang.org/x/crypto v0.2.0 // indirect + golang.org/x/image v0.1.0 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 // indirect - golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect - golang.org/x/term v0.0.0-20220919170432-7a66f970e087 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.7 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/sys v0.2.0 // indirect + golang.org/x/term v0.2.0 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/tools v0.1.12 // indirect google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect diff --git a/go.sum b/go.sum index 55bf999f2..8752aa719 100644 --- a/go.sum +++ b/go.sum @@ -84,16 +84,12 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.18/go.mod h1:L+HB2uBoDgi3+r1pJEJcbGwyyHhd2QXaGsKLbDwtm8Q= -github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U= github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI= github.com/alecthomas/chroma v0.7.1/go.mod h1:gHw09mkX1Qp80JlYbmN9L3+4R5o6DJJ3GRShh+AICNc= -github.com/alecthomas/chroma v0.9.2 h1:yU1sE2+TZbLIQPMk30SolL2Hn53SR/Pv750f7qZ/XMs= -github.com/alecthomas/chroma v0.9.2/go.mod h1:eMuEnpA18XbG/WhOWtCzJHS7WqEtDAI+HxdwoW0nVSk= -github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo= +github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= +github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0= github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI= -github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE= -github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY= github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -175,7 +171,6 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= -github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -191,8 +186,9 @@ github.com/dineshappavoo/basex v0.0.0-20170425072625-481a6f6dc663/go.mod h1:Kad2 github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dnsimple/dnsimple-go v0.63.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -268,8 +264,8 @@ github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXym github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.24.1 h1:Sml5cgQKGYQHF+M7yYSHaH1eOjvTykrddTE/KtQVjqo= -github.com/go-openapi/runtime v0.24.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= +github.com/go-openapi/runtime v0.24.2 h1:yX9HMGQbz32M87ECaAhGpJjBmErO3QLcgdZj9BzGx7c= +github.com/go-openapi/runtime v0.24.2/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= github.com/go-openapi/spec v0.20.7 h1:1Rlu/ZrOCCob0n+JKKJAWhNWMPW8bOZRg8FJaY+0SKI= @@ -363,8 +359,9 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= -github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098 h1:Qxs3bNRWe8GTcKMxYOSXm0jx6j0de8XUtb/fsP3GZ0I= github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU= +github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c h1:iyaGYbCmcYK0Ja9a3OUa2Fo+EaN0cbLu0eKpBwPFzc8= +github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -534,8 +531,9 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE= github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= +github.com/kyokomi/emoji/v2 v2.2.10 h1:1z5eMVcxFifsmEoNpdeq4UahbcicgQ4FEHuzrCVwmiI= +github.com/kyokomi/emoji/v2 v2.2.10/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= @@ -543,8 +541,9 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL github.com/linode/linodego v0.21.0/go.mod h1:UTpq1JUZD0CZsJ8rt+0CRkqbzrp1MbGakVPt2DXY5Mk= github.com/liquidweb/liquidweb-go v1.6.1/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= github.com/lucas-clemente/quic-go v0.18.0/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg= -github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucsky/cuid v1.2.1 h1:MtJrL2OFhvYufUIn48d35QGXyeTC8tn0upumW9WwTHg= github.com/lucsky/cuid v1.2.1/go.mod h1:QaaJqckboimOmhRSJXSx/+IT+VTfxfPGSo/6mfgUfmE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= @@ -570,7 +569,6 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -673,32 +671,32 @@ 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/agent v1.0.4 h1:QuTe98uTJ3OFl2Zrw+Pkk06X8pQcV2/kzYxJ8G+HxIY= -github.com/openziti/agent v1.0.4/go.mod h1:k9gQv82hTTxdVSfMmD0LyWzCEy+9fWh2ISsg1llgRqU= -github.com/openziti/channel/v2 v2.0.9 h1:vkB44EsSMIIxCcua0JK7VpUrBi9N7bNb42tuUAtOw28= -github.com/openziti/channel/v2 v2.0.9/go.mod h1:bHjCw8iZngh8QfUwloqi5JeDszS93kQfW8e7fEt5OJY= +github.com/openziti/agent v1.0.5 h1:wZUcMYqvwspOjDSaejMtczSXnJoqK0edI9HcEIFsTIs= +github.com/openziti/agent v1.0.5/go.mod h1:6APWgkPP6Uxf1/VyirdTVLAJxwam2vVyakrVw6yvs40= +github.com/openziti/channel/v2 v2.0.12 h1:0/qQ3qCSt70gpUuxQk8MRD3+iGKqS4wuYZpbcOzS+tc= +github.com/openziti/channel/v2 v2.0.12/go.mod h1:mESOWBphvr2/P6j3FDIiQF+Z6z3E3Vjv6GaCoGWY6eM= 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.24.11 h1:wkNzH0ZzyooFiZ5iclRmFiHJVfMj6yPsgDyYbD43kVE= -github.com/openziti/edge v0.24.11/go.mod h1:sIAjb03x6jqYyzaanliBTfF5q8DqGJHCmQ1k9nB9eN4= -github.com/openziti/edge v0.24.12 h1:ugZ1Uoz6+/7Fs0u5mN01H6gQDeu8cT0FJdEZJs/V5sU= -github.com/openziti/edge v0.24.12/go.mod h1:sIAjb03x6jqYyzaanliBTfF5q8DqGJHCmQ1k9nB9eN4= -github.com/openziti/fabric v0.21.9 h1:zMU3blfo9CUctHcwTetH/x/9+3+3c/NNy+4RuQG8zaw= -github.com/openziti/fabric v0.21.9/go.mod h1:YFAIBg42uMRGBJhZ1lwIBehsfN2jwXJvY0H4dvqpCM8= -github.com/openziti/foundation/v2 v2.0.6 h1:sN4SAVtvheuqdY6kGuCgS0d+2x2g+kAqwcv5v7LkKN4= -github.com/openziti/foundation/v2 v2.0.6/go.mod h1:M/RUF8wR2X3OE9buI+Gd3ac7FzrZkQ+g07XY/dX3X/U= -github.com/openziti/identity v1.0.18 h1:e57J8oudjoU6XNKgmxFjBeePNwxDBE6n0l3FdxDvWoA= -github.com/openziti/identity v1.0.18/go.mod h1:OVeskbGOZx7r7/nJ2qTZXCbE+lFSChGv7WFofN6TJWc= +github.com/openziti/edge v0.24.36 h1:3ywHRL5XXYtA4+y12WptofLhkndshePuy/MyKT3A2xo= +github.com/openziti/edge v0.24.36/go.mod h1:3I6GZTcb3j57Y9IlBrnpceklfzdR10ejp4D7+11B6BM= +github.com/openziti/fabric v0.21.17 h1:oT32L0Lu64Jd7CkHrQZdOwG0Mew8bMBEUowtRyhERvs= +github.com/openziti/fabric v0.21.17/go.mod h1:VsRUi2wdA3k4bOXxfrohaoUuhcjf8ZdpPPN0NzD8my4= +github.com/openziti/foundation/v2 v2.0.7 h1:QtpP0ntUhr/7uLR1iM7eEkrusQ2b2ZqTblgdq8cac9Y= +github.com/openziti/foundation/v2 v2.0.7/go.mod h1:Z0gnQsGJb/H/B+pixLtmCIpw1dBllD4QoT6LeD35WzA= +github.com/openziti/identity v1.0.20 h1:8nsQFHpqKS1ByD8QuPDxQWfS8CQEidyn5jFXWnXguX0= +github.com/openziti/identity v1.0.20/go.mod h1:X0WLWEgnM1iL8asNbuu7vUW0kZq8nnWKepMW214C9Mk= github.com/openziti/jwks v1.0.2 h1:32BGXIAnefS+v7uXKPb1x8/cQ7srek6Ai06dsrMTY4E= github.com/openziti/jwks v1.0.2/go.mod h1:KwO0x9FBG0aoJS5f6nH5xeHoplyR1H143SMI9kF0mC8= -github.com/openziti/metrics v1.1.4 h1:UGLU1kBJ3ztDO1SAs42qecN/BV4/JTPGH93LWvZwa4c= -github.com/openziti/metrics v1.1.4/go.mod h1:Wy7suQpju6oqWc1cmKA6+0Bh3izbudDGdfSqCuJ63UU= -github.com/openziti/sdk-golang v0.16.135 h1:9/pxkHGZJYUsdM03/rQksOz2S3i9C/sSUIHwmEbrxXk= -github.com/openziti/sdk-golang v0.16.135/go.mod h1:o4brIi4dvez9mM+IPtKuUN97RiGAwcY3D9zFm6SIMOI= -github.com/openziti/storage v0.1.25 h1:8HMNCR9pRKhZT8VMWad89zLntmZHLJVbWC2dDFxQ/BQ= -github.com/openziti/storage v0.1.25/go.mod h1:fQEDWSuEMn8lOYwDl1hPGMqQNjm2P3p+5y5Lz0uDZCo= -github.com/openziti/transport/v2 v2.0.36 h1:yttgXbFnj4adypuYFErb0TCOLR+v87j0se7iFw+rmIk= -github.com/openziti/transport/v2 v2.0.36/go.mod h1:EsuNHXUzdispjF9k4Kkql4SGd74rZyvJ3sp4dj77ki0= +github.com/openziti/metrics v1.1.5 h1:qhsGsYWdp7LxPCYi9WMGHGbjiHvsT1DtjM44JNHLZWk= +github.com/openziti/metrics v1.1.5/go.mod h1:B6RCuVRTpI3kEIhQlCvsHj3Pqi6bSnqFmRPgfgv9ico= +github.com/openziti/runzmd v1.0.3 h1:g+JyJS66ykMIidLTzroKBLwbsSF9S1hDvolj2PpD8lE= +github.com/openziti/runzmd v1.0.3/go.mod h1:2YuoQl5zZ6edfb+k1MjglW2cwfZvXwug2WldvBIUNrU= +github.com/openziti/sdk-golang v0.16.146 h1:5R7ZOSh+Q0pmZdzEv3l2Q03KQgiUrpaj3ymD8DjBT5k= +github.com/openziti/sdk-golang v0.16.146/go.mod h1:yOgsofdEd82pph97N4DX0xYlfgjJ2LCgC/mHkMw+5hU= +github.com/openziti/storage v0.1.26 h1:1tV4czY/TNmzX3raUZjbR8jVl5L92pdD0SjmdzCzUmE= +github.com/openziti/storage v0.1.26/go.mod h1:Zkm+4d2gckkIbuuCw/sKFWKKhPROZak3gLFzdII0KWQ= +github.com/openziti/transport/v2 v2.0.38 h1:9+EtBF052TtGvT5isuPj/SUTXNHg8RbkGBcEKfiUPd8= +github.com/openziti/transport/v2 v2.0.38/go.mod h1:FB/pqmA8RdUsoWtpTc6E/it6lLdA7GOugy9no3JDU/4= github.com/openziti/x509-claims v1.0.3 h1:HNdQ8Nf1agB3lBs1gahcO6zfkeS4S5xoQ2/PkY4HRX0= github.com/openziti/x509-claims v1.0.3/go.mod h1:Z0WIpBm6c4ecrpRKrou6Gk2wrLWxJO/+tuUwKh8VewE= github.com/openziti/xweb/v2 v2.0.2 h1:XYlVFriTq/U1wcUrc+XPnWJGhXh9NJPhtQ7+r3aC0cU= @@ -709,8 +707,8 @@ github.com/oracle/oci-go-sdk v24.2.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35uk github.com/orcaman/concurrent-map/v2 v2.0.0 h1:iSMwuBQvQ1nX5i9gYuGMiSy0fjWHmazdjF+NdSO9JzI= github.com/orcaman/concurrent-map/v2 v2.0.0/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM= github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA= -github.com/parallaxsecond/parsec-client-go v0.0.0-20220111122524-cb78842db373 h1:CUvH4JL/8OVy023LMER3dB/MerNQ6OIz4QV3E/JQ3UY= -github.com/parallaxsecond/parsec-client-go v0.0.0-20220111122524-cb78842db373/go.mod h1:gLH27qo/dvMhLTVVyMELpe3Tut7sOfkiDg7ZpeqKwsw= +github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 h1:mOvehYivJ4Aqu2CPe3D3lv8jhqOI9/1o0THxJHBE0qw= +github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9/go.mod h1:gLH27qo/dvMhLTVVyMELpe3Tut7sOfkiDg7ZpeqKwsw= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -791,10 +789,9 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA= -github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A= +github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg= +github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -848,8 +845,8 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= -github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -863,8 +860,9 @@ github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -875,8 +873,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -884,11 +883,12 @@ github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= -github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A= -github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -898,8 +898,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vultr/govultr/v2 v2.0.0/go.mod h1:2PsEeg+gs3p/Fo5Pw8F9mv+DUBEOlrNZ8GmCTGmhOhs= @@ -921,6 +921,7 @@ 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= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -982,9 +983,10 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= -golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE= +golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -998,8 +1000,9 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 h1:gQ6GUSD102fPgli+Yb4cR/cGaHF7tNBt+GYoRCpGC7s= golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk= +golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1024,8 +1027,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1081,8 +1084,10 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220923203811-8be639271d50 h1:vKyz8L3zkd+xrMeIaBsQ/MNVPVFSffdaU3ZyYlBGFnI= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1110,6 +1115,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1162,7 +1168,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1199,16 +1204,17 @@ golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220919170432-7a66f970e087 h1:tPwmk4vmvVCMdr98VgL4JH+qZxPL8fqlUOHnyOM8N3w= -golang.org/x/term v0.0.0-20220919170432-7a66f970e087/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1217,8 +1223,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1286,12 +1293,11 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= diff --git a/network-tests/go.mod b/network-tests/go.mod index 7834ecad4..125148e4c 100644 --- a/network-tests/go.mod +++ b/network-tests/go.mod @@ -2,14 +2,12 @@ module github.com/openziti/ziti/network-tests go 1.19 -replace github.com/openziti/ziti => ../ - require ( - github.com/openziti/fablab v0.4.7 - github.com/openziti/sdk-golang v0.16.135 - github.com/openziti/zitilab v0.1.1 + github.com/openziti/fablab v0.4.14 + github.com/openziti/sdk-golang v0.16.146 + github.com/openziti/zitilab v0.1.9 github.com/sirupsen/logrus v1.9.0 - github.com/spf13/cobra v1.6.0 + github.com/spf13/cobra v1.6.1 ) require ( @@ -19,18 +17,17 @@ require ( github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/MichaelMure/go-term-markdown v0.1.4 // indirect github.com/MichaelMure/go-term-text v0.3.1 // indirect - github.com/alecthomas/chroma v0.9.2 // indirect + github.com/alecthomas/chroma v0.10.0 // indirect github.com/andybalholm/brotli v1.0.4 // indirect github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211106181442-e4c1a74c66bd // indirect github.com/armon/go-metrics v0.3.10 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/aws/aws-sdk-go v1.44.114 // indirect + github.com/aws/aws-sdk-go v1.44.118 // indirect github.com/biogo/store v0.0.0-20200525035639-8c94ae1e7c9c // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/boltdb/bolt v1.3.1 // indirect github.com/c-bata/go-prompt v0.2.6 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect - github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3 // indirect github.com/dineshappavoo/basex v0.0.0-20170425072625-481a6f6dc663 // indirect @@ -51,7 +48,7 @@ require ( github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/loads v0.21.2 // indirect - github.com/go-openapi/runtime v0.24.1 // indirect + github.com/go-openapi/runtime v0.24.2 // indirect github.com/go-openapi/spec v0.20.7 // indirect github.com/go-openapi/strfmt v0.21.3 // indirect github.com/go-openapi/swag v0.22.3 // indirect @@ -74,7 +71,7 @@ require ( github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d // indirect - github.com/jedib0t/go-pretty/v6 v6.4.0 // indirect + github.com/jedib0t/go-pretty/v6 v6.4.2 // indirect github.com/jessevdk/go-flags v1.5.0 // indirect github.com/jinzhu/copier v0.3.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -106,22 +103,22 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/openziti/agent v1.0.4 // indirect - github.com/openziti/channel/v2 v2.0.9 // indirect - github.com/openziti/edge v0.24.12 // indirect - github.com/openziti/fabric v0.21.9 // indirect - github.com/openziti/foundation/v2 v2.0.6 // indirect - github.com/openziti/identity v1.0.18 // indirect + github.com/openziti/agent v1.0.5 // indirect + github.com/openziti/channel/v2 v2.0.12 // indirect + github.com/openziti/edge v0.24.36 // indirect + github.com/openziti/fabric v0.21.17 // indirect + github.com/openziti/foundation/v2 v2.0.7 // indirect + github.com/openziti/identity v1.0.20 // indirect github.com/openziti/jwks v1.0.2 // indirect - github.com/openziti/metrics v1.1.4 // indirect - github.com/openziti/storage v0.1.25 // indirect - github.com/openziti/transport/v2 v2.0.36 // indirect + github.com/openziti/metrics v1.1.5 // indirect + github.com/openziti/storage v0.1.26 // indirect + github.com/openziti/transport/v2 v2.0.38 // indirect github.com/openziti/x509-claims v1.0.3 // indirect github.com/openziti/xweb/v2 v2.0.2 // indirect - github.com/openziti/ziti v0.26.8 // indirect + github.com/openziti/ziti v0.26.10 // indirect github.com/openziti/ziti-db-explorer v1.1.1 // indirect github.com/orcaman/concurrent-map/v2 v2.0.0 // indirect - github.com/parallaxsecond/parsec-client-go v0.0.0-20220111122524-cb78842db373 // indirect + github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/sftp v1.13.5 // indirect @@ -132,7 +129,7 @@ require ( github.com/rivo/uniseg v0.4.2 // indirect github.com/rodaine/table v1.0.1 // indirect github.com/russross/blackfriday v1.5.2 // indirect - github.com/shirou/gopsutil/v3 v3.22.9 // indirect + github.com/shirou/gopsutil/v3 v3.22.10 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/speps/go-hashids v2.0.0+incompatible // indirect github.com/spf13/afero v1.6.0 // indirect @@ -140,13 +137,13 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.10.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect + github.com/stretchr/testify v1.8.1 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect - github.com/tklauser/numcpus v0.5.0 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.1 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -154,16 +151,15 @@ require ( go.etcd.io/bbolt v1.3.6 // indirect go.mongodb.org/mongo-driver v1.10.0 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect - golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect + golang.org/x/crypto v0.1.0 // indirect golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 // indirect - golang.org/x/mod v0.5.1 // indirect - golang.org/x/net v0.0.0-20220923203811-8be639271d50 // indirect - golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 // indirect - golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect - golang.org/x/term v0.0.0-20220919170432-7a66f970e087 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.7 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/net v0.1.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.2.0 // indirect + golang.org/x/term v0.2.0 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/tools v0.1.12 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/AlecAivazis/survey.v1 v1.8.7 // indirect gopkg.in/ini.v1 v1.66.2 // indirect diff --git a/network-tests/go.sum b/network-tests/go.sum index 10ee2acad..99bf2aa04 100644 --- a/network-tests/go.sum +++ b/network-tests/go.sum @@ -76,16 +76,12 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.18/go.mod h1:L+HB2uBoDgi3+r1pJEJcbGwyyHhd2QXaGsKLbDwtm8Q= -github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U= github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI= github.com/alecthomas/chroma v0.7.1/go.mod h1:gHw09mkX1Qp80JlYbmN9L3+4R5o6DJJ3GRShh+AICNc= -github.com/alecthomas/chroma v0.9.2 h1:yU1sE2+TZbLIQPMk30SolL2Hn53SR/Pv750f7qZ/XMs= -github.com/alecthomas/chroma v0.9.2/go.mod h1:eMuEnpA18XbG/WhOWtCzJHS7WqEtDAI+HxdwoW0nVSk= -github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo= +github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= +github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0= github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI= -github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE= -github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY= github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -109,8 +105,8 @@ github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:W github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.30.20/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.44.114 h1:plIkWc/RsHr3DXBj4MEw9sEW4CcL/e2ryokc+CKyq1I= -github.com/aws/aws-sdk-go v1.44.114/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.44.118 h1:FJOqIRTukf7+Ulp047/k7JB6eqMXNnj7eb+coORThHQ= +github.com/aws/aws-sdk-go v1.44.118/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -149,7 +145,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -231,8 +226,8 @@ github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXym github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.24.1 h1:Sml5cgQKGYQHF+M7yYSHaH1eOjvTykrddTE/KtQVjqo= -github.com/go-openapi/runtime v0.24.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= +github.com/go-openapi/runtime v0.24.2 h1:yX9HMGQbz32M87ECaAhGpJjBmErO3QLcgdZj9BzGx7c= +github.com/go-openapi/runtime v0.24.2/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= github.com/go-openapi/spec v0.20.7 h1:1Rlu/ZrOCCob0n+JKKJAWhNWMPW8bOZRg8FJaY+0SKI= @@ -427,8 +422,8 @@ github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7P github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 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/jedib0t/go-pretty/v6 v6.4.0 h1:YlI/2zYDrweA4MThiYMKtGRfT+2qZOO65ulej8GTcVI= -github.com/jedib0t/go-pretty/v6 v6.4.0/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI= +github.com/jedib0t/go-pretty/v6 v6.4.2 h1:DcJNSNIb1E17Tvy9w9S7z+sExvWvvjNbFdyr6C+FUL0= +github.com/jedib0t/go-pretty/v6 v6.4.2/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= @@ -501,7 +496,6 @@ github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kN github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -599,44 +593,46 @@ github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openziti/agent v1.0.4 h1:QuTe98uTJ3OFl2Zrw+Pkk06X8pQcV2/kzYxJ8G+HxIY= -github.com/openziti/agent v1.0.4/go.mod h1:k9gQv82hTTxdVSfMmD0LyWzCEy+9fWh2ISsg1llgRqU= -github.com/openziti/channel/v2 v2.0.9 h1:vkB44EsSMIIxCcua0JK7VpUrBi9N7bNb42tuUAtOw28= -github.com/openziti/channel/v2 v2.0.9/go.mod h1:bHjCw8iZngh8QfUwloqi5JeDszS93kQfW8e7fEt5OJY= -github.com/openziti/edge v0.24.12 h1:ugZ1Uoz6+/7Fs0u5mN01H6gQDeu8cT0FJdEZJs/V5sU= -github.com/openziti/edge v0.24.12/go.mod h1:sIAjb03x6jqYyzaanliBTfF5q8DqGJHCmQ1k9nB9eN4= -github.com/openziti/fablab v0.4.7 h1:922uJM16ryYaUKzzcb2EWLunoK7xdZ5B/kZ3p/HGmFg= -github.com/openziti/fablab v0.4.7/go.mod h1:9wwNKuWeoAC2FRbv1/Y/GCbkL7nKEHXjav3AkP+g4Ds= -github.com/openziti/fabric v0.21.9 h1:zMU3blfo9CUctHcwTetH/x/9+3+3c/NNy+4RuQG8zaw= -github.com/openziti/fabric v0.21.9/go.mod h1:YFAIBg42uMRGBJhZ1lwIBehsfN2jwXJvY0H4dvqpCM8= -github.com/openziti/foundation/v2 v2.0.6 h1:sN4SAVtvheuqdY6kGuCgS0d+2x2g+kAqwcv5v7LkKN4= -github.com/openziti/foundation/v2 v2.0.6/go.mod h1:M/RUF8wR2X3OE9buI+Gd3ac7FzrZkQ+g07XY/dX3X/U= -github.com/openziti/identity v1.0.18 h1:e57J8oudjoU6XNKgmxFjBeePNwxDBE6n0l3FdxDvWoA= -github.com/openziti/identity v1.0.18/go.mod h1:OVeskbGOZx7r7/nJ2qTZXCbE+lFSChGv7WFofN6TJWc= +github.com/openziti/agent v1.0.5 h1:wZUcMYqvwspOjDSaejMtczSXnJoqK0edI9HcEIFsTIs= +github.com/openziti/agent v1.0.5/go.mod h1:6APWgkPP6Uxf1/VyirdTVLAJxwam2vVyakrVw6yvs40= +github.com/openziti/channel/v2 v2.0.12 h1:0/qQ3qCSt70gpUuxQk8MRD3+iGKqS4wuYZpbcOzS+tc= +github.com/openziti/channel/v2 v2.0.12/go.mod h1:mESOWBphvr2/P6j3FDIiQF+Z6z3E3Vjv6GaCoGWY6eM= +github.com/openziti/edge v0.24.36 h1:3ywHRL5XXYtA4+y12WptofLhkndshePuy/MyKT3A2xo= +github.com/openziti/edge v0.24.36/go.mod h1:3I6GZTcb3j57Y9IlBrnpceklfzdR10ejp4D7+11B6BM= +github.com/openziti/fablab v0.4.14 h1:765ha5lu3TEznhQP1LVAyLYfPJsVLYFLoP8tIvrfCtc= +github.com/openziti/fablab v0.4.14/go.mod h1:FmnlfLEQUa/Gdf82wnkQLFe44lGexoIxGd+JOtRIMHs= +github.com/openziti/fabric v0.21.17 h1:oT32L0Lu64Jd7CkHrQZdOwG0Mew8bMBEUowtRyhERvs= +github.com/openziti/fabric v0.21.17/go.mod h1:VsRUi2wdA3k4bOXxfrohaoUuhcjf8ZdpPPN0NzD8my4= +github.com/openziti/foundation/v2 v2.0.7 h1:QtpP0ntUhr/7uLR1iM7eEkrusQ2b2ZqTblgdq8cac9Y= +github.com/openziti/foundation/v2 v2.0.7/go.mod h1:Z0gnQsGJb/H/B+pixLtmCIpw1dBllD4QoT6LeD35WzA= +github.com/openziti/identity v1.0.20 h1:8nsQFHpqKS1ByD8QuPDxQWfS8CQEidyn5jFXWnXguX0= +github.com/openziti/identity v1.0.20/go.mod h1:X0WLWEgnM1iL8asNbuu7vUW0kZq8nnWKepMW214C9Mk= github.com/openziti/jwks v1.0.2 h1:32BGXIAnefS+v7uXKPb1x8/cQ7srek6Ai06dsrMTY4E= github.com/openziti/jwks v1.0.2/go.mod h1:KwO0x9FBG0aoJS5f6nH5xeHoplyR1H143SMI9kF0mC8= -github.com/openziti/metrics v1.1.4 h1:UGLU1kBJ3ztDO1SAs42qecN/BV4/JTPGH93LWvZwa4c= -github.com/openziti/metrics v1.1.4/go.mod h1:Wy7suQpju6oqWc1cmKA6+0Bh3izbudDGdfSqCuJ63UU= -github.com/openziti/sdk-golang v0.16.135 h1:9/pxkHGZJYUsdM03/rQksOz2S3i9C/sSUIHwmEbrxXk= -github.com/openziti/sdk-golang v0.16.135/go.mod h1:o4brIi4dvez9mM+IPtKuUN97RiGAwcY3D9zFm6SIMOI= -github.com/openziti/storage v0.1.25 h1:8HMNCR9pRKhZT8VMWad89zLntmZHLJVbWC2dDFxQ/BQ= -github.com/openziti/storage v0.1.25/go.mod h1:fQEDWSuEMn8lOYwDl1hPGMqQNjm2P3p+5y5Lz0uDZCo= -github.com/openziti/transport/v2 v2.0.36 h1:yttgXbFnj4adypuYFErb0TCOLR+v87j0se7iFw+rmIk= -github.com/openziti/transport/v2 v2.0.36/go.mod h1:EsuNHXUzdispjF9k4Kkql4SGd74rZyvJ3sp4dj77ki0= +github.com/openziti/metrics v1.1.5 h1:qhsGsYWdp7LxPCYi9WMGHGbjiHvsT1DtjM44JNHLZWk= +github.com/openziti/metrics v1.1.5/go.mod h1:B6RCuVRTpI3kEIhQlCvsHj3Pqi6bSnqFmRPgfgv9ico= +github.com/openziti/sdk-golang v0.16.146 h1:5R7ZOSh+Q0pmZdzEv3l2Q03KQgiUrpaj3ymD8DjBT5k= +github.com/openziti/sdk-golang v0.16.146/go.mod h1:yOgsofdEd82pph97N4DX0xYlfgjJ2LCgC/mHkMw+5hU= +github.com/openziti/storage v0.1.26 h1:1tV4czY/TNmzX3raUZjbR8jVl5L92pdD0SjmdzCzUmE= +github.com/openziti/storage v0.1.26/go.mod h1:Zkm+4d2gckkIbuuCw/sKFWKKhPROZak3gLFzdII0KWQ= +github.com/openziti/transport/v2 v2.0.38 h1:9+EtBF052TtGvT5isuPj/SUTXNHg8RbkGBcEKfiUPd8= +github.com/openziti/transport/v2 v2.0.38/go.mod h1:FB/pqmA8RdUsoWtpTc6E/it6lLdA7GOugy9no3JDU/4= github.com/openziti/x509-claims v1.0.3 h1:HNdQ8Nf1agB3lBs1gahcO6zfkeS4S5xoQ2/PkY4HRX0= github.com/openziti/x509-claims v1.0.3/go.mod h1:Z0WIpBm6c4ecrpRKrou6Gk2wrLWxJO/+tuUwKh8VewE= github.com/openziti/xweb/v2 v2.0.2 h1:XYlVFriTq/U1wcUrc+XPnWJGhXh9NJPhtQ7+r3aC0cU= github.com/openziti/xweb/v2 v2.0.2/go.mod h1:KQOOlnJk08EZT3TWkvDj/pbIUEVbgG0IrrNzl8gsi40= +github.com/openziti/ziti v0.26.10 h1:aPikHYJa/KvzgTiRW2hGw8f2L/+NsFgy8sbHXcuxwbU= +github.com/openziti/ziti v0.26.10/go.mod h1:hbl02rbQ8l6+kF/vXolNPCdZLQ3WKkSGEc7xeRPEl4c= github.com/openziti/ziti-db-explorer v1.1.1 h1:G0eoTby+aIjjt5TxEfR+FMI2CWd4RvZFjzaIMX2lEBw= github.com/openziti/ziti-db-explorer v1.1.1/go.mod h1:h76h7Tsb+khb0v+CqYKL6ifUfJbUMjGBFU2IvupfBE4= -github.com/openziti/zitilab v0.1.1 h1:Ewp7qghV78Te1JWwMZV2tvkm0M0xHDJWTgx56sMx5bg= -github.com/openziti/zitilab v0.1.1/go.mod h1:4xR04e4G33+ii5zwssQVlGQBG+j+DYE2Nh6HXjWUrNo= +github.com/openziti/zitilab v0.1.9 h1:NWUgq4ZyZIhXlH9HVL19JK6ArDnTNLnlKOteE6PLa8E= +github.com/openziti/zitilab v0.1.9/go.mod h1:ElsdjW6cyMBeLxda/n8DF9ec4KtZavys3hbYkgHpQf4= github.com/oracle/oci-go-sdk v24.2.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/orcaman/concurrent-map/v2 v2.0.0 h1:iSMwuBQvQ1nX5i9gYuGMiSy0fjWHmazdjF+NdSO9JzI= github.com/orcaman/concurrent-map/v2 v2.0.0/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM= github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA= -github.com/parallaxsecond/parsec-client-go v0.0.0-20220111122524-cb78842db373 h1:CUvH4JL/8OVy023LMER3dB/MerNQ6OIz4QV3E/JQ3UY= -github.com/parallaxsecond/parsec-client-go v0.0.0-20220111122524-cb78842db373/go.mod h1:gLH27qo/dvMhLTVVyMELpe3Tut7sOfkiDg7ZpeqKwsw= +github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 h1:mOvehYivJ4Aqu2CPe3D3lv8jhqOI9/1o0THxJHBE0qw= +github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9/go.mod h1:gLH27qo/dvMhLTVVyMELpe3Tut7sOfkiDg7ZpeqKwsw= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -708,10 +704,9 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA= -github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A= +github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg= +github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -735,8 +730,8 @@ github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= -github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -748,8 +743,9 @@ github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -760,8 +756,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= @@ -771,16 +768,16 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= -github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A= -github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vultr/govultr/v2 v2.0.0/go.mod h1:2PsEeg+gs3p/Fo5Pw8F9mv+DUBEOlrNZ8GmCTGmhOhs= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= @@ -847,8 +844,8 @@ golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= -golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -887,8 +884,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -940,8 +937,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220923203811-8be639271d50 h1:vKyz8L3zkd+xrMeIaBsQ/MNVPVFSffdaU3ZyYlBGFnI= -golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -966,8 +963,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1013,7 +1010,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1049,13 +1045,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220919170432-7a66f970e087 h1:tPwmk4vmvVCMdr98VgL4JH+qZxPL8fqlUOHnyOM8N3w= -golang.org/x/term v0.0.0-20220919170432-7a66f970e087/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1064,8 +1060,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1130,12 +1127,11 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= diff --git a/network-tests/simple-transfer/main.go b/network-tests/simple-transfer/main.go index cfd733075..d2b00b4d3 100644 --- a/network-tests/simple-transfer/main.go +++ b/network-tests/simple-transfer/main.go @@ -184,7 +184,7 @@ var m = &model.Model{ ), config.Component(), zitilab.DefaultZitiBinaries(), - devkit.DevKitF(zitilab.ZitiDistBinaries, []string{"ziti-echo"}), + devkit.DevKitF(zitilab.ZitiRoot, []string{"ziti-echo"}), }, Distribution: model.DistributionStages{ diff --git a/quickstart/docker/image/TestDockerfile b/quickstart/docker/image/TestDockerfile new file mode 100644 index 000000000..1d67e0df3 --- /dev/null +++ b/quickstart/docker/image/TestDockerfile @@ -0,0 +1,28 @@ +FROM ubuntu:20.04 + +RUN apt update && \ + apt install jq curl vim psmisc -y + +RUN useradd -ms /bin/bash ziti && \ + mkdir /openziti && chown ziti:ziti /openziti && \ + mkdir /openziti/scripts && chown ziti:ziti /openziti/scripts && \ + mkdir /openziti/shared && chown ziti:ziti /openziti/shared + +USER ziti +WORKDIR /openziti + +ENV ZITI_HOME=/openziti +ENV ZITI_BIN_DIR="${ZITI_HOME}/ziti-bin" +ENV ZITI_SCRIPTS="${ZITI_HOME}/scripts" +ENV ENV_FILE="${ZITI_HOME}/ziti.env" +ENV ZITI_NETWORK=localhost + +RUN mkdir -p "${ZITI_SCRIPTS}" + +COPY --chown=ziti ziti.ignore "${ZITI_BIN_DIR}" +COPY --chown=ziti ziti-cli-functions.sh "${ZITI_SCRIPTS}/" +COPY --chown=ziti dockerTestEntrypoint.sh "${ZITI_SCRIPTS}/" + +ENTRYPOINT /bin/bash -c '${ZITI_SCRIPTS}/dockerTestEntrypoint.sh' +# && while :; do sleep 1; done' + diff --git a/quickstart/docker/image/dockerTestEntrypoint.sh b/quickstart/docker/image/dockerTestEntrypoint.sh new file mode 100755 index 000000000..d11b11f59 --- /dev/null +++ b/quickstart/docker/image/dockerTestEntrypoint.sh @@ -0,0 +1,9 @@ +if [[ -f "runonce" ]]; then + echo "Keeping active for testing" + tail -f /dev/null +fi + +touch runonce + +source "${ZITI_SCRIPTS}/ziti-cli-functions.sh" +expressInstall "${ZITI_NETWORK}" \ No newline at end of file diff --git a/quickstart/docker/image/run-router.sh b/quickstart/docker/image/run-router.sh index ce98e425a..5ffe384c9 100755 --- a/quickstart/docker/image/run-router.sh +++ b/quickstart/docker/image/run-router.sh @@ -5,15 +5,22 @@ sleep 5 . "${ZITI_SCRIPTS}/ziti-cli-functions.sh" -if [[ "${ZITI_CONTROLLER_RAWNAME-}" == "" ]]; then export export ZITI_CONTROLLER_RAWNAME="ziti-controller"; fi -if [[ "${ZITI_EDGE_CONTROLLER_RAWNAME-}" == "" ]]; then export export ZITI_EDGE_CONTROLLER_RAWNAME="ziti-edge-controller"; fi -if [[ "${ZITI_EDGE_ROUTER_RAWNAME-}" == "" ]]; then export export ZITI_EDGE_ROUTER_RAWNAME="${ZITI_NETWORK-}-edge-router"; fi +if [[ "${ZITI_CONTROLLER_RAWNAME-}" == "" ]]; then export ZITI_CONTROLLER_RAWNAME="ziti-controller"; fi +if [[ "${ZITI_EDGE_CONTROLLER_RAWNAME-}" == "" ]]; then export ZITI_EDGE_CONTROLLER_RAWNAME="ziti-edge-controller"; fi +if [[ "${ZITI_EDGE_ROUTER_RAWNAME-}" == "" ]]; then + export ZITI_EDGE_ROUTER_DESIRED_RAWNAME="${ZITI_NETWORK-}-edge-router" +else + ZITI_EDGE_ROUTER_DESIRED_RAWNAME="${ZITI_EDGE_ROUTER_RAWNAME}" +fi if [[ "${ZITI_EDGE_ROUTER_PORT-}" == "" ]]; then export ZITI_EDGE_ROUTER_PORT="3022"; fi if [[ "${ZITI_EDGE_ROUTER_HOSTNAME}" == "" ]]; then export ZITI_EDGE_ROUTER_HOSTNAME="${ZITI_EDGE_ROUTER_RAWNAME}${ZITI_DOMAIN_SUFFIX}"; fi if [[ "${ZITI_EDGE_ROUTER_ROLES}" == "" ]]; then export ZITI_EDGE_ROUTER_ROLES="${ZITI_EDGE_ROUTER_RAWNAME}"; fi . ${ZITI_HOME}/ziti.env +# This is a unique situation due to the env file being shared among all routers so we need to explicitly set the router +export ZITI_EDGE_ROUTER_RAWNAME="${ZITI_EDGE_ROUTER_DESIRED_RAWNAME}" + # shellcheck disable=SC2091 until $(curl -s -o /dev/null --fail -k "https://${ZITI_EDGE_CTRL_ADVERTISED_HOST_PORT}"); do echo "waiting for https://${ZITI_EDGE_CTRL_ADVERTISED_HOST_PORT}" diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index d5fafdc48..e2e158f35 100755 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -445,6 +445,7 @@ function ziti_expressConfiguration { if [[ "${ZITI_ZAC_HOSTNAME-}" != "" ]]; then echo "ZITI_ZAC_HOSTNAME OVERRIDDEN: $ZITI_ZAC_HOSTNAME"; fi if [[ "${ZITI_EDGE_ROUTER_HOSTNAME-}" != "" ]]; then echo "ZITI_EDGE_ROUTER_HOSTNAME OVERRIDDEN: $ZITI_EDGE_ROUTER_HOSTNAME"; fi if [[ "${ZITI_EDGE_ROUTER_PORT-}" != "" ]]; then echo "ZITI_EDGE_ROUTER_PORT OVERRIDDEN: $ZITI_EDGE_ROUTER_PORT"; fi + if [[ "${ZITI_EDGE_ROUTER_RAWNAME-}" != "" ]]; then echo "ZITI_EDGE_ROUTER_RAWNAME OVERRIDDEN: $ZITI_EDGE_ROUTER_RAWNAME"; fi echo " " echo " " @@ -495,14 +496,9 @@ function ziti_expressConfiguration { "${ZITI_BIN_DIR-}/ziti" edge create edge-router-policy allEdgeRouters --edge-router-roles '#public' --identity-roles '#all' > /dev/null echo -e "---------- Creating a service edge router policy allowing all services to use $(GREEN "#public") edge routers" - "${ZITI_BIN_DIR-}/ziti" edge delete service-edge-router-policy allSvcPublicRouters > /dev/null - "${ZITI_BIN_DIR-}/ziti" edge create service-edge-router-policy allSvcPublicRouters --edge-router-roles '#public' --service-roles '#all' > /dev/null + "${ZITI_BIN_DIR-}/ziti" edge delete service-edge-router-policy allSvcAllRouters > /dev/null + "${ZITI_BIN_DIR-}/ziti" edge create service-edge-router-policy allSvcAllRouters --edge-router-roles '#all' --service-roles '#all' > /dev/null - if [[ "${ZITI_EDGE_ROUTER_RAWNAME-}" != "" ]]; then - echo "ZITI_EDGE_ROUTER_RAWNAME OVERRIDDEN: $ZITI_EDGE_ROUTER_RAWNAME" - else - ZITI_EDGE_ROUTER_RAWNAME="${ZITI_NETWORK}-edge-router" - fi echo "USING ZITI_EDGE_ROUTER_RAWNAME: $ZITI_EDGE_ROUTER_RAWNAME" createRouterPki "${ZITI_EDGE_ROUTER_RAWNAME}" @@ -979,7 +975,8 @@ function ziti_createEnvFile { export ZITI_HOME="${ZITI_HOME}" if [[ "${ZITI_OSTYPE}" == "windows" ]]; then - export ZITI_HOME_OS_SPECIFIC="$(cygpath -m "${ZITI_HOME}")" + ZITI_HOME_OS_SPECIFIC="$(cygpath -m "${ZITI_HOME}")" + export ZITI_HOME_OS_SPECIFIC else export ZITI_HOME_OS_SPECIFIC="${ZITI_HOME}" fi @@ -1016,7 +1013,8 @@ function ziti_createEnvFile { export ZITI_PKI="${ZITI_SHARED}/pki" if [[ "${ZITI_OSTYPE}" == "windows" ]]; then - export ZITI_PKI_OS_SPECIFIC="$(cygpath -m "${ZITI_PKI}")" + ZITI_PKI_OS_SPECIFIC="$(cygpath -m "${ZITI_PKI}")" + export ZITI_PKI_OS_SPECIFIC else export ZITI_PKI_OS_SPECIFIC="${ZITI_PKI}" fi @@ -1055,6 +1053,8 @@ function ziti_createEnvFile { if [[ "${ZITI_SIGNING_CERT}" == "" ]]; then export export ZITI_SIGNING_CERT="${ZITI_PKI_OS_SPECIFIC}/${ZITI_SIGNING_INTERMEDIATE_NAME}/certs/${ZITI_SIGNING_INTERMEDIATE_NAME}.cert"; fi if [[ "${ZITI_SIGNING_KEY}" == "" ]]; then export export ZITI_SIGNING_KEY="${ZITI_PKI_OS_SPECIFIC}/${ZITI_SIGNING_INTERMEDIATE_NAME}/keys/${ZITI_SIGNING_INTERMEDIATE_NAME}.key"; fi + if [[ "${ZITI_EDGE_ROUTER_RAWNAME-}" == "" ]]; then ZITI_EDGE_ROUTER_RAWNAME="${ZITI_NETWORK}-edge-router"; fi + mkdir -p "${ZITI_BIN_ROOT}" mkdir -p "${ZITI_HOME}/db" mkdir -p "${ZITI_PKI}" @@ -1382,7 +1382,7 @@ function createZacSystemdFile { if which node >/dev/null; then # store the absolute path to the node executable because it's required by systemd on Amazon Linux, at least - NODE_BIN=$(readlink -f $(which node)) + NODE_BIN=$(readlink -f "$(which node)") else echo "ERROR: missing executable 'node'" >&2 return 1 @@ -1439,6 +1439,7 @@ function checkEnvVariable() { do # Parameter expansion is different between shells if [[ -n "$ZSH_VERSION" ]]; then + # shellcheck disable=SC2296 if [[ -z "${(P)arg}" ]]; then echo -e " * ERROR: $(RED "${arg} is not set") " return 1 diff --git a/quickstart/test/quickstart_test.go b/quickstart/test/quickstart_test.go new file mode 100644 index 000000000..1fe747c81 --- /dev/null +++ b/quickstart/test/quickstart_test.go @@ -0,0 +1,757 @@ +package test + +import ( + "archive/tar" + "bufio" + "bytes" + "context" + "crypto/tls" + "crypto/x509" + "encoding/json" + "fmt" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/client" + "github.com/openziti/edge/rest_management_api_client" + api_client_config "github.com/openziti/edge/rest_management_api_client/config" + "github.com/openziti/edge/rest_management_api_client/edge_router" + "github.com/openziti/edge/rest_management_api_client/edge_router_policy" + "github.com/openziti/edge/rest_management_api_client/identity" + "github.com/openziti/edge/rest_management_api_client/service" + "github.com/openziti/edge/rest_management_api_client/service_edge_router_policy" + "github.com/openziti/edge/rest_management_api_client/service_policy" + "github.com/openziti/edge/rest_management_api_client/terminator" + "github.com/openziti/edge/rest_model" + "github.com/openziti/edge/rest_util" + "github.com/openziti/sdk-golang/ziti" + sdk_config "github.com/openziti/sdk-golang/ziti/config" + "github.com/openziti/sdk-golang/ziti/enroll" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "io" + "net" + "net/http" + "os" + "os/exec" + "strings" + "testing" + "time" +) + +func startDockerComposeQuickstart() { + // Run docker compose environment + _ = os.Setenv("ZITI_VERSION", "test") + cmd := exec.Command("docker-compose", "-f", "docker/docker-compose.yml", "up", "-d") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + fmt.Println(err) + log.Fatal("Failed to start compose environment") + } + _ = os.Unsetenv("ZITI_VERSION") +} + +func stopDockerComposeQuickstart() { + oldWD, _ := os.Getwd() + _ = os.Chdir("docker") + cmd := exec.Command("docker-compose", "down", "-v") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + fmt.Println(err) + log.Fatal("Failed to stop compose environment") + } + _ = os.Chdir(oldWD) +} + +func buildDockerQuickstartTestImage() { + oldWD, _ := os.Getwd() + _ = os.Chdir("../docker/image") + + dir := "." + + buf := new(bytes.Buffer) + tw := tar.NewWriter(buf) + defer tw.Close() + + dockerFile := "TestDockerfile" + + filePaths := iterateDir(dir) + + for _, filePath := range filePaths { + err := addFileToTarWriter(filePath, tw) + if err != nil { + fmt.Println(fmt.Sprintf("Could not add file '%s', to tarball, got error '%s'", filePath, err.Error())) + } + } + + ctx := context.Background() + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + panic(err) + } + dockerFileTarReader := bytes.NewReader(buf.Bytes()) + + imageBuildResponse, err := cli.ImageBuild(ctx, dockerFileTarReader, types.ImageBuildOptions{ + Context: dockerFileTarReader, + Dockerfile: dockerFile, + Remove: true, + Tags: []string{"openziti/quickstart:test"}, + }) + if err != nil { + fmt.Println(err) + log.Fatal("Failed to build dockerfile") + } + defer imageBuildResponse.Body.Close() + + danglers := filters.NewArgs() + danglers.Add("dangling", "true") + results, err := cli.ImageList(ctx, types.ImageListOptions{ + All: false, + Filters: danglers, + }) + + for _, img := range results { + _, err = cli.ImageRemove(ctx, img.ID, types.ImageRemoveOptions{}) + if err != nil { + fmt.Println(fmt.Sprintf("Error removing dangling image %s, got error '%s'", img.ID, err.Error())) + } + } + _ = os.Chdir(oldWD) +} + +func iterateDir(dirPath string) []string { + dir, err := os.Open(dirPath) + if err != nil { + fmt.Println(err) + log.Fatal("Failed to parse ziti.ignore") + } + defer dir.Close() + fis, err := dir.Readdir(0) + if err != nil { + fmt.Println(err) + log.Fatal("Failed to read directory") + } + var filePaths []string + for _, fi := range fis { + curPath := dirPath + "/" + fi.Name() + if fi.IsDir() { + //TarGzWrite( curPath, tw, fi ) + filePaths = append(filePaths, iterateDir(curPath)...) + } else { + filePaths = append(filePaths, curPath) + //err = addToTar(tw, curPath) + if err != nil { + fmt.Println(err) + log.Fatal("Failed add " + curPath) + } + //TarGzWrite( curPath, tw, fi ) + } + } + return filePaths +} + +func addFileToTarWriter(filePath string, tarWriter *tar.Writer) error { + file, err := os.Open(filePath) + if err != nil { + return errors.New(fmt.Sprintf("Could not open file '%s', got error '%s'", filePath, err.Error())) + } + defer file.Close() + + stat, err := file.Stat() + if err != nil { + return errors.New(fmt.Sprintf("Could not get stat for file '%s', got error '%s'", filePath, err.Error())) + } + + header := &tar.Header{ + Name: filePath, + Size: stat.Size(), + Mode: int64(stat.Mode()), + ModTime: stat.ModTime(), + } + + err = tarWriter.WriteHeader(header) + if err != nil { + return errors.New(fmt.Sprintf("Could not write header for file '%s', got error '%s'", filePath, err.Error())) + } + + _, err = io.Copy(tarWriter, file) + if err != nil { + return errors.New(fmt.Sprintf("Could not copy the file '%s' data to the tarball, got error '%s'", filePath, err.Error())) + } + + return nil +} + +func startDockerQuickstartTest() string { + cmd := exec.Command("docker", "run", "-d", "--name", "quickstart-test", "openziti/quickstart:test") + cmd.Stderr = os.Stderr + output, err := cmd.Output() + if err != nil { + fmt.Println(err) + log.Fatalf("Failed to start docker environment (%s)\n", err) + } + return strings.TrimSuffix(string(output), "\n") +} + +/* +This is a manually run test to confirm expected values are appearing in the .env file that is generated after the +quickstart script is run. +*/ +func TestQuickStartEnvFile(t *testing.T) { + expectedValues := []string{ + "export ZITI_EDGE_ROUTER_RAWNAME=\"localhost-edge-router\"", + "export ZITI_EDGE_CONTROLLER_RAWNAME=\"localhost\"", + "export ZITI_HOME_OS_SPECIFIC=\"/openziti\"", + "export ZITI_HOME=\"/openziti\"", + "export ZITI_BIN_DIR=\"/openziti/ziti-bin\"", + "export ZITI_EDGE_CTRL_ADVERTISED=\"localhost:1280\"", + "export ZITI_USER=\"admin\"", + "export ZITI_PWD=\"admin\"", + "export ZITI_PKI_OS_SPECIFIC=\"/openziti/pki\"", + "export ZITI_EDGE_CONTROLLER_ROOTCA_NAME=\"localhost-root-ca\"", + "export ZITI_EDGE_CONTROLLER_INTERMEDIATE_NAME=\"localhost-intermediate\"", + } + + // Build the image + buildDockerQuickstartTestImage() + + // Start the image + containerId := startDockerQuickstartTest() + + // Wait until it finishes + for { + time.Sleep(1) + output, _ := exec.Command("docker", "inspect", "-f", "{{.State.Running}}", containerId).Output() + if string(output) == "false\n" { + break + } + } + + // Start it back up and get the env file + output, err := exec.Command("docker", "start", containerId).Output() + if err != nil { + fmt.Printf("Error: %s\n", output) + } + cpString := containerId + ":/openziti/localhost.env" + cmd := exec.Command("docker", "cp", cpString, ".") + err = cmd.Run() + if err != nil { + fmt.Printf("Error copying env file: %s\n", output) + } + + // Check env file for expected values + file, err := os.Open("localhost.env") + if err != nil { + log.Fatal(err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + for i := 0; i < len(expectedValues); i++ { + if expectedValues[i] == scanner.Text() { + // If found, stop looking for it by removing it from the array + expectedValues = append(expectedValues[:i], expectedValues[i+1:]...) + } + } + } + + // Anything still in the array wasn't found + if len(expectedValues) > 0 { + for i := 0; i < len(expectedValues); i++ { + fmt.Printf("Could not find expected value (%s)\n", expectedValues[i]) + } + } + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + + // Cleanup + err = os.Remove(file.Name()) + if err != nil { + log.Fatalf("Error removing test file %s", file.Name()) + } + err = exec.Command("docker", "rm", "-f", containerId).Run() + if err != nil { + log.Fatalf("Error cleaning up docker container %s", containerId) + } + + // Test + assert.Equal(t, 0, len(expectedValues), "Not all expected env file values were found") +} + +/* +This is a manually run test that will, with the default values, confirm the docker-compose ziti network is running as +expected. The values can be edited to confirm other ziti networks but will require an http server on the back end. +*/ +func TestSimpleWebService(t *testing.T) { + + // Wait for the controller to become available + testerUsername := "gotester" + ctrlAddress := "https://ziti-edge-controller:1280" + hostingRouterName := "ziti-edge-router" + dialAddress := "simple.web.smoke.test" + dialPort := 80 + bindHostAddress := "web-test-blue" + bindHostPort := 8000 + serviceName := "basic.web.smoke.test.service" + waitForController(ctrlAddress) + // Give routers time to enroll themselves + time.Sleep(5 * time.Second) + + // Authenticate with the controller + caCerts, err := rest_util.GetControllerWellKnownCas(ctrlAddress) + if err != nil { + log.Fatal(err) + } + caPool := x509.NewCertPool() + for _, ca := range caCerts { + caPool.AddCert(ca) + } + client, err := rest_util.NewEdgeManagementClientWithUpdb("admin", "admin", ctrlAddress, caPool) + if err != nil { + log.Fatal(err) + } + + // Create the tester identity + ident := createIdentity(client, testerUsername, rest_model.IdentityTypeUser, false) + defer func() { _ = deleteIdentityByID(client, ident.GetPayload().Data.ID) }() + + // Enroll the identity + identConfig := enrollIdentity(client, ident.Payload.Data.ID) + + // Create a json config file + output, err := os.Create(testerUsername + ".json") + if err != nil { + fmt.Println(err) + log.Fatal("Failed to create output config file") + } + defer func() { + _ = output.Close() + err = os.Remove(testerUsername + ".json") + if err != nil { + fmt.Println(err) + log.Fatal("Failed to delete json config file") + } + }() + enc := json.NewEncoder(output) + enc.SetEscapeHTML(false) + encErr := enc.Encode(&identConfig) + if encErr != nil { + fmt.Println(err) + log.Fatal("Failed to generate encoded output") + } + + // Allow dialing the service using an intercept config (intercept because we'll be using the SDK) + dialSvcConfig := createInterceptV1ServiceConfig(client, "basic.smoke.dial", []string{"tcp"}, []string{dialAddress}, dialPort, dialPort) + defer func() { _ = deleteServiceConfigByID(client, dialSvcConfig.ID) }() + + // Provide host config for the hostname + bindSvcConfig := createHostV1ServiceConfig(client, "basic.smoke.bind", "tcp", bindHostAddress, bindHostPort) + defer func() { _ = deleteServiceConfigByID(client, bindSvcConfig.ID) }() + + // Create a service that "links" the dial and bind configs + createService(client, serviceName, []string{bindSvcConfig.ID, dialSvcConfig.ID}) + + // Create a service policy to allow the router to host the web test service + hostRouterIdent := getIdentityByName(client, hostingRouterName) + webTestService := getServiceByName(client, serviceName) + defer func() { _ = deleteServiceByID(client, *webTestService.ID) }() + bindSP := createServicePolicy(client, "basic.web.smoke.test.service.bind", rest_model.DialBindBind, rest_model.Roles{"@" + *hostRouterIdent.ID}, rest_model.Roles{"@" + *webTestService.ID}) + defer func() { _ = deleteServicePolicyByID(client, bindSP.ID) }() + + // Create a service policy to allow tester to dial the service + testerIdent := getIdentityByName(client, testerUsername) + dialSP := createServicePolicy(client, "basic.web.smoke.test.service.dial", rest_model.DialBindDial, rest_model.Roles{"@" + *testerIdent.ID}, rest_model.Roles{"@" + *webTestService.ID}) + defer func() { _ = deleteServicePolicyByID(client, dialSP.ID) }() + + // Test connectivity with private edge router, wait some time for the terminator to be created + currentCount := getTerminatorCountByRouterName(client, hostingRouterName) + termCntReached := waitForTerminatorCountByRouterName(client, hostingRouterName, currentCount+1, 30*time.Second) + if !termCntReached { + fmt.Println("Unable to detect a terminator for the edge router") + } + helloUrl := fmt.Sprintf("http://%s:%d", serviceName, dialPort) + httpClient := createZitifiedHttpClient("/Users/geoffberl/git/NetFoundry/ziti/quickstart/" + testerUsername + ".json") + resp, e := httpClient.Get(helloUrl) + if e != nil { + panic(e) + } + + assert.Equal(t, 200, resp.StatusCode, fmt.Sprintf("Expected successful HTTP status code 200, received %d instead", resp.StatusCode)) +} + +func enrollIdentity(client *rest_management_api_client.ZitiEdgeManagement, identityID string) *sdk_config.Config { + // Get the identity object + params := &identity.DetailIdentityParams{ + Context: context.Background(), + ID: identityID, + } + params.SetTimeout(30 * time.Second) + resp, err := client.Identity.DetailIdentity(params, nil) + + if err != nil { + log.Fatal(err) + } + + // Enroll the identity + tkn, _, err := enroll.ParseToken(resp.GetPayload().Data.Enrollment.Ott.JWT) + if err != nil { + log.Fatal(err) + } + + flags := enroll.EnrollmentFlags{ + Token: tkn, + KeyAlg: "RSA", + } + conf, err := enroll.Enroll(flags) + + if err != nil { + log.Fatal(err) + } + + return conf +} + +var zitiContext ziti.Context + +func Dial(_ context.Context, _ string, addr string) (net.Conn, error) { + service := strings.Split(addr, ":")[0] // will always get passed host:port + return zitiContext.Dial(service) +} + +func createZitifiedHttpClient(idFile string) http.Client { + cfg, err := sdk_config.NewFromFile(idFile) + if err != nil { + panic(err) + } + zitiContext = ziti.NewContextWithConfig(cfg) + zitiTransport := http.DefaultTransport.(*http.Transport).Clone() // copy default transport + zitiTransport.DialContext = Dial //zitiDialContext.Dial + return http.Client{Transport: zitiTransport} +} + +// #################### Test Utils ############################# + +func createIdentity(client *rest_management_api_client.ZitiEdgeManagement, name string, + identType rest_model.IdentityType, isAdmin bool) *identity.CreateIdentityCreated { + i := &rest_model.IdentityCreate{ + Enrollment: &rest_model.IdentityCreateEnrollment{ + Ott: true, + }, + IsAdmin: &isAdmin, + Name: &name, + RoleAttributes: nil, + ServiceHostingCosts: nil, + ServiceHostingPrecedences: nil, + Tags: nil, + Type: &identType, + } + p := identity.NewCreateIdentityParams() + p.Identity = i + + // Create the identity + ident, err := client.Identity.CreateIdentity(p, nil) + if err != nil { + fmt.Println(err) + log.Fatal("Failed to create the identity") + } + + return ident +} + +func deleteIdentityByID(client *rest_management_api_client.ZitiEdgeManagement, id string) *identity.DeleteIdentityOK { + deleteParams := &identity.DeleteIdentityParams{ + ID: id, + } + deleteParams.SetTimeout(30 * time.Second) + resp, err := client.Identity.DeleteIdentity(deleteParams, nil) + if err != nil { + fmt.Println(err) + } + return resp +} + +func getConfigTypeByName(client *rest_management_api_client.ZitiEdgeManagement, name string) *rest_model.ConfigTypeDetail { + interceptFilter := "name=\"" + name + "\"" + configTypeParams := &api_client_config.ListConfigTypesParams{ + Filter: &interceptFilter, + Context: context.Background(), + } + interceptCTResp, err := client.Config.ListConfigTypes(configTypeParams, nil) + if err != nil { + log.Fatalf("Could not obtain %s config type", name) + fmt.Println(err) + } + return interceptCTResp.GetPayload().Data[0] +} + +func getIdentityByName(client *rest_management_api_client.ZitiEdgeManagement, name string) *rest_model.IdentityDetail { + filter := "name=\"" + name + "\"" + params := &identity.ListIdentitiesParams{ + Filter: &filter, + Context: context.Background(), + } + params.SetTimeout(30 * time.Second) + resp, err := client.Identity.ListIdentities(params, nil) + if err != nil { + log.Fatalf("Could not obtain an ID for the identity named %s", name) + fmt.Println(err) + } + return resp.GetPayload().Data[0] +} + +func getServiceByName(client *rest_management_api_client.ZitiEdgeManagement, name string) *rest_model.ServiceDetail { + filter := "name=\"" + name + "\"" + params := &service.ListServicesParams{ + Filter: &filter, + Context: context.Background(), + } + params.SetTimeout(30 * time.Second) + resp, err := client.Service.ListServices(params, nil) + if err != nil { + log.Fatalf("Could not obtain an ID for the service named %s", name) + fmt.Println(err) + } + return resp.GetPayload().Data[0] +} + +func getEdgeRouterByName(client *rest_management_api_client.ZitiEdgeManagement, name string) rest_model.EdgeRouterDetail { + filterValues := "name=\"" + name + "\"" + listParams := &edge_router.ListEdgeRoutersParams{ + Filter: &filterValues, + } + listParams.SetTimeout(30 * time.Second) + resp, err := client.EdgeRouter.ListEdgeRouters(listParams, nil) + if err != nil { + fmt.Println(err) + log.Fatal("Could not get edge router filtered by name") + } + return *resp.GetPayload().Data[0] +} + +func createEdgeRouterPolicy(client *rest_management_api_client.ZitiEdgeManagement, name string, roles rest_model.Roles) service_edge_router_policy.CreateServiceEdgeRouterPolicyCreated { + defaultSemantic := rest_model.SemanticAllOf + serp := &rest_model.ServiceEdgeRouterPolicyCreate{ + EdgeRouterRoles: roles, + Name: &name, + Semantic: &defaultSemantic, + ServiceRoles: roles, + } + serpParams := &service_edge_router_policy.CreateServiceEdgeRouterPolicyParams{ + Policy: serp, + Context: context.Background(), + } + serpParams.SetTimeout(30 * time.Second) + resp, err := client.ServiceEdgeRouterPolicy.CreateServiceEdgeRouterPolicy(serpParams, nil) + if err != nil { + fmt.Println(err) + log.Fatal("Could not create service edge router policy") + } + return *resp +} + +func createInterceptV1ServiceConfig(client *rest_management_api_client.ZitiEdgeManagement, name string, protocols []string, addresses []string, portRangeLow int, portRangeHigh int) rest_model.CreateLocation { + configTypeID := *getConfigTypeByName(client, "intercept.v1").ID + interceptData := map[string]interface{}{ + "protocols": protocols, + "addresses": addresses, + "portRanges": []map[string]interface{}{ + { + "low": portRangeLow, + "high": portRangeHigh, + }, + }, + } + confCreate := &rest_model.ConfigCreate{ + ConfigTypeID: &configTypeID, + Data: &interceptData, + Name: &name, + } + confParams := &api_client_config.CreateConfigParams{ + Config: confCreate, + Context: context.Background(), + } + confParams.SetTimeout(30 * time.Second) + resp, err := client.Config.CreateConfig(confParams, nil) + if err != nil { + fmt.Println(err) + log.Fatal("Could not create intercept.v1 service config") + } + return *resp.GetPayload().Data +} + +func createHostV1ServiceConfig(client *rest_management_api_client.ZitiEdgeManagement, name string, protocol string, address string, port int) rest_model.CreateLocation { + hostID := getConfigTypeByName(client, "host.v1").ID + hostData := map[string]interface{}{ + "protocol": protocol, + "address": address, + "port": port, + } + confCreate := &rest_model.ConfigCreate{ + ConfigTypeID: hostID, + Data: &hostData, + Name: &name, + } + confParams := &api_client_config.CreateConfigParams{ + Config: confCreate, + Context: context.Background(), + } + confParams.SetTimeout(30 * time.Second) + resp, err := client.Config.CreateConfig(confParams, nil) + if err != nil { + fmt.Println(err) + log.Fatal("Could not create host.v1 service config") + } + return *resp.GetPayload().Data +} + +func createService(client *rest_management_api_client.ZitiEdgeManagement, name string, serviceConfigs []string) rest_model.CreateLocation { + encryptOn := true // Default + serviceCreate := &rest_model.ServiceCreate{ + Configs: serviceConfigs, + EncryptionRequired: &encryptOn, + Name: &name, + } + serviceParams := &service.CreateServiceParams{ + Service: serviceCreate, + Context: context.Background(), + } + serviceParams.SetTimeout(30 * time.Second) + resp, err := client.Service.CreateService(serviceParams, nil) + if err != nil { + fmt.Println(err) + log.Fatal("Failed to create " + name + " service") + } + return *resp.GetPayload().Data +} + +func createServicePolicy(client *rest_management_api_client.ZitiEdgeManagement, name string, servType rest_model.DialBind, identityRoles rest_model.Roles, serviceRoles rest_model.Roles) rest_model.CreateLocation { + + defaultSemantic := rest_model.SemanticAllOf + servicePolicy := &rest_model.ServicePolicyCreate{ + IdentityRoles: identityRoles, + Name: &name, + Semantic: &defaultSemantic, + ServiceRoles: serviceRoles, + Type: &servType, + } + params := &service_policy.CreateServicePolicyParams{ + Policy: servicePolicy, + Context: context.Background(), + } + params.SetTimeout(30 * time.Second) + resp, err := client.ServicePolicy.CreateServicePolicy(params, nil) + if err != nil { + fmt.Println(err) + log.Fatal("Failed to create the " + name + " service policy") + } + + return *resp.GetPayload().Data +} + +func getTerminatorCountByRouterName(client *rest_management_api_client.ZitiEdgeManagement, routerName string) int { + filter := "router.name=\"" + routerName + "\"" + params := &terminator.ListTerminatorsParams{ + Filter: &filter, + Context: context.Background(), + } + + resp, err := client.Terminator.ListTerminators(params, nil) + if err != nil { + fmt.Println(err) + log.Fatal("An error occurred during terminator query") + } + + return len(resp.GetPayload().Data) +} + +func waitForTerminatorCountByRouterName(client *rest_management_api_client.ZitiEdgeManagement, routerName string, count int, timeout time.Duration) bool { + startTime := time.Now() + for { + if getTerminatorCountByRouterName(client, routerName) == count { + return true + } + if time.Since(startTime) >= timeout { + break + } + time.Sleep(1 * time.Second) + } + return false +} + +func deleteEdgeRouterPolicyByID(client *rest_management_api_client.ZitiEdgeManagement, id string) *edge_router_policy.DeleteEdgeRouterPolicyOK { + deleteParams := &edge_router_policy.DeleteEdgeRouterPolicyParams{ + ID: id, + } + deleteParams.SetTimeout(30 * time.Second) + resp, err := client.EdgeRouterPolicy.DeleteEdgeRouterPolicy(deleteParams, nil) + if err != nil { + fmt.Println(err) + } + return resp +} + +func deleteServiceEdgeRouterPolicyByID(client *rest_management_api_client.ZitiEdgeManagement, id string) *service_edge_router_policy.DeleteServiceEdgeRouterPolicyOK { + deleteParams := &service_edge_router_policy.DeleteServiceEdgeRouterPolicyParams{ + ID: id, + } + deleteParams.SetTimeout(30 * time.Second) + resp, err := client.ServiceEdgeRouterPolicy.DeleteServiceEdgeRouterPolicy(deleteParams, nil) + if err != nil { + fmt.Println(err) + } + return resp +} + +func deleteServiceConfigByID(client *rest_management_api_client.ZitiEdgeManagement, id string) *api_client_config.DeleteConfigOK { + deleteParams := &api_client_config.DeleteConfigParams{ + ID: id, + } + deleteParams.SetTimeout(30 * time.Second) + resp, err := client.Config.DeleteConfig(deleteParams, nil) + if err != nil { + fmt.Println(err) + } + return resp +} + +func deleteServiceByID(client *rest_management_api_client.ZitiEdgeManagement, id string) *service.DeleteServiceOK { + deleteParams := &service.DeleteServiceParams{ + ID: id, + } + deleteParams.SetTimeout(30 * time.Second) + resp, err := client.Service.DeleteService(deleteParams, nil) + if err != nil { + fmt.Println(err) + } + return resp +} + +func deleteServicePolicyByID(client *rest_management_api_client.ZitiEdgeManagement, id string) *service_policy.DeleteServicePolicyOK { + deleteParams := &service_policy.DeleteServicePolicyParams{ + ID: id, + } + deleteParams.SetTimeout(30 * time.Second) + resp, err := client.ServicePolicy.DeleteServicePolicy(deleteParams, nil) + if err != nil { + fmt.Println(err) + } + return resp +} + +func waitForController(hostport string) { + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + for { + resp, _ := http.Get(hostport) + if resp != nil && resp.StatusCode == 200 { + break + } + time.Sleep(1 * time.Second) + fmt.Println("Waiting for controller...") + } +} diff --git a/ziti/cmd/ziti/cmd/agent_controller_raft_join.go b/ziti/cmd/ziti/cmd/agent_controller_raft_join.go index 5532144d6..8aa981b28 100644 --- a/ziti/cmd/ziti/cmd/agent_controller_raft_join.go +++ b/ziti/cmd/ziti/cmd/agent_controller_raft_join.go @@ -18,10 +18,10 @@ package cmd import ( "fmt" + "github.com/openziti/agent" "github.com/openziti/channel/v2" "github.com/openziti/fabric/controller" "github.com/openziti/fabric/pb/mgmt_pb" - "github.com/openziti/agent" "github.com/openziti/identity" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/agentcli" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" @@ -33,7 +33,8 @@ import ( type AgentCtrlRaftJoinOptions struct { agentcli.AgentOptions - Voter bool + Voter bool + MemberId string } func NewAgentCtrlRaftJoin(p common.OptionsProvider) *cobra.Command { @@ -44,8 +45,8 @@ func NewAgentCtrlRaftJoin(p common.OptionsProvider) *cobra.Command { } cmd := &cobra.Command{ - Args: cobra.RangeArgs(2, 3), - Use: "raft-join ", + Args: cobra.RangeArgs(1, 2), + Use: "raft-join ", Run: func(cmd *cobra.Command, args []string) { options.Cmd = cmd options.Args = args @@ -55,6 +56,7 @@ func NewAgentCtrlRaftJoin(p common.OptionsProvider) *cobra.Command { } cmd.Flags().BoolVar(&options.Voter, "voter", true, "Is this member a voting member") + cmd.Flags().StringVar(&options.MemberId, "id", "", "The member id. If not provided, it will be looked up") return cmd } @@ -64,7 +66,7 @@ func (o *AgentCtrlRaftJoinOptions) Run() error { var addr string var err error - if len(o.Args) == 3 { + if len(o.Args) == 2 { addr, err = agent.ParseGopsAddress(o.Args) if err != nil { return err @@ -84,22 +86,25 @@ func (o *AgentCtrlRaftJoinOptions) makeRequest(conn net.Conn) error { } offset := 0 - if len(o.Args) == 3 { + if len(o.Args) == 2 { offset = 1 } msg := channel.NewMessage(int32(mgmt_pb.ContentType_RaftJoinRequestType), nil) - msg.PutStringHeader(controller.AgentIdHeader, o.Args[offset]) - msg.PutStringHeader(controller.AgentAddrHeader, o.Args[offset+1]) + msg.PutStringHeader(controller.AgentAddrHeader, o.Args[offset]) msg.PutBoolHeader(controller.AgentIsVoterHeader, o.Voter) + if o.MemberId != "" { + msg.PutStringHeader(controller.AgentIdHeader, o.MemberId) + } + reply, err := msg.WithTimeout(5 * time.Second).SendForReply(ch) if err != nil { return err } result := channel.UnmarshalResult(reply) if result.Success { - fmt.Println("success") + fmt.Println(result.Message) } else { fmt.Printf("error: %v\n", result.Message) } diff --git a/ziti/cmd/ziti/cmd/config_templates/router.yml b/ziti/cmd/ziti/cmd/config_templates/router.yml index 035905b12..a487968a4 100644 --- a/ziti/cmd/ziti/cmd/config_templates/router.yml +++ b/ziti/cmd/ziti/cmd/config_templates/router.yml @@ -21,7 +21,7 @@ link: {{ if .Router.IsPrivate }}#{{ end }} listeners: {{ if .Router.IsPrivate }}#{{ end }} - binding: transport {{ if .Router.IsPrivate }}#{{ end }} bind: tls:0.0.0.0:{{ .Router.Listener.BindPort }} -{{ if .Router.IsPrivate }}#{{ end }} advertise: tls:{{ .Router.Edge.Hostname }}:{{ .Router.Listener.BindPort }} +{{ if .Router.IsPrivate }}#{{ end }} advertise: tls:{{ .Router.Edge.AdvertisedHost }}:{{ .Router.Listener.BindPort }} {{ if .Router.IsPrivate }}#{{ end }} options: {{ if .Router.IsPrivate }}#{{ end }} outQueueSize: {{ .Router.Listener.OutQueueSize }} @@ -30,14 +30,15 @@ link: {{ if .Router.IsFabric }}#{{ end }} - binding: edge {{ if .Router.IsFabric }}#{{ end }} address: {{ if .Router.IsWss }}ws{{ else }}tls{{end}}:0.0.0.0:{{ .Router.Edge.Port }} {{ if .Router.IsFabric }}#{{ end }} options: -{{ if .Router.IsFabric }}#{{ end }} advertise: {{ .Router.Edge.Hostname }}:{{ if .Router.IsWss }}3023{{ else }}{{ .Router.Edge.Port }}{{ end }} +{{ if .Router.IsFabric }}#{{ end }} advertise: {{ .Router.Edge.AdvertisedHost }}:{{ if .Router.IsWss }}3023{{ else }}{{ .Router.Edge.Port }}{{ end }} {{ if .Router.IsFabric }}#{{ end }} connectTimeoutMs: {{ .Router.Listener.ConnectTimeout.Milliseconds }} -{{ if .Router.IsFabric }}#{{ end }} getSessionTimeout: {{ .Router.Listener.GetSessionTimeout.Seconds }}s -{{ if .Router.IsFabric }}#{{ end }} - binding: tunnel -{{ if .Router.IsFabric }}#{{ end }} options: -{{ if .Router.IsFabric }}#{{ end }} mode: host #tproxy|host - -{{ if or .Router.IsFabric }} +{{ if .Router.IsFabric }}#{{ end }} getSessionTimeout: {{ .Router.Listener.GetSessionTimeout.Seconds }} +{{ if or .Router.IsFabric (eq .Router.TunnelerMode "none") }}#{{ end }} - binding: tunnel +{{ if or .Router.IsFabric (eq .Router.TunnelerMode "none") }}#{{ end }} options: +{{ if or .Router.IsFabric (eq .Router.TunnelerMode "none") }}# mode: host #tproxy|host{{ else }} mode: {{ .Router.TunnelerMode }} #tproxy|host{{ end }} +{{ if and (not .Router.IsFabric) (eq .Router.TunnelerMode "tproxy") }} resolver: udp://{{ .Router.Edge.AdvertisedHost }}:53{{ end }} +{{ if and (not .Router.IsFabric) (eq .Router.TunnelerMode "tproxy") }} lanIf: {{ .Router.Edge.LanInterface }}{{ end }} +{{ if .Router.IsFabric -}} csr: country: US province: NC @@ -86,4 +87,5 @@ forwarder: xgressDialQueueLength: {{ .Router.Forwarder.XgressDialQueueLength }} xgressDialWorkerCount: {{ .Router.Forwarder.XgressDialWorkerCount }} linkDialQueueLength: {{ .Router.Forwarder.LinkDialQueueLength }} - linkDialWorkerCount: {{ .Router.Forwarder.LinkDialWorkerCount }} \ No newline at end of file + linkDialWorkerCount: {{ .Router.Forwarder.LinkDialWorkerCount }} + \ No newline at end of file diff --git a/ziti/cmd/ziti/cmd/create_config.go b/ziti/cmd/ziti/cmd/create_config.go index fc5bfea99..77f0bda76 100644 --- a/ziti/cmd/ziti/cmd/create_config.go +++ b/ziti/cmd/ziti/cmd/create_config.go @@ -17,6 +17,9 @@ package cmd import ( + "os" + "time" + "github.com/openziti/channel/v2" edge "github.com/openziti/edge/controller/config" fabCtrl "github.com/openziti/fabric/controller" @@ -28,8 +31,6 @@ import ( "github.com/openziti/ziti/ziti/cmd/ziti/constants" "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "os" - "time" ) const ( @@ -119,6 +120,7 @@ type RouterTemplateValues struct { IsPrivate bool IsFabric bool IsWss bool + TunnelerMode string IdentityCert string IdentityServerCert string IdentityKey string @@ -130,9 +132,11 @@ type RouterTemplateValues struct { } type EdgeRouterTemplateValues struct { - Hostname string - Port string - IPOverride string + Hostname string + Port string + IPOverride string + AdvertisedHost string + LanInterface string } type WSSRouterTemplateValues struct { diff --git a/ziti/cmd/ziti/cmd/create_config_environment.go b/ziti/cmd/ziti/cmd/create_config_environment.go index cb897086a..d6a996d1d 100644 --- a/ziti/cmd/ziti/cmd/create_config_environment.go +++ b/ziti/cmd/ziti/cmd/create_config_environment.go @@ -19,17 +19,18 @@ package cmd import ( _ "embed" "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "text/template" + cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates" "github.com/openziti/ziti/ziti/cmd/ziti/constants" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "os" - "path/filepath" - "runtime" - "strings" - "text/template" ) type EnvVariableTemplateData struct { @@ -112,6 +113,7 @@ func NewCmdCreateConfigEnvironment() *cobra.Command { {constants.ZitiRouterIdentityKeyVarName, constants.ZitiRouterIdentityKeyVarDescription, data.Router.IdentityKey}, {constants.ZitiRouterIdentityCAVarName, constants.ZitiRouterIdentityCAVarDescription, data.Router.IdentityCA}, {constants.ZitiEdgeRouterIPOverrideVarName, constants.ZitiEdgeRouterIPOverrideVarDescription, data.Router.Edge.IPOverride}, + {constants.ZitiEdgeRouterAdvertisedHostVarName, constants.ZitiEdgeRouterAdvertisedHostVarDescription, data.Router.Edge.AdvertisedHost}, {constants.ZitiCtrlListenerAddressVarName, constants.ZitiCtrlListenerAddressVarDescription, data.Controller.ListenerAddress}, {constants.ZitiCtrlAdvertisedAddressVarName, constants.ZitiCtrlAdvertisedAddressVarDescription, data.Controller.AdvertisedAddress}, {constants.ZitiEdgeCtrlListenerHostPortVarName, constants.ZitiEdgeCtrlListenerHostPortVarDescription, data.Controller.Edge.ListenerHostPort}, @@ -182,6 +184,7 @@ func NewCmdCreateConfigEnvironment() *cobra.Command { "%-40s %-50s %s\n"+ "%-40s %-50s %s\n"+ "%-40s %-50s %s\n"+ + "%-40s %-50s %s\n"+ "%-40s %-50s %s", constants.ZitiHomeVarName, constants.ZitiHomeVarDescription, data.ZitiHome, constants.ZitiCtrlPortVarName, constants.ZitiCtrlPortVarDescription, data.Controller.Port, @@ -198,6 +201,7 @@ func NewCmdCreateConfigEnvironment() *cobra.Command { constants.ZitiRouterIdentityKeyVarName, constants.ZitiRouterIdentityKeyVarDescription, data.Router.IdentityKey, constants.ZitiRouterIdentityCAVarName, constants.ZitiRouterIdentityCAVarDescription, data.Router.IdentityCA, constants.ZitiEdgeRouterIPOverrideVarName, constants.ZitiEdgeRouterIPOverrideVarDescription, data.Router.Edge.IPOverride, + constants.ZitiEdgeRouterAdvertisedHostVarName, constants.ZitiEdgeRouterAdvertisedHostVarDescription, data.Router.Edge.AdvertisedHost, constants.ZitiCtrlIdentityCertVarName, constants.ZitiCtrlIdentityCertVarDescription, data.Controller.IdentityCert, constants.ZitiCtrlIdentityServerCertVarName, constants.ZitiCtrlIdentityServerCertVarDescription, data.Controller.IdentityServerCert, constants.ZitiCtrlIdentityKeyVarName, constants.ZitiCtrlIdentityKeyVarDescription, data.Controller.IdentityKey, diff --git a/ziti/cmd/ziti/cmd/create_config_router.go b/ziti/cmd/ziti/cmd/create_config_router.go index bda8b58a1..05c27a850 100644 --- a/ziti/cmd/ziti/cmd/create_config_router.go +++ b/ziti/cmd/ziti/cmd/create_config_router.go @@ -18,11 +18,12 @@ package cmd import ( _ "embed" + "os" + "strings" + cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "os" - "strings" ) const ( @@ -33,9 +34,11 @@ const ( type CreateConfigRouterOptions struct { CreateConfigOptions - RouterName string - WssEnabled bool - IsPrivate bool + RouterName string + WssEnabled bool + IsPrivate bool + TunnelerMode string + LanInterface string } var routerOptions = CreateConfigRouterOptions{} diff --git a/ziti/cmd/ziti/cmd/create_config_router_common.go b/ziti/cmd/ziti/cmd/create_config_router_common.go index f01e916f2..0440384fb 100644 --- a/ziti/cmd/ziti/cmd/create_config_router_common.go +++ b/ziti/cmd/ziti/cmd/create_config_router_common.go @@ -18,9 +18,11 @@ package cmd import ( _ "embed" + "log" + "os" + cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/cmd/ziti/constants" - "os" ) func SetZitiRouterIdentity(r *RouterTemplateValues, routerName string) { @@ -29,21 +31,40 @@ func SetZitiRouterIdentity(r *RouterTemplateValues, routerName string) { SetZitiRouterIdentityKey(r, routerName) SetZitiRouterIdentityCA(r, routerName) - edgeRouterRawName := os.Getenv(constants.ZitiEdgeRouterRawNameVarName) - externalDNS := os.Getenv(constants.ExternalDNSVarName) - if externalDNS != "" { - r.Edge.Hostname = externalDNS - } else if edgeRouterRawName != "" { - r.Edge.Hostname = edgeRouterRawName - } else { - r.Edge.Hostname, _ = os.Hostname() - } - // Edge router IP override edgeRouterIPOverride := os.Getenv(constants.ZitiEdgeRouterIPOverrideVarName) if edgeRouterIPOverride != "" { r.Edge.IPOverride = edgeRouterIPOverride } + + externalDNS := os.Getenv(constants.ExternalDNSVarName) + edgeRouterRawName := os.Getenv(constants.ZitiEdgeRouterRawNameVarName) + if externalDNS != "" { + r.Edge.Hostname = externalDNS + r.Edge.AdvertisedHost = r.Edge.Hostname //not redundant set AdvertisedHost + } else if edgeRouterRawName != "" { + r.Edge.Hostname = edgeRouterRawName + r.Edge.AdvertisedHost = r.Edge.Hostname //not redundant set AdvertisedHost + } else { + r.Edge.Hostname, _ = os.Hostname() + r.Edge.AdvertisedHost = r.Edge.Hostname //not redundant set AdvertisedHost + } + + advertisedHost := os.Getenv(constants.ZitiEdgeRouterAdvertisedHostVarName) + if advertisedHost != "" { + if advertisedHost != edgeRouterIPOverride && advertisedHost != r.Edge.AdvertisedHost { + log.Panicf("if %s[%s] is supplied, it *MUST* match the %s[%s] or resolved hostname[%s]", constants.ZitiEdgeRouterAdvertisedHostVarName, advertisedHost, constants.ZitiEdgeRouterIPOverrideVarName, edgeRouterIPOverride, r.Edge.Hostname) + } + r.Edge.AdvertisedHost = advertisedHost //finally override AdvertisedHost if provided + } else { + if externalDNS != "" || edgeRouterRawName != "" { + r.Edge.AdvertisedHost = r.Edge.Hostname + } else if edgeRouterIPOverride != "" { + r.Edge.AdvertisedHost = edgeRouterIPOverride + } else { + r.Edge.AdvertisedHost = r.Edge.Hostname //not redundant set AdvertisedHost + } + } } func SetZitiRouterIdentityCert(r *RouterTemplateValues, routerName string) { val := os.Getenv(constants.ZitiRouterIdentityCertVarName) diff --git a/ziti/cmd/ziti/cmd/create_config_router_edge.go b/ziti/cmd/ziti/cmd/create_config_router_edge.go index 2ea27b9e3..be0becc08 100644 --- a/ziti/cmd/ziti/cmd/create_config_router_edge.go +++ b/ziti/cmd/ziti/cmd/create_config_router_edge.go @@ -18,24 +18,34 @@ package cmd import ( _ "embed" + "os" + "path/filepath" + "strings" + "text/template" + cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "os" - "path/filepath" - "strings" - "text/template" ) const ( - optionWSS = "wss" - defaultWSS = false - wssDescription = "Create an edge router config with wss enabled" - optionPrivate = "private" - defaultPrivate = false - privateDescription = "Create a private router config" + optionWSS = "wss" + defaultWSS = false + wssDescription = "Create an edge router config with wss enabled" + optionPrivate = "private" + defaultPrivate = false + privateDescription = "Create a private router config" + tproxyTunMode = "tproxy" + hostTunMode = "host" + noneTunMode = "none" + optionTunnelerMode = "tunnelerMode" + defaultTunnelerMode = hostTunMode + tunnelerModeDescription = "Specify tunneler mode \"" + noneTunMode + "\", \"" + hostTunMode + "\", or \"" + tproxyTunMode + "\"" + optionLanInterface = "lanInterface" + defaultLanInterface = "" + lanInterfaceDescription = "The interface on host of the router to insert iptables ingress filter rules" ) var ( @@ -64,6 +74,8 @@ func NewCmdCreateConfigRouterEdge() *cobra.Command { PreRun: func(cmd *cobra.Command, args []string) { data.Router.IsWss = routerOptions.WssEnabled data.Router.IsPrivate = routerOptions.IsPrivate + data.Router.TunnelerMode = routerOptions.TunnelerMode + data.Router.Edge.LanInterface = routerOptions.LanInterface }, Run: func(cmd *cobra.Command, args []string) { routerOptions.Cmd = cmd @@ -82,6 +94,8 @@ func NewCmdCreateConfigRouterEdge() *cobra.Command { func (options *CreateConfigRouterOptions) addEdgeFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&options.WssEnabled, optionWSS, defaultWSS, wssDescription) cmd.Flags().BoolVar(&options.IsPrivate, optionPrivate, defaultPrivate, privateDescription) + cmd.PersistentFlags().StringVarP(&options.TunnelerMode, optionTunnelerMode, "", defaultTunnelerMode, tunnelerModeDescription) + cmd.PersistentFlags().StringVarP(&options.LanInterface, optionLanInterface, "", defaultLanInterface, lanInterfaceDescription) cmd.PersistentFlags().StringVarP(&options.RouterName, optionRouterName, "n", "", "name of the router") err := cmd.MarkPersistentFlagRequired(optionRouterName) if err != nil { @@ -96,6 +110,11 @@ func (options *CreateConfigRouterOptions) runEdgeRouter(data *ConfigTemplateValu return errors.New("Flags for private and wss configs are mutually exclusive. You must choose private or wss, not both") } + // Make sure the tunneler mode is valid + if options.TunnelerMode != hostTunMode && options.TunnelerMode != tproxyTunMode && options.TunnelerMode != noneTunMode { + return errors.New("Unknown tunneler mode [" + options.TunnelerMode + "] provided, should be \"" + noneTunMode + "\", \"" + hostTunMode + "\", or \"" + tproxyTunMode + "\"") + } + tmpl, err := template.New("edge-router-config").Parse(routerConfigEdgeTemplate) if err != nil { return err diff --git a/ziti/cmd/ziti/cmd/create_config_router_edge_test.go b/ziti/cmd/ziti/cmd/create_config_router_edge_test.go new file mode 100644 index 000000000..bebf5d2a4 --- /dev/null +++ b/ziti/cmd/ziti/cmd/create_config_router_edge_test.go @@ -0,0 +1,277 @@ +package cmd + +import ( + "github.com/openziti/ziti/ziti/cmd/ziti/constants" + "github.com/stretchr/testify/assert" + "os" + "testing" + "time" +) + +var defaultArgs = []string{"edge", "--routerName", "test-router"} +var testHostname, _ = os.Hostname() + +func setEnvByMap[K string, V string](m map[K]V) { + for k, v := range m { + os.Setenv(string(k), string(v)) + } +} + +func execCreateConfigCommand(args []string, keys map[string]string) { + // Setup options + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + + setEnvByMap(keys) + // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) + cmd := NewCmdCreateConfigRouter() + cmd.SetArgs(args) + _ = captureOutput(func() { + _ = cmd.Execute() + }) +} + +func TestEdgeRouterAdvertised(t *testing.T) { + clearOptionsAndTemplateData() + routerAdvHostIp := "192.168.10.10" + routerAdvHostDns := "controller01.zitinetwork.example.org" + keys := map[string]string{ + "ZITI_CTRL_PORT": "80", + "ZITI_EDGE_ROUTER_PORT": "443", + } + execCreateConfigCommand(defaultArgs, keys) + assert.Equal(t, testHostname, data.Router.Edge.AdvertisedHost, nil) + + keys["ZITI_EDGE_ROUTER_RAWNAME"] = routerAdvHostDns + execCreateConfigCommand(defaultArgs, keys) + assert.Equal(t, routerAdvHostDns, data.Router.Edge.AdvertisedHost, nil) + + keys["ZITI_EDGE_ROUTER_RAWNAME"] = "" + keys["ZITI_EDGE_ROUTER_IP_OVERRIDE"] = routerAdvHostIp + execCreateConfigCommand(defaultArgs, keys) + assert.Equal(t, routerAdvHostIp, data.Router.Edge.AdvertisedHost, nil) + + keys["ZITI_EDGE_ROUTER_IP_OVERRIDE"] = "" + keys["EXTERNAL_DNS"] = routerAdvHostDns + execCreateConfigCommand(defaultArgs, keys) + assert.Equal(t, routerAdvHostDns, data.Router.Edge.AdvertisedHost, nil) + + keys["ZITI_EDGE_ROUTER_ADVERTISED_HOST"] = routerAdvHostIp + keys["ZITI_EDGE_ROUTER_IP_OVERRIDE"] = routerAdvHostIp + execCreateConfigCommand(defaultArgs, keys) + assert.Equal(t, routerAdvHostIp, data.Router.Edge.AdvertisedHost, nil) + + keys["ZITI_EDGE_ROUTER_ADVERTISED_HOST"] = routerAdvHostDns + keys["EXTERNAL_DNS"] = routerAdvHostDns + execCreateConfigCommand(defaultArgs, keys) + assert.Equal(t, routerAdvHostDns, data.Router.Edge.AdvertisedHost, nil) +} + +func TestTunnelerEnabledByDefault(t *testing.T) { + // Setup options + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + + // Create and run the CLI command without the tunnel flag + config := createRouterConfig([]string{"edge", "--routerName", "myRouter"}) + + // Confirm tunneler is enabled in config output + foundTunnel := false + for i := 0; i < len(config.Listeners); i++ { + if config.Listeners[i].Binding == "tunnel" { + foundTunnel = true + } + } + assert.True(t, foundTunnel, "Expected to find tunnel listener binding but it was not found") +} + +func TestTunnelerNoneMode(t *testing.T) { + // Setup options + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + + // Create and run the CLI command with the disable tunnel flag + config := createRouterConfig([]string{"edge", "--routerName", "myRouter", "--tunnelerMode", "none"}) + + // Expect tunneler mode to be "none" mode + assert.Equal(t, noneTunMode, data.Router.TunnelerMode, "Expected tunneler mode to be %s but found %s", noneTunMode, data.Router.TunnelerMode) + + // Confirm tunneler is disabled in config output + foundTunnel := false + for i := 0; i < len(config.Listeners); i++ { + if config.Listeners[i].Binding == "tunnel" { + foundTunnel = true + } + } + assert.False(t, foundTunnel, "Tunnel listener binding was not expected but it was found") +} + +func TestTunnelerHostModeIsDefault(t *testing.T) { + // Setup options + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + + // Create and run the CLI command without the tunnel flag + config := createRouterConfig([]string{"edge", "--routerName", "myRouter"}) + + // Expect tunneler mode to be "host" mode + assert.Equal(t, hostTunMode, data.Router.TunnelerMode, "Expected tunneler mode to be %s but found %s", hostTunMode, data.Router.TunnelerMode) + + // Confirm tunneler mode in config is set to host mode + for i := 0; i < len(config.Listeners); i++ { + if config.Listeners[i].Binding == "tunnel" { + assert.Equal(t, hostTunMode, config.Listeners[i].Options.Mode, "Expected tunneler mode to be %s but found %s in config output", hostTunMode, data.Router.TunnelerMode) + } + } +} + +func TestTunnelerTproxyMode(t *testing.T) { + // Setup options + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + + // Create and run the CLI command without the tunnel flag + config := createRouterConfig([]string{"edge", "--routerName", "myRouter", "--tunnelerMode", tproxyTunMode}) + + // Expect tunneler mode to be "host" mode + assert.Equal(t, tproxyTunMode, data.Router.TunnelerMode, "Expected tunneler mode to be %s but found %s", tproxyTunMode, data.Router.TunnelerMode) + + // Confirm tunneler mode in config is set to host mode + for i := 0; i < len(config.Listeners); i++ { + if config.Listeners[i].Binding == "tunnel" { + assert.Equal(t, tproxyTunMode, config.Listeners[i].Options.Mode, "Expected tunneler mode to be %s but found %s in config output", tproxyTunMode, data.Router.TunnelerMode) + } + } +} + +func TestTunnelerInvalidMode(t *testing.T) { + invalidMode := "invalidMode" + + expectedErrorMsg := "Unknown tunneler mode [" + invalidMode + "] provided, should be \"" + noneTunMode + "\", \"" + hostTunMode + "\", or \"" + tproxyTunMode + "\"" + + // Create the options with both flags set to true + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + routerOptions.TunnelerMode = invalidMode + + err := routerOptions.runEdgeRouter(&ConfigTemplateValues{}) + + assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err) +} + +func TestPrivateEdgeRouterNotAdvertising(t *testing.T) { + clearOptionsAndTemplateData() + + // Create and run the CLI command + config := createRouterConfig([]string{"edge", "--routerName", "myRouter", "--private"}) + + // Expect that the config values are represented correctly + assert.Equal(t, 0, len(config.Link.Listeners), "Expected zero link listeners for private edge router, found a non-zero value") +} + +func TestBlankEdgeRouterNameBecomesHostname(t *testing.T) { + hostname, _ := os.Hostname() + blank := "" + + // Setup options with blank router name + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + routerOptions.RouterName = blank + + // Check that template values is a blank name + assert.Equal(t, blank, data.Router.Name, "Mismatch router name, expected %s but got %s", "", hostname) + + // Create and run the CLI command + _ = createRouterConfig([]string{"edge", "--routerName", blank}) + + // Check that the blank name was replaced with hostname in the template values + assert.Equal(t, hostname, data.Router.Name, "Mismatch router name, expected %s but got %s", "", hostname) + +} + +func TestEdgeRouterCannotBeWSSAndPrivate(t *testing.T) { + expectedErrorMsg := "Flags for private and wss configs are mutually exclusive. You must choose private or wss, not both" + + // Create the options with both flags set to true + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + routerOptions.IsPrivate = true + routerOptions.WssEnabled = true + + err := routerOptions.runEdgeRouter(&ConfigTemplateValues{}) + + assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err) +} + +func TestEdgeRouterOutputPathDoesNotExist(t *testing.T) { + expectedErrorMsg := "stat /IDoNotExist: no such file or directory" + + // Set the router options + clearOptionsAndTemplateData() + routerOptions.TunnelerMode = defaultTunnelerMode + routerOptions.RouterName = "MyEdgeRouter" + routerOptions.Output = "/IDoNotExist/MyEdgeRouter.yaml" + + err := routerOptions.runEdgeRouter(&ConfigTemplateValues{}) + + assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err) +} + +func TestExecuteCreateConfigRouterEdgeHasNonBlankTemplateValues(t *testing.T) { + routerName := "MyEdgeRouter" + expectedNonEmptyStringFields := []string{".ZitiHome", ".Hostname", ".Router.Name", ".Router.IdentityCert", ".Router.IdentityServerCert", ".Router.IdentityKey", ".Router.IdentityCA", ".Router.Edge.Hostname", ".Router.Edge.Port"} + expectedNonEmptyStringValues := []*string{&data.ZitiHome, &data.Hostname, &data.Router.Name, &data.Router.IdentityCert, &data.Router.IdentityServerCert, &data.Router.IdentityKey, &data.Router.IdentityCA, &data.Router.Edge.Hostname, &data.Router.Edge.Port} + expectedNonEmptyIntFields := []string{".Router.Listener.BindPort", ".Router.Listener.OutQueueSize", ".Router.Wss.ReadBufferSize", ".Router.Wss.WriteBufferSize", ".Router.Forwarder.XgressDialQueueLength", ".Router.Forwarder.XgressDialWorkerCount", ".Router.Forwarder.LinkDialQueueLength", ".Router.Forwarder.LinkDialWorkerCount"} + expectedNonEmptyIntValues := []*int{&data.Router.Listener.BindPort, &data.Router.Listener.OutQueueSize, &data.Router.Wss.ReadBufferSize, &data.Router.Wss.WriteBufferSize, &data.Router.Forwarder.XgressDialQueueLength, &data.Router.Forwarder.XgressDialWorkerCount, &data.Router.Forwarder.LinkDialQueueLength, &data.Router.Forwarder.LinkDialWorkerCount} + expectedNonEmptyTimeFields := []string{".Router.Listener.ConnectTimeout", "Router.Listener.GetSessionTimeout", ".Router.Wss.WriteTimeout", ".Router.Wss.ReadTimeout", ".Router.Wss.IdleTimeout", ".Router.Wss.PongTimeout", ".Router.Wss.PingInterval", ".Router.Wss.HandshakeTimeout", ".Router.Forwarder.LatencyProbeInterval"} + expectedNonEmptyTimeValues := []*time.Duration{&data.Router.Listener.ConnectTimeout, &data.Router.Listener.GetSessionTimeout, &data.Router.Wss.WriteTimeout, &data.Router.Wss.ReadTimeout, &data.Router.Wss.IdleTimeout, &data.Router.Wss.PongTimeout, &data.Router.Wss.PingInterval, &data.Router.Wss.HandshakeTimeout, &data.Router.Forwarder.LatencyProbeInterval} + + // Create and run the CLI command + _ = createRouterConfig([]string{"edge", "--routerName", routerName}) + + // Check that the expected string template values are not blank + for field, value := range expectedNonEmptyStringValues { + assert.NotEqualf(t, "", *value, expectedNonEmptyStringFields[field]+" should be a non-blank value") + } + + // Check that the expected int template values are not zero + for field, value := range expectedNonEmptyIntValues { + assert.NotZero(t, *value, expectedNonEmptyIntFields[field]+" should be a non-zero value") + } + + // Check that the expected time.Duration template values are not zero + for field, value := range expectedNonEmptyTimeValues { + assert.NotZero(t, *value, expectedNonEmptyTimeFields[field]+" should be a non-zero value") + } +} + +func TestEdgeRouterIPOverrideIsConsumed(t *testing.T) { + routerName := "MyFabricRouter" + blank := "" + externalIP := "123.456.78.9" + + // Setup options + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + + // Set the env variable to non-empty value + _ = os.Setenv(constants.ZitiEdgeRouterIPOverrideVarName, externalIP) + + // Check that template value is currently blank + assert.Equal(t, blank, data.Router.Edge.IPOverride, "Mismatch router IP override, expected %s but got %s", blank, data.Router.Edge.IPOverride) + + // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) + config := createRouterConfig([]string{"edge", "--routerName", routerName}) + + // Check that the template values now contains the custom external IP override value + assert.Equal(t, externalIP, data.Router.Edge.IPOverride, "Mismatch router IP override, expected %s but got %s", externalIP, data.Router.Edge.IPOverride) + + // Check that the config output has the IP + found := false + for i := 1; i < len(config.Edge.Csr.Sans.Ip); i++ { + if config.Edge.Csr.Sans.Ip[i] == externalIP { + found = true + } + } + assert.True(t, found, "Expected value not found; expected to find value of "+constants.ZitiEdgeRouterIPOverrideVarName+" in edge router config output.") +} diff --git a/ziti/cmd/ziti/cmd/create_config_router_fabric_test.go b/ziti/cmd/ziti/cmd/create_config_router_fabric_test.go new file mode 100644 index 000000000..2b1e0cf8a --- /dev/null +++ b/ziti/cmd/ziti/cmd/create_config_router_fabric_test.go @@ -0,0 +1,111 @@ +package cmd + +import ( + "github.com/openziti/ziti/ziti/cmd/ziti/constants" + "github.com/stretchr/testify/assert" + "os" + "testing" + "time" +) + +func TestExecuteCreateConfigRouterFabricHasNonBlankTemplateValues(t *testing.T) { + routerName := "MyFabricRouter" + expectedNonEmptyStringFields := []string{".ZitiHome", ".Hostname", ".Router.Name", ".Router.IdentityCert", ".Router.IdentityServerCert", ".Router.IdentityKey", ".Router.IdentityCA", ".Router.Edge.Hostname", ".Router.Edge.Port"} + expectedNonEmptyStringValues := []*string{&data.ZitiHome, &data.Hostname, &data.Router.Name, &data.Router.IdentityCert, &data.Router.IdentityServerCert, &data.Router.IdentityKey, &data.Router.IdentityCA, &data.Router.Edge.Hostname, &data.Router.Edge.Port} + expectedNonEmptyIntFields := []string{".Router.Listener.BindPort", ".Router.Listener.OutQueueSize", ".Router.Wss.ReadBufferSize", ".Router.Wss.WriteBufferSize", ".Router.Forwarder.XgressDialQueueLength", ".Router.Forwarder.XgressDialWorkerCount", ".Router.Forwarder.LinkDialQueueLength", ".Router.Forwarder.LinkDialWorkerCount"} + expectedNonEmptyIntValues := []*int{&data.Router.Listener.BindPort, &data.Router.Listener.OutQueueSize, &data.Router.Wss.ReadBufferSize, &data.Router.Wss.WriteBufferSize, &data.Router.Forwarder.XgressDialQueueLength, &data.Router.Forwarder.XgressDialWorkerCount, &data.Router.Forwarder.LinkDialQueueLength, &data.Router.Forwarder.LinkDialWorkerCount} + expectedNonEmptyTimeFields := []string{".Router.Listener.ConnectTimeout", "Router.Listener.GetSessionTimeout", ".Router.Wss.WriteTimeout", ".Router.Wss.ReadTimeout", ".Router.Wss.IdleTimeout", ".Router.Wss.PongTimeout", ".Router.Wss.PingInterval", ".Router.Wss.HandshakeTimeout", ".Router.Forwarder.LatencyProbeInterval"} + expectedNonEmptyTimeValues := []*time.Duration{&data.Router.Listener.ConnectTimeout, &data.Router.Listener.GetSessionTimeout, &data.Router.Wss.WriteTimeout, &data.Router.Wss.ReadTimeout, &data.Router.Wss.IdleTimeout, &data.Router.Wss.PongTimeout, &data.Router.Wss.PingInterval, &data.Router.Wss.HandshakeTimeout, &data.Router.Forwarder.LatencyProbeInterval} + + // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) + _ = createRouterConfig([]string{"fabric", "--routerName", routerName}) + + // Check that the expected string template values are not blank + for field, value := range expectedNonEmptyStringValues { + assert.NotEqualf(t, "", *value, expectedNonEmptyStringFields[field]+" should be a non-blank value") + } + + // Check that the expected int template values are not zero + for field, value := range expectedNonEmptyIntValues { + assert.NotZero(t, *value, expectedNonEmptyIntFields[field]+" should be a non-zero value") + } + + // Check that the expected time.Duration template values are not zero + for field, value := range expectedNonEmptyTimeValues { + assert.NotZero(t, *value, expectedNonEmptyTimeFields[field]+" should be a non-zero value") + } +} + +func TestFabricRouterIPOverrideIsConsumed(t *testing.T) { + routerName := "MyFabricRouter" + blank := "" + externalIP := "123.456.78.9" + + // Setup options + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + + // Set the env variable to non-empty value + _ = os.Setenv(constants.ZitiEdgeRouterIPOverrideVarName, externalIP) + + // Check that template value is currently blank + assert.Equal(t, blank, data.Router.Edge.IPOverride, "Mismatch router IP override, expected %s but got %s", blank, data.Router.Edge.IPOverride) + + // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) + config := createRouterConfig([]string{"fabric", "--routerName", routerName}) + + // Check that the template values now contains the custom external IP override value + assert.Equal(t, externalIP, data.Router.Edge.IPOverride, "Mismatch router IP override, expected %s but got %s", externalIP, data.Router.Edge.IPOverride) + + // Check that the config output has the IP + found := false + for i := 1; i < len(config.Csr.Sans.Ip); i++ { + if config.Csr.Sans.Ip[i] == externalIP { + found = true + } + } + assert.True(t, found, "Expected value not found; expected to find value of "+constants.ZitiEdgeRouterIPOverrideVarName+" in fabric router config output.") +} + +func TestFabricRouterHasNoListeners(t *testing.T) { + clearOptionsAndTemplateData() + + // Create and run the CLI command + config := createRouterConfig([]string{"fabric", "--routerName", "myRouter"}) + + // Expect that the config values are represented correctly + assert.Equal(t, 0, len(config.Listeners), "Expected zero listeners for fabric router, found a non-zero value") +} + +func TestBlankFabricRouterNameBecomesHostname(t *testing.T) { + hostname, _ := os.Hostname() + blank := "" + + // Create the options with empty router name + clearOptionsAndTemplateData() + routerOptions.Output = defaultOutput + routerOptions.RouterName = blank + + // Check that template values is a blank name + assert.Equal(t, blank, data.Router.Name, "Mismatch router name, expected %s but got %s", "", hostname) + + // Create and run the CLI command + _ = createRouterConfig([]string{"fabric", "--routerName", blank}) + + // Check that the blank name was replaced with hostname in the template values + assert.Equal(t, hostname, data.Router.Name, "Mismatch router name, expected %s but got %s", "", hostname) + +} + +func TestFabricRouterOutputPathDoesNotExist(t *testing.T) { + expectedErrorMsg := "stat /IDoNotExist: no such file or directory" + + // Set the router options + clearOptionsAndTemplateData() + routerOptions.RouterName = "MyFabricRouter" + routerOptions.Output = "/IDoNotExist/MyFabricRouter.yaml" + + err := routerOptions.runFabricRouter(&ConfigTemplateValues{}) + + assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err) +} diff --git a/ziti/cmd/ziti/cmd/create_config_router_test.go b/ziti/cmd/ziti/cmd/create_config_router_test.go index 7bf3d7e7f..81ad11d25 100644 --- a/ziti/cmd/ziti/cmd/create_config_router_test.go +++ b/ziti/cmd/ziti/cmd/create_config_router_test.go @@ -1,105 +1,135 @@ package cmd import ( + "fmt" "github.com/openziti/ziti/ziti/cmd/ziti/constants" "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" "os" - "strings" "testing" - "time" ) +/* BEGIN Controller config template structure */ + +type RouterConfig struct { + V string `yaml:"v"` + Identity Identity `yaml:"identity"` + Ctrl RouterCtrl `yaml:"ctrl"` + Link Link `yaml:"link"` + Listeners []Listener `yaml:"listeners"` + Csr Csr `yaml:"csr"` + Edge RouterEdge `yaml:"edge"` + Transport Transport `yaml:"transport"` + Forwarder Forwarder `yaml:"forwarder"` +} + +type RouterCtrl struct { + Endpoint string `yaml:"endpoint"` +} + +type Link struct { + Dialers []Dialer `yaml:"dialers"` + Listeners []Listener `yaml:"listeners"` + Timeout string `yaml:"timeout"` + InitialDelay string `yaml:"initialDelay"` +} + +type Dialer struct { + Binding string `yaml:"binding"` +} + +type Listener struct { + Binding string `yaml:"binding"` + Bind string `yaml:"bind"` + Advertise string `yaml:"advertise"` + Address string `yaml:"address"` + Options ListenerOptions `yaml:"options"` +} + +type ListenerOptions struct { + Advertise string `yaml:"advertise"` + ConnectTimeout int `yaml:"connectTimeoutMs"` + GetSessionTimeout int `yaml:"getSessionTimeout"` + Mode string `yaml:"mode"` + Resolver string `yaml:"resolver"` + LanIf []string `yaml:"lanIf"` + OutQueueSize string `yaml:"outQueueSize"` +} + +type RouterEdge struct { + Csr Csr `yaml:"csr"` +} + +type Csr struct { + Country string `yaml:"country"` + Province string `yaml:"province"` + Locality string `yaml:"locality"` + Organization string `yaml:"organization"` + OrganizationalUnit string `yaml:"organizationalUnit"` + Sans Sans `yaml:"sans"` +} + +type Sans struct { + Dns []string `yaml:"dns"` + Ip []string `yaml:"ip"` +} + +type Transport struct { + Ws Ws `yaml:"ws"` +} + +type Ws struct { + writeTimeout int `yaml:"writeTimeout"` + readTimeout int `yaml:"readTimeout"` + idleTimeout int `yaml:"idleTimeout"` + pongTimeout int `yaml:"pongTimeout"` + pingInterval int `yaml:"pingInterval"` + handshakeTimeout int `yaml:"handshakeTimeout"` + readBufferSize int `yaml:"readBufferSize"` + writeBufferSize int `yaml:"writeBufferSize"` + enableCompression string `yaml:"enableCompression"` + server_cert string `yaml:"server_Cert"` + key string `yaml:"key"` +} + +type Forwarder struct { + LatencyProbeInterval int `yaml:"latencyProbeInterval"` + XgressDialQueueLength int `yaml:"xgressDialQueueLength"` + XgressDialWorkerCount int `yaml:"xgressDialWorkerCount"` + LinkDialQueueLength int `yaml:"linkDialQueueLength"` + LinkDialWorkerCount int `yaml:"linkDialWorkerCount"` +} + +/* END Controller config template structure */ + +func createRouterConfig(args []string) RouterConfig { + // Create and run the CLI command + cmd := NewCmdCreateConfigRouter() + cmd.SetArgs(args) + // captureOutput is used to consume output, otherwise config prints to stdout along with test results + output := captureOutput(func() { + _ = cmd.Execute() + }) + + // Convert output to config struct + configStruct := RouterConfig{} + err2 := yaml.Unmarshal([]byte(output), &configStruct) + if err2 != nil { + fmt.Println(err2) + } + return configStruct +} + func clearOptionsAndTemplateData() { routerOptions = CreateConfigRouterOptions{} data = &ConfigTemplateValues{} -} -func TestBlankEdgeRouterNameBecomesHostname(t *testing.T) { - hostname, _ := os.Hostname() - blank := "" - - // Setup options with blank router name - clearOptionsAndTemplateData() - routerOptions.Output = defaultOutput - routerOptions.RouterName = blank - - // Check that template values is a blank name - assert.Equal(t, blank, data.Router.Name, "Mismatch router name, expected %s but got %s", "", hostname) - - // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) - cmd := NewCmdCreateConfigRouter() - cmd.SetArgs([]string{"edge", "--routerName", blank}) - _ = captureOutput(func() { - _ = cmd.Execute() - }) - - // Check that the blank name was replaced with hostname in the template values - assert.Equal(t, hostname, data.Router.Name, "Mismatch router name, expected %s but got %s", "", hostname) - -} - -func TestBlankFabricRouterNameBecomesHostname(t *testing.T) { - hostname, _ := os.Hostname() - blank := "" - - // Create the options with empty router name - clearOptionsAndTemplateData() - routerOptions.Output = defaultOutput - routerOptions.RouterName = blank - - // Check that template values is a blank name - assert.Equal(t, blank, data.Router.Name, "Mismatch router name, expected %s but got %s", "", hostname) - - // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) - cmd := NewCmdCreateConfigRouter() - cmd.SetArgs([]string{"fabric", "--routerName", blank}) - _ = captureOutput(func() { - _ = cmd.Execute() - }) - - // Check that the blank name was replaced with hostname in the template values - assert.Equal(t, hostname, data.Router.Name, "Mismatch router name, expected %s but got %s", "", hostname) - -} - -func TestEdgeRouterCannotBeWSSAndPrivate(t *testing.T) { - expectedErrorMsg := "Flags for private and wss configs are mutually exclusive. You must choose private or wss, not both" - - // Create the options with both flags set to true - clearOptionsAndTemplateData() - routerOptions.Output = defaultOutput - routerOptions.IsPrivate = true - routerOptions.WssEnabled = true - - err := routerOptions.runEdgeRouter(&ConfigTemplateValues{}) - - assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err) -} - -func TestEdgeRouterOutputPathDoesNotExist(t *testing.T) { - expectedErrorMsg := "stat /IDoNotExist: no such file or directory" - - // Set the router options - clearOptionsAndTemplateData() - routerOptions.RouterName = "MyEdgeRouter" - routerOptions.Output = "/IDoNotExist/MyEdgeRouter.yaml" - - err := routerOptions.runEdgeRouter(&ConfigTemplateValues{}) - - assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err) -} - -func TestFabricRouterOutputPathDoesNotExist(t *testing.T) { - expectedErrorMsg := "stat /IDoNotExist: no such file or directory" - - // Set the router options - clearOptionsAndTemplateData() - routerOptions.RouterName = "MyFabricRouter" - routerOptions.Output = "/IDoNotExist/MyFabricRouter.yaml" - - err := routerOptions.runFabricRouter(&ConfigTemplateValues{}) - - assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err) + // Unset environment variables + envVars := getZitiEnvironmentVariables() + for i := 0; i < len(envVars); i++ { + _ = os.Unsetenv(envVars[i]) + } + _ = os.Unsetenv(constants.ExternalDNSVarName) } func TestSetZitiRouterIdentityCertDefault(t *testing.T) { @@ -204,6 +234,7 @@ func TestSetZitiRouterIdentityCACustom(t *testing.T) { func TestSetZitiRouterIdentitySetsAllIdentitiesAndEdgeRouterRawName(t *testing.T) { // Setup + clearOptionsAndTemplateData() expectedRawName := "MyEdgeRouterRawName" blank := "" rtv := &RouterTemplateValues{} @@ -230,6 +261,7 @@ func TestSetZitiRouterIdentitySetsAllIdentitiesAndEdgeRouterRawName(t *testing.T func TestSetZitiRouterIdentitySetsAllIdentitiesAndEdgeRouterRawNameToHostWhenBlank(t *testing.T) { // Setup + clearOptionsAndTemplateData() expectedRawName, _ := os.Hostname() blank := "" rtv := &RouterTemplateValues{} @@ -253,96 +285,3 @@ func TestSetZitiRouterIdentitySetsAllIdentitiesAndEdgeRouterRawNameToHostWhenBla assert.NotEqualf(t, blank, rtv.IdentityKey, "Router.IdentityCert expected to have a value, instead it was blank") assert.NotEqualf(t, blank, rtv.IdentityCA, "Router.IdentityCert expected to have a value, instead it was blank") } - -func TestExecuteCreateConfigRouterEdgeHasNonBlankTemplateValues(t *testing.T) { - routerName := "MyEdgeRouter" - expectedNonEmptyStringFields := []string{".ZitiHome", ".Hostname", ".Router.Name", ".Router.IdentityCert", ".Router.IdentityServerCert", ".Router.IdentityKey", ".Router.IdentityCA", ".Router.Edge.Hostname", ".Router.Edge.Port"} - expectedNonEmptyStringValues := []*string{&data.ZitiHome, &data.Hostname, &data.Router.Name, &data.Router.IdentityCert, &data.Router.IdentityServerCert, &data.Router.IdentityKey, &data.Router.IdentityCA, &data.Router.Edge.Hostname, &data.Router.Edge.Port} - expectedNonEmptyIntFields := []string{".Router.Listener.BindPort", ".Router.Listener.OutQueueSize", ".Router.Wss.ReadBufferSize", ".Router.Wss.WriteBufferSize", ".Router.Forwarder.XgressDialQueueLength", ".Router.Forwarder.XgressDialWorkerCount", ".Router.Forwarder.LinkDialQueueLength", ".Router.Forwarder.LinkDialWorkerCount"} - expectedNonEmptyIntValues := []*int{&data.Router.Listener.BindPort, &data.Router.Listener.OutQueueSize, &data.Router.Wss.ReadBufferSize, &data.Router.Wss.WriteBufferSize, &data.Router.Forwarder.XgressDialQueueLength, &data.Router.Forwarder.XgressDialWorkerCount, &data.Router.Forwarder.LinkDialQueueLength, &data.Router.Forwarder.LinkDialWorkerCount} - expectedNonEmptyTimeFields := []string{".Router.Listener.ConnectTimeout", "Router.Listener.GetSessionTimeout", ".Router.Wss.WriteTimeout", ".Router.Wss.ReadTimeout", ".Router.Wss.IdleTimeout", ".Router.Wss.PongTimeout", ".Router.Wss.PingInterval", ".Router.Wss.HandshakeTimeout", ".Router.Forwarder.LatencyProbeInterval"} - expectedNonEmptyTimeValues := []*time.Duration{&data.Router.Listener.ConnectTimeout, &data.Router.Listener.GetSessionTimeout, &data.Router.Wss.WriteTimeout, &data.Router.Wss.ReadTimeout, &data.Router.Wss.IdleTimeout, &data.Router.Wss.PongTimeout, &data.Router.Wss.PingInterval, &data.Router.Wss.HandshakeTimeout, &data.Router.Forwarder.LatencyProbeInterval} - - // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) - cmd := NewCmdCreateConfigRouter() - cmd.SetArgs([]string{"edge", "--routerName", routerName}) - _ = captureOutput(func() { - _ = cmd.Execute() - }) - - // Check that the expected string template values are not blank - for field, value := range expectedNonEmptyStringValues { - assert.NotEqualf(t, "", *value, expectedNonEmptyStringFields[field]+" should be a non-blank value") - } - - // Check that the expected int template values are not zero - for field, value := range expectedNonEmptyIntValues { - assert.NotZero(t, *value, expectedNonEmptyIntFields[field]+" should be a non-zero value") - } - - // Check that the expected time.Duration template values are not zero - for field, value := range expectedNonEmptyTimeValues { - assert.NotZero(t, *value, expectedNonEmptyTimeFields[field]+" should be a non-zero value") - } -} - -func TestExecuteCreateConfigRouterFabricHasNonBlankTemplateValues(t *testing.T) { - routerName := "MyFabricRouter" - expectedNonEmptyStringFields := []string{".ZitiHome", ".Hostname", ".Router.Name", ".Router.IdentityCert", ".Router.IdentityServerCert", ".Router.IdentityKey", ".Router.IdentityCA", ".Router.Edge.Hostname", ".Router.Edge.Port"} - expectedNonEmptyStringValues := []*string{&data.ZitiHome, &data.Hostname, &data.Router.Name, &data.Router.IdentityCert, &data.Router.IdentityServerCert, &data.Router.IdentityKey, &data.Router.IdentityCA, &data.Router.Edge.Hostname, &data.Router.Edge.Port} - expectedNonEmptyIntFields := []string{".Router.Listener.BindPort", ".Router.Listener.OutQueueSize", ".Router.Wss.ReadBufferSize", ".Router.Wss.WriteBufferSize", ".Router.Forwarder.XgressDialQueueLength", ".Router.Forwarder.XgressDialWorkerCount", ".Router.Forwarder.LinkDialQueueLength", ".Router.Forwarder.LinkDialWorkerCount"} - expectedNonEmptyIntValues := []*int{&data.Router.Listener.BindPort, &data.Router.Listener.OutQueueSize, &data.Router.Wss.ReadBufferSize, &data.Router.Wss.WriteBufferSize, &data.Router.Forwarder.XgressDialQueueLength, &data.Router.Forwarder.XgressDialWorkerCount, &data.Router.Forwarder.LinkDialQueueLength, &data.Router.Forwarder.LinkDialWorkerCount} - expectedNonEmptyTimeFields := []string{".Router.Listener.ConnectTimeout", "Router.Listener.GetSessionTimeout", ".Router.Wss.WriteTimeout", ".Router.Wss.ReadTimeout", ".Router.Wss.IdleTimeout", ".Router.Wss.PongTimeout", ".Router.Wss.PingInterval", ".Router.Wss.HandshakeTimeout", ".Router.Forwarder.LatencyProbeInterval"} - expectedNonEmptyTimeValues := []*time.Duration{&data.Router.Listener.ConnectTimeout, &data.Router.Listener.GetSessionTimeout, &data.Router.Wss.WriteTimeout, &data.Router.Wss.ReadTimeout, &data.Router.Wss.IdleTimeout, &data.Router.Wss.PongTimeout, &data.Router.Wss.PingInterval, &data.Router.Wss.HandshakeTimeout, &data.Router.Forwarder.LatencyProbeInterval} - - // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) - cmd := NewCmdCreateConfigRouter() - cmd.SetArgs([]string{"fabric", "--routerName", routerName}) - _ = captureOutput(func() { - _ = cmd.Execute() - }) - - // Check that the expected string template values are not blank - for field, value := range expectedNonEmptyStringValues { - assert.NotEqualf(t, "", *value, expectedNonEmptyStringFields[field]+" should be a non-blank value") - } - - // Check that the expected int template values are not zero - for field, value := range expectedNonEmptyIntValues { - assert.NotZero(t, *value, expectedNonEmptyIntFields[field]+" should be a non-zero value") - } - - // Check that the expected time.Duration template values are not zero - for field, value := range expectedNonEmptyTimeValues { - assert.NotZero(t, *value, expectedNonEmptyTimeFields[field]+" should be a non-zero value") - } -} - -func TestEdgeRouterIPOverrideIsConsumed(t *testing.T) { - routerName := "MyFabricRouter" - blank := "" - externalIP := "123.456.78.9" - - // Setup options - clearOptionsAndTemplateData() - routerOptions.Output = defaultOutput - - // Set the env variable to non-empty value - _ = os.Setenv(constants.ZitiEdgeRouterIPOverrideVarName, externalIP) - - // Check that template value is currently blank - assert.Equal(t, blank, data.Router.Edge.IPOverride, "Mismatch router IP override, expected %s but got %s", blank, data.Router.Edge.IPOverride) - - // Create and run the CLI command (capture output, otherwise config prints to stdout instead of test results) - cmd := NewCmdCreateConfigRouter() - cmd.SetArgs([]string{"edge", "--routerName", routerName}) - configOutput := captureOutput(func() { - _ = cmd.Execute() - }) - - // Check that the template values now contains the custom external IP override value - assert.Equal(t, externalIP, data.Router.Edge.IPOverride, "Mismatch router IP override, expected %s but got %s", externalIP, data.Router.Edge.IPOverride) - - // Check that the config output has the IP - assert.True(t, strings.Contains(configOutput, externalIP), "Expected value not found; expected to find value of "+constants.ZitiEdgeRouterIPOverrideVarName+" in config output.") -} diff --git a/ziti/cmd/ziti/cmd/create_config_test.go b/ziti/cmd/ziti/cmd/create_config_test.go index be592481c..59a8b002b 100644 --- a/ziti/cmd/ziti/cmd/create_config_test.go +++ b/ziti/cmd/ziti/cmd/create_config_test.go @@ -39,6 +39,7 @@ func getZitiEnvironmentVariables() []string { "ZITI_EDGE_CTRL_ADVERTISED_HOST_PORT", "ZITI_EDGE_IDENTITY_ENROLLMENT_DURATION", "ZITI_EDGE_ROUTER_ENROLLMENT_DURATION", + "ZITI_EDGE_ROUTER_ADVERTISED_HOST", } } diff --git a/ziti/cmd/ziti/cmd/demo/setup-client.go b/ziti/cmd/ziti/cmd/demo/setup-client.go index c929b8889..28dedd95e 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-client.go +++ b/ziti/cmd/ziti/cmd/demo/setup-client.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var clientScriptSource []byte type client struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,16 +70,16 @@ func newClientCmd(p common.OptionsProvider) *cobra.Command { } func (self *client) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("select-edge-router", &actions.SelectEdgeRouterAction{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("select-edge-router", &actionz.SelectEdgeRouterAction{}) return t.Run(clientScriptSource) } diff --git a/ziti/cmd/ziti/cmd/demo/setup-multi-router-tunneler-hosted-service.go b/ziti/cmd/ziti/cmd/demo/setup-multi-router-tunneler-hosted-service.go index 4c79b03f1..8e9ea2525 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-multi-router-tunneler-hosted-service.go +++ b/ziti/cmd/ziti/cmd/demo/setup-multi-router-tunneler-hosted-service.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var multiRouterTunnelerHostedScriptSource []byte type multiRouterTunnelerHosted struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,17 +70,17 @@ func newMultiRouterTunnelerHostedCmd(p common.OptionsProvider) *cobra.Command { } func (self *multiRouterTunnelerHosted) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("ziti-create-config", &actions.ZitiCreateConfigAction{}) - t.RegisterActionHandler("ziti-for-each", &actions.ZitiForEach{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("ziti-create-config", &actionz.ZitiCreateConfigAction{}) + t.RegisterActionHandler("ziti-for-each", &actionz.ZitiForEach{}) return t.Run(multiRouterTunnelerHostedScriptSource) } diff --git a/ziti/cmd/ziti/cmd/demo/setup-multi-sdk-service.go b/ziti/cmd/ziti/cmd/demo/setup-multi-sdk-service.go index ec29150e9..dfaf0f13d 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-multi-sdk-service.go +++ b/ziti/cmd/ziti/cmd/demo/setup-multi-sdk-service.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var multiSdkHostedScriptSource []byte type multiSdkHosted struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,15 +70,15 @@ func newMultiSdkHostedCmd(p common.OptionsProvider) *cobra.Command { } func (self *multiSdkHosted) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) return t.Run(multiSdkHostedScriptSource) } diff --git a/ziti/cmd/ziti/cmd/demo/setup-multi-tunneler-hosted-service.go b/ziti/cmd/ziti/cmd/demo/setup-multi-tunneler-hosted-service.go index bb11a701d..6c28fc6fd 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-multi-tunneler-hosted-service.go +++ b/ziti/cmd/ziti/cmd/demo/setup-multi-tunneler-hosted-service.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var multiTunnelerHostedScriptSource []byte type multiTunnelerHosted struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,17 +70,17 @@ func newMultiTunnelerHostedCmd(p common.OptionsProvider) *cobra.Command { } func (self *multiTunnelerHosted) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("ziti-create-config", &actions.ZitiCreateConfigAction{}) - t.RegisterActionHandler("ziti-for-each", &actions.ZitiForEach{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("ziti-create-config", &actionz.ZitiCreateConfigAction{}) + t.RegisterActionHandler("ziti-for-each", &actionz.ZitiForEach{}) return t.Run(multiTunnelerHostedScriptSource) } diff --git a/ziti/cmd/ziti/cmd/demo/setup-router-tunneler-both-sides.go b/ziti/cmd/ziti/cmd/demo/setup-router-tunneler-both-sides.go index 87cee0029..b2d073e2a 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-router-tunneler-both-sides.go +++ b/ziti/cmd/ziti/cmd/demo/setup-router-tunneler-both-sides.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var routerTunnelerBothSidesScriptSource []byte type routerTunnelerBothSides struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,17 +70,17 @@ func newRouterTunnelerBothSidesCmd(p common.OptionsProvider) *cobra.Command { } func (self *routerTunnelerBothSides) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("ziti-create-config", &actions.ZitiCreateConfigAction{}) - t.RegisterActionHandler("ziti-for-each", &actions.ZitiForEach{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("ziti-create-config", &actionz.ZitiCreateConfigAction{}) + t.RegisterActionHandler("ziti-for-each", &actionz.ZitiForEach{}) return t.Run(routerTunnelerBothSidesScriptSource) } diff --git a/ziti/cmd/ziti/cmd/demo/setup-single-router-tunneler-hosted-service.go b/ziti/cmd/ziti/cmd/demo/setup-single-router-tunneler-hosted-service.go index 5e332abff..485b6e011 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-single-router-tunneler-hosted-service.go +++ b/ziti/cmd/ziti/cmd/demo/setup-single-router-tunneler-hosted-service.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var singleRouterTunnelerHostedScriptSource []byte type singleRouterTunnelerHosted struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,18 +70,18 @@ func newSingleRouterTunnelerHostedCmd(p common.OptionsProvider) *cobra.Command { } func (self *singleRouterTunnelerHosted) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("ziti-create-config", &actions.ZitiCreateConfigAction{}) - t.RegisterActionHandler("select-edge-router", &actions.SelectEdgeRouterAction{}) - t.RegisterActionHandler("ziti-for-each", &actions.ZitiForEach{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("ziti-create-config", &actionz.ZitiCreateConfigAction{}) + t.RegisterActionHandler("select-edge-router", &actionz.SelectEdgeRouterAction{}) + t.RegisterActionHandler("ziti-for-each", &actionz.ZitiForEach{}) return t.Run(singleRouterTunnelerHostedScriptSource) } diff --git a/ziti/cmd/ziti/cmd/demo/setup-single-sdk-service.go b/ziti/cmd/ziti/cmd/demo/setup-single-sdk-service.go index c5de45994..19d108f8a 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-single-sdk-service.go +++ b/ziti/cmd/ziti/cmd/demo/setup-single-sdk-service.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var singleSdkHostedScriptSource []byte type singleSdkHosted struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,16 +70,16 @@ func newSingleSdkHostedCmd(p common.OptionsProvider) *cobra.Command { } func (self *singleSdkHosted) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("select-edge-router", &actions.SelectEdgeRouterAction{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("select-edge-router", &actionz.SelectEdgeRouterAction{}) return t.Run(singleSdkHostedScriptSource) } diff --git a/ziti/cmd/ziti/cmd/demo/setup-update-config-addressable.go b/ziti/cmd/ziti/cmd/demo/setup-update-config-addressable.go index 8b9277ba2..bd083a9fb 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-update-config-addressable.go +++ b/ziti/cmd/ziti/cmd/demo/setup-update-config-addressable.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var updateConfigAddressableSource []byte type updateConfigAddressable struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,18 +70,18 @@ func newUpdateConfigAddressableCmd(p common.OptionsProvider) *cobra.Command { } func (self *updateConfigAddressable) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("ziti-create-config", &actions.ZitiCreateConfigAction{}) - t.RegisterActionHandler("ziti-update-config", &actions.ZitiUpdateConfigAction{}) - t.RegisterActionHandler("ziti-for-each", &actions.ZitiForEach{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("ziti-create-config", &actionz.ZitiCreateConfigAction{}) + t.RegisterActionHandler("ziti-update-config", &actionz.ZitiUpdateConfigAction{}) + t.RegisterActionHandler("ziti-for-each", &actionz.ZitiForEach{}) return t.Run(updateConfigAddressableSource) } diff --git a/ziti/cmd/ziti/cmd/demo/setup-update-config-ha.go b/ziti/cmd/ziti/cmd/demo/setup-update-config-ha.go index 861c33e1c..9e2cac205 100644 --- a/ziti/cmd/ziti/cmd/demo/setup-update-config-ha.go +++ b/ziti/cmd/ziti/cmd/demo/setup-update-config-ha.go @@ -18,12 +18,12 @@ package demo import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial" "github.com/spf13/cobra" "time" ) @@ -33,7 +33,7 @@ var updateConfigHASource []byte type updateConfigHA struct { api.Options - tutorial2.TutorialOptions + tutorial.TutorialOptions interactive bool } @@ -70,18 +70,18 @@ func newUpdateConfigHACmd(p common.OptionsProvider) *cobra.Command { } func (self *updateConfigHA) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = !self.interactive - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiEnsureLoggedIn{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("ziti-create-config", &actions.ZitiCreateConfigAction{}) - t.RegisterActionHandler("ziti-update-config", &actions.ZitiUpdateConfigAction{}) - t.RegisterActionHandler("ziti-for-each", &actions.ZitiForEach{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("ziti-create-config", &actionz.ZitiCreateConfigAction{}) + t.RegisterActionHandler("ziti-update-config", &actionz.ZitiUpdateConfigAction{}) + t.RegisterActionHandler("ziti-for-each", &actionz.ZitiForEach{}) return t.Run(updateConfigHASource) } diff --git a/ziti/cmd/ziti/cmd/demo/zcat.go b/ziti/cmd/ziti/cmd/demo/zcat.go index 8715cb181..fda7d7ff9 100644 --- a/ziti/cmd/ziti/cmd/demo/zcat.go +++ b/ziti/cmd/ziti/cmd/demo/zcat.go @@ -30,34 +30,34 @@ import ( "time" ) -type zcat struct { +type zcatAction struct { verbose bool logFormatter string configFile string } func newZcatCmd() *cobra.Command { - server := &zcat{} + action := &zcatAction{} cmd := &cobra.Command{ Use: "zcat ", Example: "ziti demo zcat tcp:localhost:1234 or ziti demo zcat -i zcat.json ziti:echo", Short: "A simple network cat facility which can run over tcp or ziti", Args: cobra.ExactArgs(1), - Run: server.run, + Run: action.run, } // allow interspersing positional args and flags cmd.Flags().SetInterspersed(true) - cmd.Flags().BoolVarP(&server.verbose, "verbose", "v", false, "Enable verbose logging") - cmd.Flags().StringVar(&server.logFormatter, "log-formatter", "", "Specify log formatter [json|pfxlog|text]") - cmd.Flags().StringVarP(&server.configFile, "identity", "i", "", "Specify the Ziti identity to use. If not specified the Ziti listener won't be started") + cmd.Flags().BoolVarP(&action.verbose, "verbose", "v", false, "Enable verbose logging") + cmd.Flags().StringVar(&action.logFormatter, "log-formatter", "", "Specify log formatter [json|pfxlog|text]") + cmd.Flags().StringVarP(&action.configFile, "identity", "i", "", "Specify the Ziti identity to use. If not specified the Ziti listener won't be started") cmd.Flags().SetInterspersed(true) return cmd } -func (self *zcat) initLogging() { +func (self *zcatAction) initLogging() { logLevel := logrus.InfoLevel if self.verbose { logLevel = logrus.DebugLevel @@ -78,7 +78,7 @@ func (self *zcat) initLogging() { } } -func (self *zcat) run(_ *cobra.Command, args []string) { +func (self *zcatAction) run(_ *cobra.Command, args []string) { self.initLogging() log := pfxlog.Logger() @@ -128,7 +128,7 @@ func (self *zcat) run(_ *cobra.Command, args []string) { self.copy(os.Stdout, conn) } -func (self *zcat) copy(writer io.Writer, reader io.Reader) { +func (self *zcatAction) copy(writer io.Writer, reader io.Reader) { buf := make([]byte, info.MaxUdpPacketSize) bytesCopied, err := io.CopyBuffer(writer, reader, buf) pfxlog.Logger().Debugf("Copied %v bytes", bytesCopied) diff --git a/ziti/cmd/ziti/cmd/pki.go b/ziti/cmd/ziti/cmd/pki.go index d56dedbce..10924e24a 100644 --- a/ziti/cmd/ziti/cmd/pki.go +++ b/ziti/cmd/ziti/cmd/pki.go @@ -60,6 +60,7 @@ type PKIFlags struct { IP []string Email []string PKI *pki.ZitiPKI + SpiffeID string } var ( diff --git a/ziti/cmd/ziti/cmd/pki_create_ca.go b/ziti/cmd/ziti/cmd/pki_create_ca.go index b2c99e698..35c14d0b8 100644 --- a/ziti/cmd/ziti/cmd/pki_create_ca.go +++ b/ziti/cmd/ziti/cmd/pki_create_ca.go @@ -17,9 +17,11 @@ package cmd import ( - "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" "io" + "net/url" + "strings" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/cmd/ziti/internal/log" @@ -68,14 +70,14 @@ func (o *PKICreateCAOptions) addPKICreateCAFlags(cmd *cobra.Command) { cmd.Flags().IntVarP(&o.Flags.CAExpire, "expire-limit", "", 3650, "Expiration limit in days") cmd.Flags().IntVarP(&o.Flags.CAMaxpath, "max-path-len", "", -1, "Intermediate maximum path length") cmd.Flags().IntVarP(&o.Flags.CAPrivateKeySize, "private-key-size", "", 4096, "Size of the private key") + cmd.Flags().StringVar(&o.Flags.SpiffeID, "trust-domain", "", "An optional spiffe trust domain. spiffe:// will be automatically prefixed, if not provided") } // Run implements this command func (o *PKICreateCAOptions) Run() error { - pkiroot, err := o.ObtainPKIRoot() if err != nil { - return fmt.Errorf("%s", err) + return err } o.Flags.PKI = &pki.ZitiPKI{Store: &store.Local{}} @@ -84,7 +86,7 @@ func (o *PKICreateCAOptions) Run() error { cafile, err := o.ObtainCAFile() if err != nil { - return fmt.Errorf("%s", err) + return err } commonName := o.Flags.CAName @@ -94,6 +96,17 @@ func (o *PKICreateCAOptions) Run() error { template.IsCA = true + if o.Flags.SpiffeID != "" { + if !strings.HasPrefix(o.Flags.SpiffeID, "spiffe://") { + o.Flags.SpiffeID = "spiffe://" + o.Flags.SpiffeID + } + spiffeId, err := url.Parse(o.Flags.SpiffeID) + if err != nil { + return errors.Wrapf(err, "unable to parse spiffe id [%v]", o.Flags.SpiffeID) + } + template.URIs = append(template.URIs, spiffeId) + } + var signer *certificate.Bundle req := &pki.Request{ @@ -103,8 +116,8 @@ func (o *PKICreateCAOptions) Run() error { PrivateKeySize: o.Flags.CAPrivateKeySize, } - if err := o.Flags.PKI.Sign(signer, req); err != nil { - return fmt.Errorf("Cannot Sign: %v", err) + if err = o.Flags.PKI.Sign(signer, req); err != nil { + return errors.Wrap(err, "cannot sign") } log.Infoln("Success") diff --git a/ziti/cmd/ziti/cmd/pki_create_client.go b/ziti/cmd/ziti/cmd/pki_create_client.go index e7df514d5..38f785c95 100644 --- a/ziti/cmd/ziti/cmd/pki_create_client.go +++ b/ziti/cmd/ziti/cmd/pki_create_client.go @@ -17,9 +17,10 @@ package cmd import ( - "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" "io" + "net/url" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/cmd/ziti/internal/log" @@ -72,14 +73,14 @@ func (o *PKICreateClientOptions) addPKICreateClientFlags(cmd *cobra.Command) { cmd.Flags().IntVarP(&o.Flags.CAExpire, "expire-limit", "", 365, "Expiration limit in days") cmd.Flags().IntVarP(&o.Flags.CAMaxpath, "max-path-len", "", -1, "Intermediate maximum path length") cmd.Flags().IntVarP(&o.Flags.CAPrivateKeySize, "private-key-size", "", 2048, "Size of the private key") + cmd.Flags().StringVar(&o.Flags.SpiffeID, "spiffe-id", "", "Optionally provide the path portion of a SPIFFE id. The trust domain will be taken from the signing certificate.") } // Run implements this command func (o *PKICreateClientOptions) Run() error { - pkiroot, err := o.ObtainPKIRoot() if err != nil { - return fmt.Errorf("%s", err) + return err } o.Flags.PKI = &pki.ZitiPKI{Store: &store.Local{}} @@ -90,7 +91,7 @@ func (o *PKICreateClientOptions) Run() error { clientCertFile, err := o.ObtainClientCertFile() if err != nil { - return fmt.Errorf("%s", err) + return err } filename := o.ObtainFileName(clientCertFile, commonName) @@ -103,17 +104,37 @@ func (o *PKICreateClientOptions) Run() error { caname, err := o.ObtainCAName(pkiroot) if err != nil { - return fmt.Errorf("%s", err) + return err } keyFile, err := o.ObtainKeyFile(false) if err != nil { - return fmt.Errorf("%s", err) + return err } signer, err = o.Flags.PKI.GetCA(caname) if err != nil { - return fmt.Errorf("Cannot locate signer: %v", err) + return errors.Wrap(err, "cannot locate signer") + } + + if o.Flags.SpiffeID != "" { + var trustDomain *url.URL + for _, uri := range signer.Cert.URIs { + if uri.Scheme == "spiffe" { + if trustDomain != nil { + return errors.New("signing cert contained multiple spiffe ids, which is not allowed") + } + trustDomain = uri + } + } + + if trustDomain == nil { + return errors.New("signing cert doesn't have a spiffe id. unknown trust domain") + } + + spiffId := *trustDomain + spiffId.Path = o.Flags.SpiffeID + template.URIs = append(template.URIs, &spiffId) } req := &pki.Request{ @@ -125,7 +146,7 @@ func (o *PKICreateClientOptions) Run() error { } if err := o.Flags.PKI.Sign(signer, req); err != nil { - return fmt.Errorf("Cannot Sign: %v", err) + return errors.Wrap(err, "cannot sign") } log.Infoln("Success") diff --git a/ziti/cmd/ziti/cmd/pki_create_intermediate.go b/ziti/cmd/ziti/cmd/pki_create_intermediate.go index 1b1b3ed8e..d664c5bb2 100644 --- a/ziti/cmd/ziti/cmd/pki_create_intermediate.go +++ b/ziti/cmd/ziti/cmd/pki_create_intermediate.go @@ -17,7 +17,7 @@ package cmd import ( - "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" "io" @@ -74,10 +74,9 @@ func (o *PKICreateIntermediateOptions) addPKICreateIntermediateFlags(cmd *cobra. // Run implements this command func (o *PKICreateIntermediateOptions) Run() error { - pkiroot, err := o.ObtainPKIRoot() if err != nil { - return fmt.Errorf("%s", err) + return err } o.Flags.PKI = &pki.ZitiPKI{Store: &store.Local{}} @@ -86,7 +85,7 @@ func (o *PKICreateIntermediateOptions) Run() error { intermediatefile, err := o.ObtainIntermediateCAFile() if err != nil { - return fmt.Errorf("%s", err) + return err } commonName := o.Flags.IntermediateName @@ -100,12 +99,18 @@ func (o *PKICreateIntermediateOptions) Run() error { caname, err := o.ObtainCAName(pkiroot) if err != nil { - return fmt.Errorf("%s", err) + return err } signer, err = o.Flags.PKI.GetCA(caname) if err != nil { - return fmt.Errorf("Cannot locate signer: %v", err) + return errors.Wrap(err, "cannot locate signer") + } + + for _, uri := range signer.Cert.URIs { + if uri.Scheme == "spiffe" { + template.URIs = append(template.URIs, uri) + } } req := &pki.Request{ @@ -116,7 +121,7 @@ func (o *PKICreateIntermediateOptions) Run() error { } if err := o.Flags.PKI.Sign(signer, req); err != nil { - return fmt.Errorf("Cannot Sign: %v", err) + return errors.Wrap(err, "cannot sign") } log.Infoln("Success") diff --git a/ziti/cmd/ziti/cmd/pki_create_server.go b/ziti/cmd/ziti/cmd/pki_create_server.go index 392808658..e1b64a2f4 100644 --- a/ziti/cmd/ziti/cmd/pki_create_server.go +++ b/ziti/cmd/ziti/cmd/pki_create_server.go @@ -17,15 +17,15 @@ package cmd import ( - "fmt" - "github.com/spf13/cobra" - "io" - cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/cmd/ziti/internal/log" "github.com/openziti/ziti/ziti/pki/certificate" "github.com/openziti/ziti/ziti/pki/pki" "github.com/openziti/ziti/ziti/pki/store" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "io" + "net/url" ) // PKICreateServerOptions the options for the create spring command @@ -73,19 +73,19 @@ func (o *PKICreateServerOptions) addPKICreateServerFlags(cmd *cobra.Command) { cmd.Flags().IntVarP(&o.Flags.CAExpire, "expire-limit", "", 365, "Expiration limit in days") cmd.Flags().IntVarP(&o.Flags.CAMaxpath, "max-path-len", "", -1, "Intermediate maximum path length") cmd.Flags().IntVarP(&o.Flags.CAPrivateKeySize, "private-key-size", "", 4096, "Size of the private key") + cmd.Flags().StringVar(&o.Flags.SpiffeID, "spiffe-id", "", "Optionally provide the path portion of a SPIFFE id. The trust domain will be taken from the signing certificate.") } // Run implements this command func (o *PKICreateServerOptions) Run() error { - IPs, DNSNames, err := o.ObtainIPsAndDNSNames() if err != nil { - return fmt.Errorf("%s", err) + return err } pkiroot, err := o.ObtainPKIRoot() if err != nil { - return fmt.Errorf("%s", err) + return err } o.Flags.PKI = &pki.ZitiPKI{Store: &store.Local{}} @@ -96,7 +96,7 @@ func (o *PKICreateServerOptions) Run() error { serverCertFile, err := o.ObtainServerCertFile() if err != nil { - return fmt.Errorf("%s", err) + return err } filename := o.ObtainFileName(serverCertFile, commonName) @@ -110,17 +110,37 @@ func (o *PKICreateServerOptions) Run() error { caname, err := o.ObtainCAName(pkiroot) if err != nil { - return fmt.Errorf("%s", err) + return err } keyFile, err := o.ObtainKeyFile(false) if err != nil { - return fmt.Errorf("%s", err) + return err } signer, err = o.Flags.PKI.GetCA(caname) if err != nil { - return fmt.Errorf("Cannot locate signer: %v", err) + return errors.Wrap(err, "cannot locate signer") + } + + if o.Flags.SpiffeID != "" { + var trustDomain *url.URL + for _, uri := range signer.Cert.URIs { + if uri.Scheme == "spiffe" { + if trustDomain != nil { + return errors.New("signing cert contained multiple spiffe ids, which is not allowed") + } + trustDomain = uri + } + } + + if trustDomain == nil { + return errors.New("signing cert doesn't have a spiffe id. unknown trust domain") + } + + spiffId := *trustDomain + spiffId.Path = o.Flags.SpiffeID + template.URIs = append(template.URIs, &spiffId) } req := &pki.Request{ @@ -132,12 +152,12 @@ func (o *PKICreateServerOptions) Run() error { } if err := o.Flags.PKI.Sign(signer, req); err != nil { - return fmt.Errorf("Cannot Sign: %v", err) + return errors.Wrap(err, "cannot sign") } // Concat the newly-created server cert with the intermediate cert to create a server.chain.pem file if err := o.Flags.PKI.Chain(signer, req); err != nil { - return fmt.Errorf("Cannot Sign: %v", err) + return errors.Wrap(err, "cannot sign") } log.Infoln("Success") diff --git a/ziti/cmd/ziti/cmd/tutorial/actions/keep_session_alive.go b/ziti/cmd/ziti/cmd/tutorial/actions/keep_session_alive.go deleted file mode 100644 index 749cbef01..000000000 --- a/ziti/cmd/ziti/cmd/tutorial/actions/keep_session_alive.go +++ /dev/null @@ -1,52 +0,0 @@ -/* - 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 actions - -import ( - "fmt" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" - "net/url" - "strings" - "time" -) - -type KeepSessionAliveAction struct{} - -func (self *KeepSessionAliveAction) Execute(ctx *tutorial.ActionContext) error { - interval := time.Minute - if val, ok := ctx.Headers["interval"]; ok { - if d, err := time.ParseDuration(val); err != nil { - return err - } else { - interval = d - } - } - if !strings.EqualFold("true", ctx.Headers["quiet"]) { - fmt.Printf("Running session refresh every %v\n", interval) - } - go func() { - ticker := time.NewTicker(interval) - for { - select { - case <-ticker.C: - _, _, _ = edge.ListEntitiesOfType("edge-routers", url.Values{}, false, nil, 10, false) - } - } - }() - return nil -} diff --git a/ziti/cmd/ziti/cmd/tutorial/actions/select_edge_router.go b/ziti/cmd/ziti/cmd/tutorial/actions/select_edge_router.go deleted file mode 100644 index 11e4e8f22..000000000 --- a/ziti/cmd/ziti/cmd/tutorial/actions/select_edge_router.go +++ /dev/null @@ -1,138 +0,0 @@ -/* - 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 actions - -import ( - "fmt" - "github.com/openziti/foundation/v2/term" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" - "github.com/pkg/errors" - "strconv" - "strings" -) - -type edgeRouter struct { - id string - name string -} - -type SelectEdgeRouterAction struct{} - -func (self *SelectEdgeRouterAction) Execute(ctx *tutorial.ActionContext) error { - for { - err := self.SelectEdgeRouter(ctx) - if err == nil { - return nil - } - - retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("Error getting edge router (err=%v). Try again? [Y/N] (default Y): ", err), true) - if err2 != nil { - fmt.Printf("encountered error prompting for input: %v\n", err2) - return err - } - - if !retry { - return err - } - } -} - -func (self *SelectEdgeRouterAction) SelectEdgeRouter(ctx *tutorial.ActionContext) error { - fmt.Println("") - - valid := false - var edgeRouterName string - - for !valid { - children, _, err := edge.ListEntitiesWithFilter("edge-routers", "limit none") - if err != nil { - return errors.Wrap(err, "unable to list edge routers") - } - - var ers []*edgeRouter - - if len(children) == 0 { - return errors.New("no edge routers found") - } - - for _, child := range children { - isOnline := child.S("isOnline").Data().(bool) - if isOnline { - id := child.S("id").Data().(string) - name := child.S("name").Data().(string) - ers = append(ers, &edgeRouter{id: id, name: name}) - } - } - - if len(ers) == 0 { - fmt.Println("Error: no online edge routers found. Found these offline edge routers: ") - for _, child := range children { - id := child.S("id").Data().(string) - name := child.S("name").Data().(string) - fmt.Printf("id: %10v name: %10v\n", id, name) - } - return errors.New("no on-line edge routers") - } - - fmt.Printf("Available edge routers: \n\n") - for idx, er := range ers { - fmt.Printf(" %v: %v\n", idx+1, er.name) - } - fmt.Print(" R: Refresh list from controller\n") - var val string - - if !ctx.Runner.AssumeDefault { - val, err = term.Prompt("\nSelect edge router, by number or name (default 1): ") - if err != nil { - return err - } - } - - if val == "" { - edgeRouterName = ers[0].name - valid = true - } else { - if idx, err := strconv.Atoi(val); err == nil { - if idx > 0 && idx <= len(ers) { - edgeRouterName = ers[idx-1].name - valid = true - } - } - } - - if !valid { - for _, er := range ers { - if val == er.name { - edgeRouterName = val - valid = true - } - } - } - - if !valid { - if strings.EqualFold("r", val) { - fmt.Println("Refreshing edge router list") - } else { - fmt.Printf("Invalid input %v\n", val) - } - } - } - - ctx.Runner.AddVariable("edgeRouterName", edgeRouterName) - return nil -} diff --git a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_create_config.go b/ziti/cmd/ziti/cmd/tutorial/actions/ziti_create_config.go deleted file mode 100644 index 86b0eb8e5..000000000 --- a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_create_config.go +++ /dev/null @@ -1,94 +0,0 @@ -/* - 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 actions - -import ( - "fmt" - "github.com/fatih/color" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" - "github.com/pkg/errors" - "os" - "strings" -) - -// TODO: make this code more DRY -type ZitiCreateConfigAction struct{} - -func (self *ZitiCreateConfigAction) Execute(ctx *tutorial.ActionContext) error { - if strings.EqualFold("true", ctx.Headers["templatize"]) { - body, err := ctx.Runner.Template(ctx.Body) - if err != nil { - return err - } - ctx.Body = body - } - name := ctx.Headers["name"] - configType := ctx.Headers["type"] - - buf := &strings.Builder{} - buf.WriteString("About to execute:\n\n") - - line := fmt.Sprintf("ziti edge create config %v %v '%v'", name, configType, ctx.Body) - params := tutorial.ParseArgumentsWithStrings(line) - if params[0] != "ziti" { - return errors.Errorf("invalid parameter for ziti action, must start with 'ziti': %v", ctx.Body) - } - params[0] = line - ctx.Runner.LeftPadBuilder(buf) - buf.WriteString(" ") - buf.WriteString(color.New(color.Bold).Sprintf(line)) - buf.WriteRune('\n') - buf.WriteRune('\n') - ctx.Runner.LeftPadBuilder(buf) - buf.WriteString("Continue [Y/N] (default Y): ") - - if !ctx.Runner.AssumeDefault { - tutorial.Continue(buf.String(), true) - } - - fmt.Println("") - c := color.New(color.FgBlue, color.Bold) - - colorStdOut := !strings.EqualFold("false", ctx.Headers["colorStdOut"]) - - allowRetry := strings.EqualFold("true", ctx.Headers["allowRetry"]) - failOk := strings.EqualFold("true", ctx.Headers["failOk"]) - _, _ = c.Printf("$ %v\n", line) - done := false - for !done { - if err := tutorial.Exec(os.Args[0], colorStdOut, "edge", "create", "config", name, configType, ctx.Body); err != nil { - if failOk { - return nil - } - if allowRetry { - retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("operation failed with err: %v. Retry [Y/N] (default Y):", err), true) - if err2 != nil { - fmt.Printf("error while asking about retry: %v\n", err2) - return err - } - if !retry { - return err - } - } else { - return err - } - } else { - done = true - } - } - return nil -} diff --git a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_ensure_logged_in.go b/ziti/cmd/ziti/cmd/tutorial/actions/ziti_ensure_logged_in.go deleted file mode 100644 index 428e58209..000000000 --- a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_ensure_logged_in.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - 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 actions - -import ( - "fmt" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" - "net/url" -) - -type ZitiEnsureLoggedIn struct { - LoginParams LoginParams -} - -func (self *ZitiEnsureLoggedIn) Execute(ctx *tutorial.ActionContext) error { - _, _, err := edge.ListEntitiesOfType("edge-routers", url.Values{}, false, nil, 10, false) - if err == nil { - fmt.Println("Already authenticated to Ziti Controller") - return nil - } - loginAction := &ZitiLoginAction{LoginParams: self.LoginParams} - return loginAction.Execute(ctx) -} diff --git a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_for_each.go b/ziti/cmd/ziti/cmd/tutorial/actions/ziti_for_each.go deleted file mode 100644 index a047db173..000000000 --- a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_for_each.go +++ /dev/null @@ -1,100 +0,0 @@ -/* - 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 actions - -import ( - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" - "github.com/openziti/ziti/ziti/cmd/ziti/util" - "github.com/pkg/errors" - "net/url" - "os" - "strconv" -) - -type ZitiForEach struct{} - -func (self *ZitiForEach) Execute(ctx *tutorial.ActionContext) error { - ctx.Headers["templatize"] = "true" - apiType, found := ctx.Headers["api"] - if !found { - apiType = string(util.EdgeAPI) - } - entityType := ctx.Headers["type"] - - params := url.Values{} - filter, found := ctx.Headers["filter"] - if found { - params.Add("filter", filter) - } - - minCount := 1 - if count, found := ctx.Headers["minCount"]; found { - val, err := strconv.Atoi(count) - if err != nil { - return errors.Wrapf(err, "couldn't parse minCount, invalid value '%v'", count) - } - if val < 0 { - return errors.Wrapf(err, "invalid minCount, invalid value '%v', must >= 0", count) - } - minCount = val - } - - maxCount := 1 - if count, found := ctx.Headers["maxCount"]; found { - val, err := strconv.Atoi(count) - if err != nil { - return errors.Wrapf(err, "couldn't parse maxCount, invalid value '%v'", count) - } - if val < minCount { - return errors.Wrapf(err, "invalid maxCount '%v', must >= minCount of %v", count, minCount) - } - maxCount = val - } - - entities, _, err := api.ListEntitiesOfType(util.API(apiType), entityType, params, false, os.Stdout, 1, false) - if err != nil { - return err - } - - if len(entities) < minCount { - return errors.Errorf("expected at least %v %v, only found %v", minCount, entityType, len(entities)) - } - - if len(entities) > maxCount { - return errors.Errorf("expected at most %v %v, only found %v", maxCount, entityType, len(entities)) - } - - runner := ZitiRunnerAction{} - originalBody := ctx.Body - for _, entity := range entities { - wrapper := api.Wrap(entity) - id := wrapper.String("id") - name := wrapper.String("name") - - ctx.Runner.AddVariable("entityId", id) - ctx.Runner.AddVariable("entityName", name) - if err := runner.Execute(ctx); err != nil { - return err - } - ctx.Runner.ClearVariable("entityId") - ctx.Runner.ClearVariable("entityName") - ctx.Body = originalBody - } - - return nil -} diff --git a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_login.go b/ziti/cmd/ziti/cmd/tutorial/actions/ziti_login.go deleted file mode 100644 index 8569f547b..000000000 --- a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_login.go +++ /dev/null @@ -1,44 +0,0 @@ -/* - 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 actions - -import "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" - -type LoginParams interface { - GetControllerUrl() string - GetUsername() string - GetPassword() string -} - -type ZitiLoginAction struct { - LoginParams LoginParams -} - -func (self *ZitiLoginAction) Execute(ctx *tutorial.ActionContext) error { - cmd := "ziti edge login --ignore-config" - if self.LoginParams.GetControllerUrl() != "" { - cmd += " " + self.LoginParams.GetControllerUrl() - } - if self.LoginParams.GetUsername() != "" { - cmd += " --username " + self.LoginParams.GetUsername() - } - if self.LoginParams.GetPassword() != "" { - cmd += " --password " + self.LoginParams.GetPassword() - } - ctx.Body = cmd - return (&ZitiRunnerAction{}).Execute(ctx) -} diff --git a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_runner.go b/ziti/cmd/ziti/cmd/tutorial/actions/ziti_runner.go deleted file mode 100644 index 0d8ac8f9c..000000000 --- a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_runner.go +++ /dev/null @@ -1,99 +0,0 @@ -/* - 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 actions - -import ( - "fmt" - "github.com/fatih/color" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" - "github.com/pkg/errors" - "os" - "strings" -) - -type ZitiRunnerAction struct{} - -func (self *ZitiRunnerAction) Execute(ctx *tutorial.ActionContext) error { - if strings.EqualFold("true", ctx.Headers["templatize"]) { - body, err := ctx.Runner.Template(ctx.Body) - if err != nil { - return err - } - ctx.Body = body - } - lines := strings.Split(ctx.Body, "\n") - var cmds [][]string - buf := &strings.Builder{} - buf.WriteString("About to execute:\n\n") - - for _, line := range lines { - line = strings.TrimSpace(line) - if len(line) > 0 { - params := tutorial.ParseArgumentsWithStrings(line) - if params[0] != "ziti" { - return errors.Errorf("invalid parameter for ziti action, must start with 'ziti': %v", ctx.Body) - } - params[0] = line - cmds = append(cmds, params) - ctx.Runner.LeftPadBuilder(buf) - buf.WriteString(" ") - buf.WriteString(color.New(color.Bold).Sprintf(line)) - buf.WriteRune('\n') - } - } - buf.WriteRune('\n') - ctx.Runner.LeftPadBuilder(buf) - buf.WriteString("Continue [Y/N] (default Y): ") - - if !ctx.Runner.AssumeDefault { - tutorial.Continue(buf.String(), true) - } - - fmt.Println("") - c := color.New(color.FgBlue, color.Bold) - - colorStdOut := !strings.EqualFold("false", ctx.Headers["colorStdOut"]) - - allowRetry := strings.EqualFold("true", ctx.Headers["allowRetry"]) - failOk := strings.EqualFold("true", ctx.Headers["failOk"]) - for _, cmd := range cmds { - _, _ = c.Printf("$ %v\n", cmd[0]) - done := false - for !done { - if err := tutorial.Exec(os.Args[0], colorStdOut, cmd[1:]...); err != nil { - if failOk { - return nil - } - if allowRetry { - retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("operation failed with err: %v. Retry [Y/N] (default Y):", err), true) - if err2 != nil { - fmt.Printf("error while asking about retry: %v\n", err2) - return err - } - if !retry { - return err - } - } else { - return err - } - } else { - done = true - } - } - } - return nil -} diff --git a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_update_config.go b/ziti/cmd/ziti/cmd/tutorial/actions/ziti_update_config.go deleted file mode 100644 index 54cde0438..000000000 --- a/ziti/cmd/ziti/cmd/tutorial/actions/ziti_update_config.go +++ /dev/null @@ -1,92 +0,0 @@ -/* - 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 actions - -import ( - "fmt" - "github.com/fatih/color" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" - "github.com/pkg/errors" - "os" - "strings" -) - -type ZitiUpdateConfigAction struct{} - -func (self *ZitiUpdateConfigAction) Execute(ctx *tutorial.ActionContext) error { - if strings.EqualFold("true", ctx.Headers["templatize"]) { - body, err := ctx.Runner.Template(ctx.Body) - if err != nil { - return err - } - ctx.Body = body - } - name := ctx.Headers["name"] - - buf := &strings.Builder{} - buf.WriteString("About to execute:\n\n") - - line := fmt.Sprintf("ziti edge update config %v --data '%v'", name, ctx.Body) - params := tutorial.ParseArgumentsWithStrings(line) - if params[0] != "ziti" { - return errors.Errorf("invalid parameter for ziti action, must start with 'ziti': %v", ctx.Body) - } - params[0] = line - ctx.Runner.LeftPadBuilder(buf) - buf.WriteString(" ") - buf.WriteString(color.New(color.Bold).Sprintf(line)) - buf.WriteRune('\n') - buf.WriteRune('\n') - ctx.Runner.LeftPadBuilder(buf) - buf.WriteString("Continue [Y/N] (default Y): ") - - if !ctx.Runner.AssumeDefault { - tutorial.Continue(buf.String(), true) - } - - fmt.Println("") - c := color.New(color.FgBlue, color.Bold) - - colorStdOut := !strings.EqualFold("false", ctx.Headers["colorStdOut"]) - - allowRetry := strings.EqualFold("true", ctx.Headers["allowRetry"]) - failOk := strings.EqualFold("true", ctx.Headers["failOk"]) - _, _ = c.Printf("$ %v\n", line) - done := false - for !done { - if err := tutorial.Exec(os.Args[0], colorStdOut, "edge", "update", "config", name, "--data", ctx.Body); err != nil { - if failOk { - return nil - } - if allowRetry { - retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("operation failed with err: %v. Retry [Y/N] (default Y):", err), true) - if err2 != nil { - fmt.Printf("error while asking about retry: %v\n", err2) - return err - } - if !retry { - return err - } - } else { - return err - } - } else { - done = true - } - } - return nil -} diff --git a/ziti/cmd/ziti/cmd/tutorial/first-service-tutorial.go b/ziti/cmd/ziti/cmd/tutorial/first-service-tutorial.go index 665ecda77..69e2f5650 100644 --- a/ziti/cmd/ziti/cmd/tutorial/first-service-tutorial.go +++ b/ziti/cmd/ziti/cmd/tutorial/first-service-tutorial.go @@ -18,11 +18,11 @@ package tutorial import ( _ "embed" + "github.com/openziti/runzmd" + "github.com/openziti/runzmd/actionz" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions" - "github.com/openziti/ziti/ziti/cmd/ziti/tutorial" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "time" @@ -81,16 +81,16 @@ func newFirstServiceTutorialCmd(p common.OptionsProvider) *cobra.Command { } func (self *firstServiceTutorialOptions) run() error { - t := tutorial.NewRunner() + t := runzmd.NewRunner() t.NewLinePause = self.NewlinePause t.AssumeDefault = self.AssumeDefault - t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{}) - t.RegisterActionHandler("ziti-login", &actions.ZitiLoginAction{ + t.RegisterActionHandler("ziti", &actionz.ZitiRunnerAction{}) + t.RegisterActionHandler("ziti-login", &actionz.ZitiLoginAction{ LoginParams: &self.TutorialOptions, }) - t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{}) - t.RegisterActionHandler("select-edge-router", &actions.SelectEdgeRouterAction{}) + t.RegisterActionHandler("keep-session-alive", &actionz.KeepSessionAliveAction{}) + t.RegisterActionHandler("select-edge-router", &actionz.SelectEdgeRouterAction{}) plainEchoServerActions := &PlainEchoServerActions{} t.RegisterActionHandlerF("run-plain-echo-server", plainEchoServerActions.Start) @@ -100,7 +100,7 @@ func (self *firstServiceTutorialOptions) run() error { t.RegisterActionHandlerF("run-ziti-echo-server", zitiEchoServerActions.Start) t.RegisterActionHandlerF("stop-ziti-echo-server", zitiEchoServerActions.Stop) - showActionHandler := tutorial.NewShowActionHandler() + showActionHandler := runzmd.NewShowActionHandler() showActionHandler.Add("plain_echo_server.go", plainEchoServerSource) showActionHandler.Add("plain_echo_client.go", plainEchoClientSource) showActionHandler.Add("ziti_echo_client.go", zitiEchoClientSource) @@ -114,9 +114,9 @@ type PlainEchoServerActions struct { server plainEchoServer } -func (self *PlainEchoServerActions) Start(ctx *tutorial.ActionContext) error { +func (self *PlainEchoServerActions) Start(ctx *runzmd.ActionContext) error { if !ctx.Runner.AssumeDefault { - start, err := tutorial.AskYesNoWithDefault("Start plain-echo-server? [Y/N] (default Y): ", true) + start, err := runzmd.AskYesNoWithDefault("Start plain-echo-server? [Y/N] (default Y): ", true) if err != nil { return err } @@ -132,9 +132,9 @@ func (self *PlainEchoServerActions) Start(ctx *tutorial.ActionContext) error { return nil } -func (self *PlainEchoServerActions) Stop(ctx *tutorial.ActionContext) error { +func (self *PlainEchoServerActions) Stop(ctx *runzmd.ActionContext) error { if !ctx.Runner.AssumeDefault { - start, err := tutorial.AskYesNoWithDefault("Stop plain-echo-server? [Y/N] (default Y): ", true) + start, err := runzmd.AskYesNoWithDefault("Stop plain-echo-server? [Y/N] (default Y): ", true) if err != nil { return err } @@ -153,12 +153,12 @@ type ZitiEchoServerActions struct { server zitiEchoServer } -func (self *ZitiEchoServerActions) Start(ctx *tutorial.ActionContext) error { +func (self *ZitiEchoServerActions) Start(ctx *runzmd.ActionContext) error { logrus.SetLevel(logrus.WarnLevel) self.server.identityJson = "echo-server.json" if !ctx.Runner.AssumeDefault { - start, err := tutorial.AskYesNoWithDefault("Start ziti-echo-server? [Y/N] (default Y): ", true) + start, err := runzmd.AskYesNoWithDefault("Start ziti-echo-server? [Y/N] (default Y): ", true) if err != nil { return err } @@ -173,7 +173,7 @@ func (self *ZitiEchoServerActions) Start(ctx *tutorial.ActionContext) error { return nil } -func (self *ZitiEchoServerActions) Stop(*tutorial.ActionContext) error { +func (self *ZitiEchoServerActions) Stop(*runzmd.ActionContext) error { if self.server.listener != nil { return self.server.stop() } diff --git a/ziti/cmd/ziti/constants/constants.go b/ziti/cmd/ziti/constants/constants.go index 2abe6584e..b4efd27b3 100644 --- a/ziti/cmd/ziti/constants/constants.go +++ b/ziti/cmd/ziti/constants/constants.go @@ -105,4 +105,6 @@ const ( ExternalDNSVarName = "EXTERNAL_DNS" ZitiEdgeRouterIPOverrideVarName = "ZITI_EDGE_ROUTER_IP_OVERRIDE" ZitiEdgeRouterIPOverrideVarDescription = "Override the default edge router IP with a custom IP, this IP will also be added to the PKI" + ZitiEdgeRouterAdvertisedHostVarName = "ZITI_EDGE_ROUTER_ADVERTISED_HOST" + ZitiEdgeRouterAdvertisedHostVarDescription = "The advertised host of the router" ) diff --git a/ziti/cmd/ziti/tutorial/exec.go b/ziti/cmd/ziti/tutorial/exec.go deleted file mode 100644 index d6ec21732..000000000 --- a/ziti/cmd/ziti/tutorial/exec.go +++ /dev/null @@ -1,134 +0,0 @@ -package tutorial - -import ( - "fmt" - "github.com/fatih/color" - "github.com/openziti/foundation/v2/term" - "io" - "os" - "os/exec" - "strings" -) - -func Exec(program string, colorStdout bool, args ...string) error { - p := exec.Command(program, args...) - - stdErrWrapper := &WriterWrapper{ - c: color.New(color.FgRed), - w: os.Stdout, - } - - p.Stdin = os.Stdin - - if colorStdout { - stdOutWrapper := &WriterWrapper{ - c: color.New(color.FgBlue), - w: os.Stdout, - } - p.Stdout = stdOutWrapper - } else { - p.Stdout = os.Stdout - } - - p.Stderr = stdErrWrapper - if err := p.Run(); err != nil { - return err - } - return nil -} - -func Continue(prompt string, defaultValue bool) { - resp, err := AskYesNoWithDefault(prompt, defaultValue) - if err != nil { - fmt.Printf("\nerror: %v. exiting\n", err) - os.Exit(1) - } - - if !resp { - fmt.Print("\nok, exiting\n") - os.Exit(0) - } -} - -func AskYesNo(prompt string) (bool, error) { - filter := &yesNoFilter{} - if _, err := Ask(prompt, filter.Accept); err != nil { - return false, err - } - return filter.result, nil -} - -func AskYesNoWithDefault(prompt string, defaultVal bool) (bool, error) { - filter := &yesNoDefaultFilter{ - defaultVal: defaultVal, - } - if _, err := Ask(prompt, filter.Accept); err != nil { - return false, err - } - return filter.result, nil -} - -func Ask(prompt string, f func(string) bool) (string, error) { - for { - val, err := term.Prompt(prompt) - if err != nil { - return "", err - } - val = strings.TrimSpace(val) - if f(val) { - return val, nil - } - fmt.Printf("Invalid input: %v\n", val) - } -} - -type yesNoFilter struct { - result bool -} - -func (self *yesNoFilter) Accept(s string) bool { - if strings.EqualFold("y", s) || strings.EqualFold("yes", s) { - self.result = true - return true - } - - if strings.EqualFold("n", s) || strings.EqualFold("no", s) { - self.result = false - return true - } - - return false -} - -type yesNoDefaultFilter struct { - result bool - defaultVal bool -} - -func (self *yesNoDefaultFilter) Accept(s string) bool { - if s == "" { - self.result = self.defaultVal - return true - } - - if strings.EqualFold("y", s) || strings.EqualFold("yes", s) { - self.result = true - return true - } - - if strings.EqualFold("n", s) || strings.EqualFold("no", s) { - self.result = false - return true - } - - return false -} - -type WriterWrapper struct { - c *color.Color - w io.Writer -} - -func (self *WriterWrapper) Write(p []byte) (n int, err error) { - return self.c.Fprint(self.w, string(p)) -} diff --git a/ziti/cmd/ziti/tutorial/parser.go b/ziti/cmd/ziti/tutorial/parser.go deleted file mode 100644 index 421ef3649..000000000 --- a/ziti/cmd/ziti/tutorial/parser.go +++ /dev/null @@ -1,35 +0,0 @@ -package tutorial - -import ( - "strings" - "unicode" -) - -func ParseArgumentsWithStrings(val string) []string { - var result []string - - current := &strings.Builder{} - inString := false - for _, r := range val { - if r == '\'' { - if inString { - inString = false - } else { - inString = true - } - } else if !inString && unicode.IsSpace(r) { - if current.Len() > 0 { - result = append(result, current.String()) - current.Reset() - } - } else { - current.WriteRune(r) - } - } - - if current.Len() > 0 { - result = append(result, current.String()) - } - - return result -} diff --git a/ziti/cmd/ziti/tutorial/parser_test.go b/ziti/cmd/ziti/tutorial/parser_test.go deleted file mode 100644 index a39110ecd..000000000 --- a/ziti/cmd/ziti/tutorial/parser_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package tutorial - -import ( - "reflect" - "testing" -) - -func TestParseArgumentsWithStrings(t *testing.T) { - tests := []struct { - name string - args string - want []string - }{ - { - name: "one", - args: "one two three 'four five'", - want: []string{"one", "two", "three", "four five"}, - }, - { - name: "two", - args: " one two three 'four five' ", - want: []string{"one", "two", "three", "four five"}, - }, - { - name: "two", - args: " one two three 'four \"five\"' ", - want: []string{"one", "two", "three", "four \"five\""}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := ParseArgumentsWithStrings(tt.args); !reflect.DeepEqual(got, tt.want) { - t.Errorf("ParseArgumentsWithStrings() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/ziti/cmd/ziti/tutorial/runner.go b/ziti/cmd/ziti/tutorial/runner.go deleted file mode 100644 index d21633975..000000000 --- a/ziti/cmd/ziti/tutorial/runner.go +++ /dev/null @@ -1,379 +0,0 @@ -package tutorial - -import ( - "bytes" - "fmt" - markdown "github.com/MichaelMure/go-term-markdown" - "github.com/fatih/color" - "github.com/openziti/foundation/v2/term" - "github.com/pkg/errors" - "github.com/valyala/fasttemplate" - "io" - "os" - "sort" - "strings" - "time" -) - -const ( - codeActionBlockStart = "```action:" - codeActionBlockEnd = "```" - commentActionBlockStart = "" - actionMarker = "f572d396fae9206628714fb2ce00f72e94f2258f" -) - -var debug bool - -func init() { - if val, found := os.LookupEnv("DEBUG"); found && strings.EqualFold(val, "true") { - debug = true - } -} - -func NewRunner() *Runner { - result := &Runner{ - actionHandlers: map[string]ActionHandler{}, - variables: map[string]interface{}{}, - LineWidth: 75, - LeftPad: 5, - NewLinePause: time.Millisecond * 20, - } - result.RegisterActionHandlerF("echo", func(ctx *ActionContext) error { - fmt.Printf("echo: %v", ctx.Body) - return nil - }) - result.RegisterActionHandlerF("userInput", result.HandlePromptForInput) - result.RegisterActionHandlerF("pause", result.HandlePause) - return result -} - -type ActionContext struct { - Action string - Headers map[string]string - Body string - Runner *Runner -} - -type ActionHandler interface { - Execute(ctx *ActionContext) error -} - -type ActionHandlerF func(ctx *ActionContext) error - -func (self ActionHandlerF) Execute(ctx *ActionContext) error { - return self(ctx) -} - -type Runner struct { - LineWidth int - LeftPad int - NewLinePause time.Duration - AssumeDefault bool - actionHandlers map[string]ActionHandler - actions []func() error - variables map[string]interface{} -} - -func (self *Runner) AddVariable(name string, val interface{}) { - self.variables[name] = val -} - -func (self *Runner) ClearVariable(name string) { - delete(self.variables, name) -} - -func (self *Runner) Run(source []byte) error { - markdownSource, err := self.transformSource(source) - if err != nil { - return err - } - renderedMarkdown := markdown.Render(string(markdownSource), self.LineWidth, self.LeftPad) - return self.runMarkdown(renderedMarkdown) -} - -func (self *Runner) runMarkdown(source []byte) error { - fmt.Println("") - pauseWriter := NewSlowWriter(self.NewLinePause) - - for { - next := bytes.Index(source, []byte(actionMarker)) - if next < 0 { - if err := self.EmitTemplatized(string(source), pauseWriter); err != nil { - return err - } - fmt.Println("") - return nil - } - if next == 0 { - source = source[len(actionMarker):] - action := self.nextAction() - if err := action(); err != nil { - return err - } - } else { - md := source[0:next] - if err := self.EmitTemplatized(string(md), pauseWriter); err != nil { - return err - } - source = source[next:] - } - } -} - -func (self *Runner) nextAction() func() error { - result := self.actions[0] - self.actions = self.actions[1:] - return result -} - -func (self *Runner) transformSource(source []byte) ([]byte, error) { - var result []byte - for { - if len(source) == 0 { - return result, nil - } - - var behavior parseBehavior - if CodeAction.IsStarting(source) { - behavior = CodeAction - } else if CommentAction.IsStarting(source) { - behavior = CommentAction - } - - if behavior != nil { - source = source[len(behavior.GetStartToken()):] - endIndex := bytes.Index(source, []byte(behavior.GetEndToken())) - if endIndex < 0 { - return nil, errors.Errorf("no end %v found for action block", behavior.GetEndToken()) - } - actionSource := source[:endIndex] - source = source[endIndex+len(behavior.GetEndToken()):] - - var actionHeader, body string - - nlIndex := bytes.IndexByte(actionSource, '\n') - if nlIndex < 1 { - actionHeader = string(actionSource) - } else { - actionHeader = strings.TrimSpace(string(actionSource[:nlIndex])) - body = strings.TrimSpace(string(actionSource[nlIndex+1 : endIndex])) - } - actionDef := strings.TrimSpace(actionHeader) - action, headers, err := self.parseAction(actionDef) - if err != nil { - return nil, err - } - - handler, ok := self.actionHandlers[action] - if !ok { - return nil, errors.Errorf("no handler found for action: %v. Available: %+v", action, self.actionIds()) - } - ctx := &ActionContext{ - Action: action, - Headers: headers, - Body: body, - Runner: self, - } - self.actions = append(self.actions, func() error { - return handler.Execute(ctx) - }) - - result = append(result, []byte(actionMarker)...) - } else { - result = append(result, source[0]) - source = source[1:] - } - } -} - -func (self *Runner) parseAction(s string) (string, map[string]string, error) { - var action string - headers := map[string]string{} - - idx := strings.IndexByte(s, ' ') - if idx < 1 { - return s, headers, nil - } - - action = s[:idx] - rest := s[idx+1:] - for len(rest) > 0 { - idx = strings.IndexByte(rest, '=') - if idx < 0 { - headers[rest] = "" - if debug { - fmt.Printf("%v: added %v=%v\n", action, rest, headers[rest]) - } - rest = "" - } else if idx == 0 { - return "", nil, errors.Errorf("unable to parse action %v, unexpected =", action) - } else { - key := rest[:idx] - rest = rest[idx+1:] - if rest[0] == '\'' { - rest = rest[1:] - closingQuoteIdx := strings.IndexByte(rest, '\'') - if closingQuoteIdx < 0 { - return "", nil, errors.Errorf("unable to parse action %v, unclosed single-quote", action) - } - headers[key] = rest[:closingQuoteIdx] - if debug { - fmt.Printf("%v: added %v=%v\n", action, key, headers[key]) - } - rest = rest[closingQuoteIdx+1:] - if len(rest) > 0 { - if rest[0] != ' ' { - return "", nil, errors.Errorf("unable to parse action %v, expected space after closing singe-quote", action) - } else { - rest = rest[1:] - } - } - } else { - idx = strings.IndexByte(rest, ' ') - if idx < 0 { - headers[key] = rest - if debug { - fmt.Printf("%v: added %v=%v\n", action, key, headers[key]) - } - rest = "" - } else if idx == 0 { - headers[key] = "" - if debug { - fmt.Printf("%v: added %v=%v\n", action, key, headers[key]) - } - rest = rest[1:] - } else { - headers[key] = rest[:idx] - if debug { - fmt.Printf("%v: added %v=%v\n", action, key, headers[key]) - } - rest = rest[idx+1:] - } - } - } - } - - return action, headers, nil -} - -func (self *Runner) actionIds() []string { - var result []string - for k := range self.actionHandlers { - result = append(result, k) - } - sort.Strings(result) - return result -} - -func (self *Runner) RegisterActionHandler(action string, handler ActionHandler) { - self.actionHandlers[action] = handler -} - -func (self *Runner) RegisterActionHandlerF(action string, handler func(ctx *ActionContext) error) { - self.actionHandlers[action] = ActionHandlerF(handler) -} - -func (self *Runner) LeftPadBuilder(b *strings.Builder) { - for i := 0; i < self.LeftPad; i++ { - b.WriteRune(' ') - } -} - -func (self *Runner) EmitTemplatized(s string, out io.Writer) error { - _, err := fasttemplate.ExecuteFunc(s, "${", "}", out, func(w io.Writer, tag string) (int, error) { - tag = strings.ReplaceAll(tag, "\n", "") // in case we hit a line-break - tag = strings.ReplaceAll(tag, " ", "") // in case we hit a line-break - - val, ok := self.variables[tag] - if !ok { - return 0, errors.Errorf("unknown template value: '%v'", tag) - } - buf := []byte(fmt.Sprintf("%v", val)) - return w.Write(buf) - }) - return err -} - -func (self *Runner) Template(s string) (string, error) { - buf := &strings.Builder{} - _, err := fasttemplate.ExecuteFunc(s, "${", "}", buf, func(w io.Writer, tag string) (int, error) { - val, ok := self.variables[tag] - if !ok { - return 0, errors.Errorf("unknown template value: '%v'", tag) - } - buf := []byte(fmt.Sprintf("%v", val)) - return w.Write(buf) - }) - return buf.String(), err -} - -func (self *Runner) HandlePromptForInput(ctx *ActionContext) error { - varName, ok := ctx.Headers["variable"] - if !ok { - return errors.New("prompt must specify which variable to set") - } - var val string - var err error - for val == "" { - val, err = term.Prompt(ctx.Body + " ") - if err != nil { - return err - } - } - ctx.Runner.AddVariable(varName, val) - return nil -} - -func (self *Runner) HandlePause(*ActionContext) error { - if !self.AssumeDefault { - c := color.New(color.FgHiWhite, color.Bold) - _, err := term.Prompt(c.Sprintf("Press enter to continue: ")) - return err - } - return nil -} - -type parseBehavior interface { - IsStarting(source []byte) bool - GetStartToken() string - GetEndToken() string -} - -type CodeActionBlock struct{} - -func (self CodeActionBlock) IsStarting(source []byte) bool { - return startsWith(source, []byte(codeActionBlockStart)) -} - -func (self CodeActionBlock) GetStartToken() string { - return codeActionBlockStart -} - -func (self CodeActionBlock) GetEndToken() string { - return codeActionBlockEnd -} - -type CommentActionBlock struct{} - -func (self CommentActionBlock) IsStarting(source []byte) bool { - return startsWith(source, []byte(commentActionBlockStart)) -} - -func (self CommentActionBlock) GetStartToken() string { - return commentActionBlockStart -} - -func (self CommentActionBlock) GetEndToken() string { - return commentActionBlockEnd -} - -func startsWith(b []byte, val []byte) bool { - if len(b) < len(val) { - return false - } - return bytes.Equal(b[:len(val)], val) -} - -var CodeAction = CodeActionBlock{} -var CommentAction = CommentActionBlock{} diff --git a/ziti/cmd/ziti/tutorial/show.go b/ziti/cmd/ziti/tutorial/show.go deleted file mode 100644 index 5583dec48..000000000 --- a/ziti/cmd/ziti/tutorial/show.go +++ /dev/null @@ -1,64 +0,0 @@ -package tutorial - -import ( - "fmt" - "github.com/alecthomas/chroma/quick" - "github.com/pkg/errors" -) - -func NewShowActionHandler() *ShowActionHandler { - return &ShowActionHandler{ - data: map[string]string{}, - } -} - -type ShowActionHandler struct { - data map[string]string -} - -func (self *ShowActionHandler) Execute(ctx *ActionContext) error { - name, ok := ctx.Headers["src"] - if !ok { - return errors.New("no name specified in show") - } - - content, ok := self.data[name] - if !ok { - return errors.Errorf("no contents found to show for name: '%v'", name) - } - - if !ctx.Runner.AssumeDefault { - view, err := AskYesNoWithDefault(fmt.Sprintf("View source for %v? [Y/N] (default N): ", name), false) - if err != nil { - return err - } - if !view { - return nil - } - } - - codeWriter := NewSlowWriter(ctx.Runner.NewLinePause) - - fmt.Println("") - fmt.Printf("%v:\n", name) - for i := 0; i < 80; i++ { - fmt.Print("-") - } - fmt.Println("") - if lang, found := ctx.Headers["highlight"]; found { - if err := quick.Highlight(codeWriter, content, lang, "terminal", "friendly"); err != nil { - return err - } - } else { - _, _ = fmt.Fprintln(codeWriter, content) - } - for i := 0; i < 80; i++ { - fmt.Print("-") - } - fmt.Println("") - return ctx.Runner.HandlePause(ctx) -} - -func (self *ShowActionHandler) Add(name, contents string) { - self.data[name] = contents -} diff --git a/ziti/cmd/ziti/tutorial/slow_writer.go b/ziti/cmd/ziti/tutorial/slow_writer.go deleted file mode 100644 index f43780b31..000000000 --- a/ziti/cmd/ziti/tutorial/slow_writer.go +++ /dev/null @@ -1,43 +0,0 @@ -package tutorial - -import ( - "io" - "os" - "time" -) - -func NewSlowWriter(newlinePause time.Duration) io.Writer { - return &slowWriter{ - delay: newlinePause, - } -} - -type slowWriter struct { - delay time.Duration -} - -func (self *slowWriter) Write(p []byte) (n int, err error) { - var buf []byte - written := 0 - for _, b := range p { - buf = append(buf, b) - if b == '\n' { - time.Sleep(self.delay) - n, err := os.Stdout.Write(buf) - buf = buf[0:0] - written += n - if err != nil { - return written, err - } - } - } - - if len(buf) > 0 { - n, err := os.Stdout.Write(buf) - written += n - if err != nil { - return written, err - } - } - return written, nil -}