Merge pull request #884 from openziti/release-next

Release v0.26.11
This commit is contained in:
Paul Lorenz
2022-11-10 09:38:28 -05:00
committed by GitHub
62 changed files with 2595 additions and 2667 deletions
+11 -11
View File
@@ -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 }}
+8
View File
@@ -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.
+56
View File
@@ -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
+50
View File
@@ -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`.
+60 -44
View File
@@ -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.
+13
View File
@@ -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 #<issue number>` (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.
+4
View File
@@ -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.
+55 -200
View File
@@ -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 <admin name> -p <admin password>
# 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/<id>
```
...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 <path to enrollment.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).
+78 -464
View File
@@ -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 <service name> <dns host> <dns port> \
--hosted
--hosted-ids <someIdentityId>
--tags tunneler.dial.addr=<address for tunneler to dial>
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).
+414
View File
@@ -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 <<SHELL > ${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 <<YAML > $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 <<YAML > $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 <<YAML > $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.
+33 -34
View File
@@ -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
+71 -65
View File
@@ -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=
+31 -35
View File
@@ -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
+64 -68
View File
@@ -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=
+1 -1
View File
@@ -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{
+28
View File
@@ -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'
+9
View File
@@ -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}"
+10 -3
View File
@@ -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}"
+11 -10
View File
@@ -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
+757
View File
@@ -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...")
}
}
@@ -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 <optional-target> <id> <addr>",
Args: cobra.RangeArgs(1, 2),
Use: "raft-join <optional-target> <addr>",
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)
}
+11 -9
View File
@@ -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 }}
linkDialWorkerCount: {{ .Router.Forwarder.LinkDialWorkerCount }}
+9 -5
View File
@@ -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 {
@@ -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,
+8 -5
View File
@@ -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{}
@@ -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)
+29 -10
View File
@@ -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
@@ -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.")
}
@@ -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)
}
+121 -182
View File
@@ -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.")
}
+1
View File
@@ -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",
}
}
+9 -9
View File
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
+9 -9
View File
@@ -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 <destination>",
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)
+1
View File
@@ -60,6 +60,7 @@ type PKIFlags struct {
IP []string
Email []string
PKI *pki.ZitiPKI
SpiffeID string
}
var (
+19 -6
View File
@@ -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")
+29 -8
View File
@@ -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")
+12 -7
View File
@@ -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")
+33 -13
View File
@@ -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")
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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)
}
@@ -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
}
@@ -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)
}
@@ -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
}
@@ -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
}
@@ -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()
}
+2
View File
@@ -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"
)
-134
View File
@@ -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))
}
-35
View File
@@ -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
}
-37
View File
@@ -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)
}
})
}
}
-379
View File
@@ -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 = "<!---action:"
commentActionBlockEnd = "-->"
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{}
-64
View File
@@ -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
}
-43
View File
@@ -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
}