diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 000000000..858dec41a --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,18 @@ +name: codespell + +on: pull_request + +jobs: + codespell: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run code spelling check + uses: codespell-project/actions-codespell@v2 + with: + ignore_words_list: allos,ans,dne,noe,referr,ssudo,te,tranfer,ue + skip: go.*,zititest/go.* diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d43070f67..43ee4cc0b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -483,13 +483,11 @@ jobs: exit 1 elif [[ "${GITHUB_REF}" =~ ^refs/heads/(release-v|main$) ]]; then # Set output parameters for release branches - echo "DEBUG: ZITI_VERSION=${ZITI_VERSION}" - echo ZITI_VERSION="${ZITI_VERSION}" >> $GITHUB_OUTPUT + echo ZITI_VERSION="${ZITI_VERSION}" | tee -a $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 ZITI_VERSION="${ZITI_VERSION}" >> $GITHUB_OUTPUT + echo ZITI_VERSION="${ZITI_VERSION}" | tee -a $GITHUB_OUTPUT fi - name: Publish to Artifactory diff --git a/.gitignore b/.gitignore index 40a12d2d5..008d32d53 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ release/ # Binaries for programs and plugins *.exe *.exe~ +*.rpm +*.deb *.dll *.so *.dylib diff --git a/ADOPTERS.md b/ADOPTERS.md index 5154ff556..b47acb63d 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -38,6 +38,7 @@ Here's the list of projects which are proudly adopting and using OpenZiti | Analytics HQ | https://AnalyticsHQ.com/ | | Analytics HQ is a next-generation unified platform built for modern data management and advanced analytics. | | PITS Global Data Recovery Services | https://www.pitsdatarecovery.net/ | | PITS Global Data Recovery Services is a data recovery company in the United States that offers services for recovering data from hard drives, SSDs, flash drives, RAID arrays and more. | | KEOIC | http://www.keoic.com/ | | KEO International Consultants is a multifaceted AEC firm with a presence across the Middle East and Europe. KEO uses the CloudZiti platform to facilitate zero-trust connections for users, devices, and applications throughout their worldwide network of branch offices and sites. | -| ChirpWireless | https://chirpwireless.io/ | | Chirp is a project at the forefront of the DePIN (Decentralized physical infrastructure) movement, revolutionizing the world of wireless connectivity. It's a global telecommunications network that offers wireless internet and IoT connectivity for both residential and commercial use. OpenZiti overlay network is used for management of our LoRaWAN gateway miners ("Blackbirds") across multiple countries, allowing them to be dark. | +| ChirpWireless | https://chirpwireless.io/ | | Chirp is a project at the forefront of the DePIN (Decentralized physical infrastructure) movement, revolutionizing the world of wireless connectivity. It's a global telecommunications network that offers wireless internet and IoT connectivity for both residential and commercial use. OpenZiti overlay network is used for management of our LoRaWAN gateway miners ("Blackbirds") across multiple countries, allowing them to be dark. | | GIGO Dev | https://gigo.dev/ | | GIGO Dev is a learn-to-code platform that focuses on aligning learning with the real world of development. On GIGO you work in DevSpaces (Cloud Development Environments) capable of running nearly any system configuration needed for the challenge. We use OpenZiti to dynamically and securely expose network applications inside your DevSpace. Ziti provides the simplest, easiest, and most reliable system to securely route traffic into the local network of your DevSpace. | -| Underground Nexus | https://github.com/Underground-Ops/underground-nexus | | Cloud Underground has chosen OpenZiti to integrate with our project called the Underground Nexus. OpenZiti provides our project with a unique way to maintain Zero Trust networking using it's overlay system to produce networks that don't require applications to be exposed to the public web - without the use of a VPN. | +| Underground Nexus | https://github.com/Underground-Ops/underground-nexus | | Cloud Underground has chosen OpenZiti to integrate with our project called the Underground Nexus. OpenZiti provides our project with a unique way to maintain Zero Trust networking using it's overlay system to produce networks that don't require applications to be exposed to the public web - without the use of a VPN. | +| Ubitech | https://ubitech.eu/ | | UBITECH develops Maestro, an end-to-end service orchestrator, which allows for seamless deployment and management of services across geo-distributed and heterogeneous domains (including 5G). Maestro uses OpenZiti as a programmable integration fabric to enable connectivity in multi-domain and multi-tenant scenarios. | diff --git a/BUILD.md b/BUILD.md index d1c355bcc..af4e42418 100644 --- a/BUILD.md +++ b/BUILD.md @@ -5,4 +5,4 @@ Please refer to [the local development README](./doc/002-local-dev.md) for build ## 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](./docker-images/cross-build/README.md) 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. +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 executables locally is to build and run the crossbuild container. Please refer to [the crossbuild container README](./docker-images/cross-build/README.md) for those steps. For hints on crossbuilding for MacOS and Windows see [the main GitHub Actions workflow](../.github/workflows/main.yml) which defines the steps that are run when you push to GitHub. diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cf472c07..6a1da4145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,92 @@ +# Release 0.32.0 + +## What's New + +* Auth Rate Limiter +* Link Management Fixes +* ziti edge quickstart command deprecates redundant --already-initialized flag. The identical behavior is implied by --home. + +## Backwards compatibility + +This release includes new response types from the REST authentication APIS. They are now able to return +`429` (server too busy) responses to auth requests. As this is an API change, the version number is +being bumped to 0.32. + +If controller and router are both v0.32 or later, only the router which dialed a link will report it to the controller. +If the controller is older, newer routers will report links from both the dialing and listening side of the link. + +## Auth Rate Limiter + +In order to prevent clients from overwhelming the server with auth requests, an auth rate limiter has been introduced. +The rate limiter is adaptive, in that it will react to auth attempts timing out by shrinking the number of allowed +queued auth attempts. The number will slowly recover over time. + +Example configuration: + +``` +edge: + # This section allows configurating the rate limiter for auth attempts + authRateLimiter: + # if disabled, no auth rate limiting with be enforced + enabled: true + # the smallest window size for auth attempts + minSize: 5 + # the largest allowed window size for auth attempts + maxSize: 250 +``` + +New metrics: + +* `auth.limiter.queued_count` - current number of queued auth attempts +* `auth.limiter.window_size` - current size at which new auth attempts will be rejected +* `auth.limiter.work_timer` - tracks the rate at which api sessions are being created and how long it's taking to create them + +## Link Management Fixes + +With long lived link ids, there was potential for link control message to be ambiguous, as the link id wasn't enough to identify +a specific iteration of that link. An iteration field has been added to links so that messaging is unambiguous. +Links will also only be reported from the dialing router now to reduce ambiguouity and race condition in link control channel +messaging. + +## Router SSL Handshake Timeout Config + +There is a new router config setting which allows setting the SSL handshake timeout for TLS connections, when using ALPN for listeners. + +``` +tls: + handshakeTimeout: 15s +``` + +## Component Updates and Bug Fixes + +* github.com/openziti/channel/v2: [v2.0.111 -> v2.0.116](https://github.com/openziti/channel/compare/v2.0.111...v2.0.116) + * [Issue #123](https://github.com/openziti/channel/issues/123) - Ensure hello messages respect connect timeout + * [Issue #120](https://github.com/openziti/channel/issues/120) - Allow handling new underlay instances with function instead of channel + +* github.com/openziti/edge-api: [v0.26.6 -> v0.26.8](https://github.com/openziti/edge-api/compare/v0.26.6...v0.26.8) +* github.com/openziti/foundation/v2: [v2.0.35 -> v2.0.36](https://github.com/openziti/foundation/compare/v2.0.35...v2.0.36) + * [Issue #391](https://github.com/openziti/foundation/issues/391) - goroutine pool can stall if configured for 0 min workers and with single producer + +* github.com/openziti/identity: [v1.0.68 -> v1.0.69](https://github.com/openziti/identity/compare/v1.0.68...v1.0.69) +* github.com/openziti/metrics: [v1.2.41 -> v1.2.43](https://github.com/openziti/metrics/compare/v1.2.41...v1.2.43) +* github.com/openziti/runzmd: [v1.0.36 -> v1.0.37](https://github.com/openziti/runzmd/compare/v1.0.36...v1.0.37) +* github.com/openziti/sdk-golang: [v0.22.0 -> v0.22.17](https://github.com/openziti/sdk-golang/compare/v0.22.0...v0.22.17) + * [Issue #482](https://github.com/openziti/sdk-golang/issues/482) - Deprecate ListenOptions.MaxConnections in favor of MaxTerminators + +* github.com/openziti/secretstream: [v0.1.14 -> v0.1.16](https://github.com/openziti/secretstream/compare/v0.1.14...v0.1.16) +* github.com/openziti/storage: [v0.2.27 -> v0.2.28](https://github.com/openziti/storage/compare/v0.2.27...v0.2.28) +* github.com/openziti/transport/v2: [v2.0.119 -> v2.0.121](https://github.com/openziti/transport/compare/v2.0.119...v2.0.121) + * [Issue #73](https://github.com/openziti/transport/issues/73) - Allow overriding shared TLS/ALPN listener SSL handshake timeout + +* github.com/openziti/ziti: [v0.31.4 -> v0.32.0](https://github.com/openziti/ziti/compare/v0.31.4...v0.32.0) + * [Issue #1692](https://github.com/openziti/ziti/issues/1692) - Improve link stability with long lived link ids + * [Issue #1693](https://github.com/openziti/ziti/issues/1693) - Make links owned by the dialing router + * [Issue #1685](https://github.com/openziti/ziti/issues/1685) - Race condition where we try to create terminator after client connection is closed + * [Issue #1678](https://github.com/openziti/ziti/issues/1678) - Add link validation utility + * [Issue #1673](https://github.com/openziti/ziti/issues/1673) - xgress dialers not getting passed xgress config + * [Issue #1669](https://github.com/openziti/ziti/issues/1669) - Make sure link accepts are not single threaded + * [Issue #1657](https://github.com/openziti/ziti/issues/1657) - Add api session rate limiter + # Release 0.31.4 ## What's New @@ -92,7 +181,7 @@ ziti fabric raft remove-member ctrl3 * Terminator validation utility * Circuit/Link query support -## SDK Hosting Improvments +## SDK Hosting Improvements In previous versions of OpenZiti, if many SDK clients were attempting to establish hosting, the controller could get overwhelmed. In this release, routers will use the rate limiter pool introduced in 0.27.6 when creating terminators on behalf of sdk clients @@ -162,7 +251,7 @@ When the rate limit is hit, an error will be returned. If the request came in fr the REST API, the response will use HTTP status code 429 (too many requests). The OpenAPI specs have been updated, so if you're using a generated client to make -REST calls, it's recommened that you regenerate your client. +REST calls, it's recommended that you regenerate your client. ``` @@ -173,7 +262,7 @@ commandRateLimiter: If the rate limiter is enabled, the following metrics will be produced: -* `command.limiter.queued_count` - guage of the current number of queued operations +* `command.limiter.queued_count` - gauge of the current number of queued operations * `command.limiter.work_timer` - timer for operations. Includes the following: * A histogram of how long operations take to complete * A meter showing that rate at which operations are executed @@ -189,7 +278,7 @@ If the rate limiter is enabled, the following metrics will be produced: * github.com/openziti/identity: [v1.0.64 -> v1.0.66](https://github.com/openziti/identity/compare/v1.0.64...v1.0.66) * github.com/openziti/metrics: [v1.2.36 -> v1.2.37](https://github.com/openziti/metrics/compare/v1.2.36...v1.2.37) * github.com/openziti/sdk-golang: [v0.20.122 -> v0.20.129](https://github.com/openziti/sdk-golang/compare/v0.20.122...v0.20.129) - * [Issue #443](https://github.com/openziti/sdk-golang/issues/443) - Don't send close in reponse to a close on a listener + * [Issue #443](https://github.com/openziti/sdk-golang/issues/443) - Don't send close in response to a close on a listener * github.com/openziti/secretstream: [v0.1.12 -> v0.1.13](https://github.com/openziti/secretstream/compare/v0.1.12...v0.1.13) * github.com/openziti/storage: [v0.2.20 -> v0.2.23](https://github.com/openziti/storage/compare/v0.2.20...v0.2.23) @@ -246,7 +335,7 @@ Currently only HTTP Connect proxies which don't require authentication are suppo * github.com/openziti/ziti: [v0.30.4 -> v0.30.5](https://github.com/openziti/ziti/compare/v0.30.4...v0.30.5) * [Issue #1336](https://github.com/openziti/ziti/issues/1336) - `ziti edge quickstart` did not create the usual edge router/service edge router policy. - * [Issue #1397](https://github.com/openziti/ziti/issues/1397) - HTTP Proxy suport for host.v1/host.v2 config types + * [Issue #1397](https://github.com/openziti/ziti/issues/1397) - HTTP Proxy support for host.v1/host.v2 config types * [Issue #1423](https://github.com/openziti/ziti/issues/1423) - Controller crashes when edge router reconnects (Client Hello) * [Issue #1414](https://github.com/openziti/ziti/issues/1414) - Race condition in xgress_edge_tunnel tunneller at start but not seen in pre-compiled binary * [Issue #1406](https://github.com/openziti/ziti/issues/1406) - Entity change event dispatcher isn't shutting down properly when controller shuts down @@ -279,7 +368,7 @@ Currently only HTTP Connect proxies which don't require authentication are suppo ziti edge quickstart \ --ctrl-address potato \ --ctrl-port 12345 \ - --router-address avacado \ + --router-address avocado \ --router-port 23456 \ --home $HOME/.ziti/pet-ziti \ --already-initialized \ @@ -328,7 +417,7 @@ Prior to this release there were four identity types: Of these four types, only Router has any functional purpose. Given that, the other three have been merged into a single `Default` identity type. Since Router identities can only be created by the system, it's no longer -necesary to specify the identity type when creating identities. +necessary to specify the identity type when creating identities. The identity type may still be provided, but a deprecation warning will be emitted. @@ -341,7 +430,7 @@ code may have issues with the new identity type being returned. ## HTTP Connect Proxy support -Routers may now specify a proxy configuation which will be used when establishing connections to controllers +Routers may now specify a proxy configuration which will be used when establishing connections to controllers and data links to other routers. At this point only HTTP Connect Proxies with no authentication required are supported. @@ -682,7 +771,7 @@ Bug fix * github.com/openziti/channel/v2: [v2.0.80 -> v2.0.81](https://github.com/openziti/channel/compare/v2.0.80...v2.0.81) * github.com/openziti/edge: [v0.24.326 -> v0.24.345](https://github.com/openziti/edge/compare/v0.24.326...v0.24.345) - * [Issue #1528](https://github.com/openziti/edge/issues/1528) - edge unbind returns incorect message if token is not suplied or invalid + * [Issue #1528](https://github.com/openziti/edge/issues/1528) - edge unbind returns incorrect message if token is not supplied or invalid * [Issue #1416](https://github.com/openziti/edge/issues/1416) - Allow MFA token name to be configured * github.com/openziti/edge-api: [v0.25.25 -> v0.25.29](https://github.com/openziti/edge-api/compare/v0.25.25...v0.25.29) @@ -816,7 +905,7 @@ events: ## What's New * Event changes - * Added AMQP event writter for events + * Added AMQP event writer for events * Add entity change events for auditing or external integration * Add usage event filtering * Add annotations to circuit events @@ -1023,7 +1112,7 @@ listeners: * [Issue #1471](https://github.com/openziti/edge/issues/1471) - UDP intercept connections report incorrect local/remote addresses, making confusing events * [Issue #629](https://github.com/openziti/edge/issues/629) - emit entity change events * [Issue #1295](https://github.com/openziti/edge/issues/1295) - Ensure DB migrations work properly in a clustered setup (edge) - * [Issue #1418](https://github.com/openziti/edge/issues/1418) - Checks for session edge router availablility are inefficient + * [Issue #1418](https://github.com/openziti/edge/issues/1418) - Checks for session edge router availability are inefficient * github.com/openziti/edge-api: [v0.25.11 -> v0.25.24](https://github.com/openziti/edge-api/compare/v0.25.11...v0.25.24) * github.com/openziti/fabric: [v0.22.87 -> v0.23.29](https://github.com/openziti/fabric/compare/v0.22.87...v0.23.29) diff --git a/README.md b/README.md index 4dbcfe7e5..a5cd234da 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ OpenZiti represents the next generation of secure, open-source networking for yo ## What is OpenZiti? -* The OpenZiti fabric provides a scalable, plugable, networking mesh with built in smart routing +* The OpenZiti fabric provides a scalable, pluggable, 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 OpenZiti directly into your applications * The OpenZiti tunnelers and proxies allow existing applications and networks to take advantage of a OpenZiti deployment diff --git a/changelogs/CHANGELOG.0.12.md b/changelogs/CHANGELOG.0.12.md index 4974b24c1..b2c27cab8 100644 --- a/changelogs/CHANGELOG.0.12.md +++ b/changelogs/CHANGELOG.0.12.md @@ -30,7 +30,7 @@ This release does not yet include a terminator strategy API. Strategies can be s service, but if a service has multiple terminators the first one will be used. The terminator strategy API along with some implementations will be added in a follow-up release. This release also does not include strategy inputs on terminators as discussed in the above design document. If -strategy inputs end up being useful, they may be added in the furure. +strategy inputs end up being useful, they may be added in the future. ### Terminator related API changes diff --git a/changelogs/CHANGELOG.0.13.md b/changelogs/CHANGELOG.0.13.md index e36bac67f..b9bf22c0e 100644 --- a/changelogs/CHANGELOG.0.13.md +++ b/changelogs/CHANGELOG.0.13.md @@ -297,17 +297,17 @@ When building UIs it may be useful to list entities which have role attributes b see what policy changes may look like. * Endpoint: /edge-routers - * Query: GET /edge-routers now supports two new query paramters + * Query: GET /edge-routers now supports two new query parameters * roleFilter. May be specified more than one. Should be an id or role specifier (ex: @38683097-2412-4335-b056-ae8747314dd3 or #sales) * roleSemantic. Optional. Defaults to AllOf if not specified. Indicates which semantic to use when evaluating role matches * Endpoint: /identities - * Query: GET /identities now supports two new query paramters + * Query: GET /identities now supports two new query parameters * roleFilter. May be specified more than one. Should be an id or role specifier (ex: @38683097-2412-4335-b056-ae8747314dd3 or #sales) * roleSemantic. Optional. Defaults to AllOf if not specified. Indicates which semantic to use when evaluating role matches * Endpoint: /services - * Query: GET /services now supports two new query paramters + * Query: GET /services now supports two new query parameters * roleFilter. May be specified more than one. Should be an id or role specifier (ex: @38683097-2412-4335-b056-ae8747314dd3 or #sales) * roleSemantic. Optional. Defaults to AllOf if not specified. Indicates which semantic to use when evaluating role matches diff --git a/changelogs/CHANGELOG.0.14.md b/changelogs/CHANGELOG.0.14.md index fe79e040e..40c594955 100644 --- a/changelogs/CHANGELOG.0.14.md +++ b/changelogs/CHANGELOG.0.14.md @@ -347,7 +347,7 @@ can react to terminator changes, such when a terminator is added to or removed f service is also notified via `NotifyEvent` whenever a session dial succeeds or fails and when a session for the service is ended. -The fabric currently provides four strategy implementions. +The fabric currently provides four strategy implementations. ##### `smartrouting` @@ -383,6 +383,6 @@ The terminator endpoint now supports setting the static terminator cost and term * Endpoint: /terminators * Operations: PUT/POST/PATCH now take * cost, type uint16, default 0 - * prededence, type string, default 'default', valid values: required, default, failed + * precedence, type string, default 'default', valid values: required, default, failed * Operation: GET now returns staticCost, dynamicCost diff --git a/changelogs/CHANGELOG.0.15.md b/changelogs/CHANGELOG.0.15.md index d2d848904..76ad0abaf 100644 --- a/changelogs/CHANGELOG.0.15.md +++ b/changelogs/CHANGELOG.0.15.md @@ -81,7 +81,7 @@ from a pre-0.9 version you should first update to 0.14.12, then to new versions. ## Database Snapshots -Database snapshots can now be triggered in a variety of ways to cause the creation of a dabase +Database snapshots can now be triggered in a variety of ways to cause the creation of a database backup/snapshot. This can be done from the ziti-fabric CLI, the ziti CLI and the REST API $ ziti-fabric snapshot-db @@ -97,7 +97,7 @@ will have the data and time appended to it. Snapshotting can be done at most onc Previously edge routers and fabric routers were closely related, but weren't actually the same entity. When an edge router was created, there was no corresponding fabric router until the edge -router had been succesfully enrolled. +router had been successfully enrolled. Now, edge routers are a type of fabric router. When an edge router is created, it will be visible as a fabric router with no fingerprint. This means that the corresponding router application won't be diff --git a/changelogs/CHANGELOG.0.16.md b/changelogs/CHANGELOG.0.16.md index 08c354ab2..33bbb2f19 100644 --- a/changelogs/CHANGELOG.0.16.md +++ b/changelogs/CHANGELOG.0.16.md @@ -219,7 +219,7 @@ To this end, terminators now have two new fields: Notes 1. Identity here may be related to the concept of the Edge Identity, but is not required to be. -2. How IdentitySecret is used to validate a terminator is up to the terminator valiator for the +2. How IdentitySecret is used to validate a terminator is up to the terminator validator for the binding. The edge has a terminator validator which uses the client's certs to ensure that all terminators for a given terminator identity belong to the same edge identity. diff --git a/changelogs/CHANGELOG.0.18.md b/changelogs/CHANGELOG.0.18.md index 517de88ff..a9e05fcf4 100644 --- a/changelogs/CHANGELOG.0.18.md +++ b/changelogs/CHANGELOG.0.18.md @@ -412,7 +412,7 @@ listeners: * Improve service list time by using indexes get related posture data * Improved service polling * Improved service policy enforcement - instead of polling this is now event based, which should - result in slower cpu utlization on the controller + result in slower cpu utilization on the controller * Fixed a bug in service policy PATCH which would trigger when the policy type wasn't sent * Support agent utilitiles (`ziti ps`) in ziti-tunnel * Cleanup ack handler goroutines when links shut down @@ -429,7 +429,7 @@ listeners: * A new metric has been added for timing service list requests `services.list` * A bug was fixed in the tunneler which may have lead to leaked connections * Ziti Edge API configurable HTTP Timeouts -* Add `ziti log-format` or `ziti lf` for short, for formating JSON log output as something more +* Add `ziti log-format` or `ziti lf` for short, for formatting JSON log output as something more human readable * [fabric#151](https://github.com/openziti/fabric/issues/151) Add two timeout settings to the controller to configure how long route and dial should wait before timeout @@ -472,7 +472,7 @@ edge: readHeaderTimeoutMs: 0 # (optional, default 10000) writeTimeoutMs is the maximum duration before timing out writes of the response. writeTimeoutMs: 100000 - # (optional, default 5000) idleTimeoutMs is the maximum amount of time to wait for the next request when keep-alives are enabled + # (optional, default 5000) idleTimeoutMs is the maximum amount of time to wait for the next request when keepalives are enabled idleTimeoutMs: 5000 ``` @@ -926,11 +926,11 @@ dropping data for a client if the client isn't handling incoming traffic quickly payloads will be retransmitted. The new xgress implementation uses similar windowing and retransmission strategies to the upcoming transwarp work. -### Backwards Compatability +### Backwards Compatibility 0.18+ routers will probably work with older router versions, but probably not well. 0.18+ xgress instances expect to get round trip times and receive buffer sizes on ack messages. If they don't get -them then retransmission will likely be either too agressive or not aggressive enough. +them then retransmission will likely be either too aggressive or not aggressive enough. Mixing 0.18+ routers with older router versions is not recommended without doing more testing first. @@ -942,7 +942,7 @@ Mixing 0.18+ routers with older router versions is not recommended without doing * txPortalStartSize - Initial size of send window. Default value: 16Kb * txPortalMinSize - Smallest allowed send window size. Default value: 16Kb * txPortalMaxSize - Largest allowed send window size. Default value: 4MB -* txPortalIncreaseThresh - Number of successful aks after which to increase send portal size: +* txPortalIncreaseThresh - Number of successful acks after which to increase send portal size: Default value: 224 * txPortalIncreaseScale - Send portal will be increased by amount of data sent since last retransmission. This controls how much to scale that amount by. Default value: 1.0 @@ -1020,12 +1020,12 @@ The new metrics include: * Times how long it takes to process xgress payloads coming off the link (mostly getting them into the receive buffer) * xgress.payload_relay_time - * Times how long it takes to get xgress payloads out of the recieve buffer and queued to be sent + * Times how long it takes to get xgress payloads out of the receive buffer and queued to be sent **New Gauges** * xgress.blocked_by_local_window - * Count of how many xgress instances are blocked because the local tranmit buffer size equals or + * Count of how many xgress instances are blocked because the local transmit buffer size equals or exceeds the window size * xgress.blocked_by_local_window * Count of how many xgress instances are blocked because the remote receive buffer size equals @@ -1096,7 +1096,7 @@ If the connection id could be established on the router, we could simplify thing We didn't do this previously because the sdk controls ids for outbound connection. To enable this we have split the 32 bit id range in half. The top half is now reserved for hosted connection ids. This -behavior is controlled by the SDK, which requests it when it binds uisng a boolean flag. The new +behavior is controlled by the SDK, which requests it when it binds using a boolean flag. The new flag is: ``` @@ -1106,4 +1106,4 @@ flag is: If the bind result from the router has the same flag set to true, then the sdk will expect Dial messages from the router to have a connection id provided in the header keyed with the same `1012`. -This means that this feature should be both backwards and forward compatible. \ No newline at end of file +This means that this feature should be both backwards and forward compatible. diff --git a/changelogs/CHANGELOG.0.19.md b/changelogs/CHANGELOG.0.19.md index d03bd5f24..48dd7c5a2 100644 --- a/changelogs/CHANGELOG.0.19.md +++ b/changelogs/CHANGELOG.0.19.md @@ -96,7 +96,7 @@ Example JSON output: Caveats: * Any existing host.v1 configurations that use will become invalid. - * ziti-tunnel and the converged router/tunneler creates local routes that are establised for `allowedSourceAddresses`, but the routes are not consistently cleaned up when `ziti-tunnel` exits. This issue will be addressed in a future release. + * ziti-tunnel and the converged router/tunneler creates local routes that are established for `allowedSourceAddresses`, but the routes are not consistently cleaned up when `ziti-tunnel` exits. This issue will be addressed in a future release. # Release 0.19.10 @@ -114,9 +114,9 @@ Example JSON output: * Converged Tunneler/Router (Beta 2) * intercept.v1 support (also in ziti-tunnel) * support for setting per-service hosting cost/precedence on identity -* Identites and edge routers now support appData, which is tag data consumable by sdks +* Identities and edge routers now support appData, which is tag data consumable by sdks * Edge Router Policies now expose the `isSystem` flag for system managed policies -* ziti-tunnel no longer supports tun mode. It has been superceded by tproxy mode +* ziti-tunnel no longer supports tun mode. It has been superseded by tproxy mode ## Fixes @@ -209,7 +209,7 @@ ziti-router can now run with the tunneler embedded. It has the same capabilities This is a beta release. It should be relatively feature complete and bug-free for hosting services but intercept support is still nascent. Some features are likely to be changed based on user feedback. -### Os Compatibilty +### Os Compatibility Like ziti-tunnel, `tproxy` mode will only work on linux. `proxy` and `host` modes should work on all operating systems. @@ -373,7 +373,7 @@ See here: https://github.com/openziti/edge/blob/v0.19.54/tunnel/entities/host.v1 ### host.v2 -There is a new host configuration, `host.v2`, which should supercede `host.v1`. The primary difference from `host.v1` is that it supports multiple terminators. This means that when a service is hosted by a router, it can connect to multiple service instances if the service is horizontally scaled, or in a primary/failover setup. +There is a new host configuration, `host.v2`, which should supersede `host.v1`. The primary difference from `host.v1` is that it supports multiple terminators. This means that when a service is hosted by a router, it can connect to multiple service instances if the service is horizontally scaled, or in a primary/failover setup. Each terminator definition is the same as a `host.v1` configuration, which one exception: `listOptions.connectTimeoutSeconds` is now `listenOptions.connectTimeout` and is specified as a duration (`5s`, `2500ms`, etc). diff --git a/changelogs/CHANGELOG.0.22.md b/changelogs/CHANGELOG.0.22.md index 49b925e47..4dfc9a787 100644 --- a/changelogs/CHANGELOG.0.22.md +++ b/changelogs/CHANGELOG.0.22.md @@ -64,7 +64,7 @@ Output responses include: - `200 OK` w/ empty object payloads: `{}` - `401 UNAUTHORIZED` w/ standard error messaging -- `400 BAD REQUESET` w/ standard error messaging for field errors or CSR processing errors +- `400 BAD REQUEST` w/ standard error messaging for field errors or CSR processing errors # Release 0.22.9 @@ -174,7 +174,7 @@ plorenz@carrot:~/work/nf$ ziti edge traceroute simple -c ./simple-client.json ## What's New -* Bug fix: Fix panic in listener close if the socket hadn't been initalized yet +* Bug fix: Fix panic in listener close if the socket hadn't been initialized yet * Bug fix: Fix panic in posture bulk create if mfa wasn't set * Bug fix: Fix panic in circuit creation on race condition when circuits are add/removed concurrently @@ -291,7 +291,7 @@ Fabric sessions renamed to circuits. External integrators may be impacted by cha ### Ziti CLI -Commands under `ziti edge` now reserve the `-i` flag for specifying client identity. Any command line argumet which +Commands under `ziti edge` now reserve the `-i` flag for specifying client identity. Any command line argument which previously had a `-i` short version now only has a long version. For consistency, policy roles parameters must all be specified in long form @@ -307,7 +307,7 @@ This includes the following flags: * ziti edge create posture-check mfa --ignore-legacy * ziti edge update posture-check mfa --ignore-legacy * ziti edge update authenticator updb --identity -* ziti egde update ca --identity-atributes (now -a) +* ziti edge update ca --identity-atributes (now -a) The `ziti edge` commands now store session credentials in a new location and new format. Existing sessions will be ignored. @@ -355,7 +355,7 @@ field, which is set to 2. # Pending Link Timeout -Previously whenever a router connected we'd look for new links possiblities and create new links between routers where +Previously whenever a router connected we'd look for new links possibilities and create new links between routers where any were missing. If lots of routers connected at the same time, we might create duplicate links because the links hadn't been reported as established yet. Now we'll checking for links in Pending state, and if they haven't hit a configurable timeout, we won't create another link. @@ -384,7 +384,7 @@ provided and the server's well known certs will not be downloaded. ### Identities -The Ziti CLI now suports multiple identities. An identity can be specified using `--cli-identity` or `-i`. +The Ziti CLI now supports multiple identities. An identity can be specified using `--cli-identity` or `-i`. Example commands: @@ -410,7 +410,7 @@ The above example could also be accomplished as follows: ``` $ ziti edge use dev -Settting identity 'dev' as default in ~/.config/ziti/ziti-cli.json +Setting identity 'dev' as default in ~/.config/ziti/ziti-cli.json $ ziti edge login localhost:1280 Enter username: admin @@ -423,7 +423,7 @@ id: -JucPW0kGR name: ssh encryption required: true terminator strategy: results: 1-1 of 1 $ ziti edge use default -Settting identity 'default' as default in ~/.config/ziti/ziti-cli.json +Setting identity 'default' as default in ~/.config/ziti/ziti-cli.json ``` `ziti edge use` without an argument will list logins you have made. diff --git a/changelogs/CHANGELOG.0.23.md b/changelogs/CHANGELOG.0.23.md index a1aed90fd..aa7019b2d 100644 --- a/changelogs/CHANGELOG.0.23.md +++ b/changelogs/CHANGELOG.0.23.md @@ -15,7 +15,7 @@ * Security: Router link listeners weren't properly validating certs against the server cert chain * Security: Link listeners now validate incoming links to ensure that the link was requested by the controller and the correct router dialed -* Security: Don't allow link forwarding entries to be overriden, as link ids should be unique +* Security: Don't allow link forwarding entries to be overridden, as link ids should be unique * Security: Validate ctrl channel clients against controller cert chain in addition to checking cert fingerprint ## Breaking Changes diff --git a/changelogs/CHANGELOG.0.24.md b/changelogs/CHANGELOG.0.24.md index 292f6a08b..bffc0549e 100644 --- a/changelogs/CHANGELOG.0.24.md +++ b/changelogs/CHANGELOG.0.24.md @@ -166,7 +166,7 @@ These are true for all REST API and control channel addresses. Notes: -- This process may take days, weeks, or months depending on the size of the nework and how often the router/clients are +- This process may take days, weeks, or months depending on the size of the network and how often the router/clients are run - It is imperative that all clients/routers that will remain in use after the IP/hostname move connect at least once after `newAddress` and `newListener` values are configured and in use diff --git a/changelogs/CHANGELOG.0.25.md b/changelogs/CHANGELOG.0.25.md index 4fa598e6b..bb73871d9 100644 --- a/changelogs/CHANGELOG.0.25.md +++ b/changelogs/CHANGELOG.0.25.md @@ -223,7 +223,7 @@ Currently each section of the dial logic has its own timeouts. It can easily hap an early stage timeout expires while a later one doesn't, causing work to be done whose results will be ignored. A first pass has been completed at threading timeouts/deadline through the dial logic, spanning controller and routers, so that we use approximately -the same timeout througout the dial process. +the same timeout throughout the dial process. ### Link Initial Latency Previously links would start with a latency of 0, which they would keep until the latency @@ -242,7 +242,7 @@ network: ``` ### Link Verification changes -In previous releases when a router recieved a link dial from another router, it would verify +In previous releases when a router received a link dial from another router, it would verify that the link was known to the controller and the dialing router was valid. Router validity was checked by making sure the fingerprints of the certs used to establish the link matched the fingerprints on record for the router. @@ -387,7 +387,7 @@ The `ziti-probe` tool will no longer be built and published as part of Ziti rele * Enhancement: `ziti edge update config-type` is now available * Enhancement: `ziti edge create|update identity` now supports `--external-id` * Bug fix: Fixes an issue where the router config would use hostname instead of the DNS name -* Bug fix: When establishing links, a link could be closed while being registered, leading the controlller and router to get out of sync +* Bug fix: When establishing links, a link could be closed while being registered, leading the controller and router to get out of sync * Enhancement: Add min router cost. Helps to minimize unnecessary hops. * Defaults to 10, configurable in the controller config with the minRouterCost value under `network:` * Enhancement: Can now see xgress instance and link send buffer pointer values in circuit inspections. This allows correlating to stackdumps @@ -609,7 +609,7 @@ Example Create: ## JWT Primary/Secondary Authentication -A new primary authentication mechanism is available in addition to `cert` and `passsword` (UPDB). The internal +A new primary authentication mechanism is available in addition to `cert` and `password` (UPDB). The internal method name is `ext-jwt` and it allows authentication by providing a bearer token by a known external JWT signer. A new entity `External JWT Singer` has been introduced and is defined in subsequent sections. diff --git a/changelogs/CHANGELOG.0.26.md b/changelogs/CHANGELOG.0.26.md index 629d78235..2e48b1791 100644 --- a/changelogs/CHANGELOG.0.26.md +++ b/changelogs/CHANGELOG.0.26.md @@ -44,7 +44,7 @@ ziti create config router edge --routerName myRouter --tunnelerMode tproxy --lan * 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 #317](https://github.com/openziti/sdk-golang/issues/317) - No documentation 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) @@ -232,7 +232,7 @@ events: - type: fabric.usage version: 2 - type: fabric.usage - versin: 3 + version: 3 ``` If no version is provided for usage, then v2 events will still be outputted by default. @@ -410,7 +410,7 @@ The only change in this release is updating from Golang 1.18 to 1.19 Previously if a router had multiple links and one of them was slow or blocked, it could prevent other traffic from moving. Now, if a link is unable to keep up with incoming traffic, payloads will be dropped. The end-to-end flow control and retransmission logic will handle re-sending the packet. -Links have a 64 message queue for incoming messages. Up to 64 messages are taken off the queue, sorted in priority order and then sent. Once the sorted list of messages has been sent, the next set of messages are dequeue, sorted and sent. If the queue fills while the current set of sorted messges is being sent, message will now be dropped instead of waiting for queue space to open up. +Links have a 64 message queue for incoming messages. Up to 64 messages are taken off the queue, sorted in priority order and then sent. Once the sorted list of messages has been sent, the next set of messages are dequeue, sorted and sent. If the queue fills while the current set of sorted messages is being sent, message will now be dropped instead of waiting for queue space to open up. There is now a new per-link `link.dropped_msgs` metric to track how often links are dropping messages. @@ -566,7 +566,7 @@ events: * `dialed` : Generated when the controller sends a link dial message to a router * `connected` : Generated when a router sends a link connected message to the controller * `fault` : Generated when a router sends a link fault to the controller -* `routerLinkNew` : Generated when a router sends a router link message to the controler and the link is new to the controller +* `routerLinkNew` : Generated when a router sends a router link message to the controller and the link is new to the controller * `routerLinkKnown` : Generated when a router sends a router link message to the controller and the link is known * `routerLinkDisconnectedDest` : Generated when a router sends a route link message to the controller and the router on the other side of the link is not currently connected. @@ -983,7 +983,7 @@ The `mgmt:` stanza in configuration files, which used to be required, will now b ### Old Metrics Subsystem removed -Formerly metrics could be exported to file via the `metrics:` configuration stanza. This was superceded by +Formerly metrics could be exported to file via the `metrics:` configuration stanza. This was superseded by the events subsystem, which contains metrics as well as other events. This also means that we no longer support pushing metrics directly to InfluxDB. However, we now have a diff --git a/changelogs/CHANGELOG.0.6.md b/changelogs/CHANGELOG.0.6.md index 5a2309284..141de7db0 100644 --- a/changelogs/CHANGELOG.0.6.md +++ b/changelogs/CHANGELOG.0.6.md @@ -4,7 +4,7 @@ Ziti 0.6.0 moves the back-end persistence model of Ziti Edge and Ziti Fabric into the same repository based on Bbolt (an in memory data store that is backed by a memory mapped file). The -changes remove the requirement for PostgresSQL. +changes remove the requirement for PostgreSQL. ## UPDB Enrollment JWTs diff --git a/changelogs/CHANGELOG.0.9.md b/changelogs/CHANGELOG.0.9.md index b6c4c2e5a..8d0164568 100644 --- a/changelogs/CHANGELOG.0.9.md +++ b/changelogs/CHANGELOG.0.9.md @@ -257,7 +257,7 @@ policies must now be created with no other roles or entity references. ### Service Edge Router Policy -Previously services could be confgured with edge router roles, which limited which edge routers +Previously services could be configured with edge router roles, which limited which edge routers could be used to dial or bind the service. In 0.9 that is replaced with a new standalone type: service edge router policies. A service edge diff --git a/common/capabilities/check.go b/common/capabilities/check.go new file mode 100644 index 000000000..6e7373419 --- /dev/null +++ b/common/capabilities/check.go @@ -0,0 +1,33 @@ +/* + 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 capabilities + +import ( + "github.com/openziti/channel/v2" + "github.com/openziti/ziti/common/pb/ctrl_pb" + "math/big" +) + +func IsCapable(ch channel.Channel, capability int) bool { + headers := ch.Underlay().Headers() + if val, found := headers[int32(ctrl_pb.ControlHeaders_CapabilitiesHeader)]; found { + capabilitiesMask := &big.Int{} + capabilitiesMask.SetBytes(val) + return capabilitiesMask.Bit(capability) == 1 + } + return false +} diff --git a/common/capabilities/consts.go b/common/capabilities/consts.go index 0a73ae725..ad29acf53 100644 --- a/common/capabilities/consts.go +++ b/common/capabilities/consts.go @@ -17,5 +17,6 @@ package capabilities const ( - ControllerCreateTerminatorV2 int = 1 + ControllerCreateTerminatorV2 int = 1 + ControllerSingleRouterLinkSource int = 2 ) diff --git a/common/inspect/links_inspect_result.go b/common/inspect/links_inspect_result.go index c1c2807f0..4b00388c1 100644 --- a/common/inspect/links_inspect_result.go +++ b/common/inspect/links_inspect_result.go @@ -28,6 +28,7 @@ type LinksInspectResult struct { type LinkInspectDetail struct { Id string `json:"id"` + Iteration uint32 `json:"iteration"` Key string `json:"key"` Split bool `json:"split"` Protocol string `json:"protocol"` @@ -49,8 +50,8 @@ type LinkState struct { Id string `json:"id"` Key string `json:"key"` Status string `json:"status"` - DialAttempts uint `json:"dialAttempts"` - ConnectedCount uint `json:"connectedCount"` + DialAttempts uint64 `json:"dialAttempts"` + ConnectedCount uint64 `json:"connectedCount"` RetryDelay string `json:"retryDelay"` NextDial string `json:"nextDial"` TargetAddress string `json:"targetAddress"` @@ -58,4 +59,5 @@ type LinkState struct { TargetBinding string `json:"targetBinding"` DialerGroups []string `json:"dialerGroups"` DialerBinding string `json:"dialerBinding"` + CtrlsNotified bool `json:"ctrlsNotified"` } diff --git a/common/pb/ctrl_pb/ctrl.pb.go b/common/pb/ctrl_pb/ctrl.pb.go index 7edd57df1..16e4e1a94 100644 --- a/common/pb/ctrl_pb/ctrl.pb.go +++ b/common/pb/ctrl_pb/ctrl.pb.go @@ -57,9 +57,6 @@ const ( ContentType_ValidateTerminatorsV2ResponseType ContentType = 1042 ContentType_DecommissionRouterRequestType ContentType = 1043 ContentType_PeerStateChangeRequestType ContentType = 1050 - ContentType_ListenersHeader ContentType = 10 - ContentType_RouterMetadataHeader ContentType = 11 - ContentType_CapabilitiesHeader ContentType = 12 ) // Enum value maps for ContentType. @@ -93,9 +90,6 @@ var ( 1042: "ValidateTerminatorsV2ResponseType", 1043: "DecommissionRouterRequestType", 1050: "PeerStateChangeRequestType", - 10: "ListenersHeader", - 11: "RouterMetadataHeader", - 12: "CapabilitiesHeader", } ContentType_value = map[string]int32{ "Zero": 0, @@ -126,9 +120,6 @@ var ( "ValidateTerminatorsV2ResponseType": 1042, "DecommissionRouterRequestType": 1043, "PeerStateChangeRequestType": 1050, - "ListenersHeader": 10, - "RouterMetadataHeader": 11, - "CapabilitiesHeader": 12, } ) @@ -159,6 +150,58 @@ func (ContentType) EnumDescriptor() ([]byte, []int) { return file_ctrl_proto_rawDescGZIP(), []int{0} } +type ControlHeaders int32 + +const ( + ControlHeaders_NoneHeader ControlHeaders = 0 + ControlHeaders_ListenersHeader ControlHeaders = 10 + ControlHeaders_RouterMetadataHeader ControlHeaders = 11 + ControlHeaders_CapabilitiesHeader ControlHeaders = 12 +) + +// Enum value maps for ControlHeaders. +var ( + ControlHeaders_name = map[int32]string{ + 0: "NoneHeader", + 10: "ListenersHeader", + 11: "RouterMetadataHeader", + 12: "CapabilitiesHeader", + } + ControlHeaders_value = map[string]int32{ + "NoneHeader": 0, + "ListenersHeader": 10, + "RouterMetadataHeader": 11, + "CapabilitiesHeader": 12, + } +) + +func (x ControlHeaders) Enum() *ControlHeaders { + p := new(ControlHeaders) + *p = x + return p +} + +func (x ControlHeaders) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ControlHeaders) Descriptor() protoreflect.EnumDescriptor { + return file_ctrl_proto_enumTypes[1].Descriptor() +} + +func (ControlHeaders) Type() protoreflect.EnumType { + return &file_ctrl_proto_enumTypes[1] +} + +func (x ControlHeaders) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ControlHeaders.Descriptor instead. +func (ControlHeaders) EnumDescriptor() ([]byte, []int) { + return file_ctrl_proto_rawDescGZIP(), []int{1} +} + type RouterCapability int32 const ( @@ -189,11 +232,11 @@ func (x RouterCapability) String() string { } func (RouterCapability) Descriptor() protoreflect.EnumDescriptor { - return file_ctrl_proto_enumTypes[1].Descriptor() + return file_ctrl_proto_enumTypes[2].Descriptor() } func (RouterCapability) Type() protoreflect.EnumType { - return &file_ctrl_proto_enumTypes[1] + return &file_ctrl_proto_enumTypes[2] } func (x RouterCapability) Number() protoreflect.EnumNumber { @@ -202,7 +245,7 @@ func (x RouterCapability) Number() protoreflect.EnumNumber { // Deprecated: Use RouterCapability.Descriptor instead. func (RouterCapability) EnumDescriptor() ([]byte, []int) { - return file_ctrl_proto_rawDescGZIP(), []int{1} + return file_ctrl_proto_rawDescGZIP(), []int{2} } // SettingTypes are used with the Settings message send arbitrary settings to routers. @@ -239,11 +282,11 @@ func (x SettingTypes) String() string { } func (SettingTypes) Descriptor() protoreflect.EnumDescriptor { - return file_ctrl_proto_enumTypes[2].Descriptor() + return file_ctrl_proto_enumTypes[3].Descriptor() } func (SettingTypes) Type() protoreflect.EnumType { - return &file_ctrl_proto_enumTypes[2] + return &file_ctrl_proto_enumTypes[3] } func (x SettingTypes) Number() protoreflect.EnumNumber { @@ -252,7 +295,7 @@ func (x SettingTypes) Number() protoreflect.EnumNumber { // Deprecated: Use SettingTypes.Descriptor instead. func (SettingTypes) EnumDescriptor() ([]byte, []int) { - return file_ctrl_proto_rawDescGZIP(), []int{2} + return file_ctrl_proto_rawDescGZIP(), []int{3} } type TerminatorPrecedence int32 @@ -288,11 +331,11 @@ func (x TerminatorPrecedence) String() string { } func (TerminatorPrecedence) Descriptor() protoreflect.EnumDescriptor { - return file_ctrl_proto_enumTypes[3].Descriptor() + return file_ctrl_proto_enumTypes[4].Descriptor() } func (TerminatorPrecedence) Type() protoreflect.EnumType { - return &file_ctrl_proto_enumTypes[3] + return &file_ctrl_proto_enumTypes[4] } func (x TerminatorPrecedence) Number() protoreflect.EnumNumber { @@ -301,7 +344,7 @@ func (x TerminatorPrecedence) Number() protoreflect.EnumNumber { // Deprecated: Use TerminatorPrecedence.Descriptor instead. func (TerminatorPrecedence) EnumDescriptor() ([]byte, []int) { - return file_ctrl_proto_rawDescGZIP(), []int{3} + return file_ctrl_proto_rawDescGZIP(), []int{4} } type TerminatorInvalidReason int32 @@ -337,11 +380,11 @@ func (x TerminatorInvalidReason) String() string { } func (TerminatorInvalidReason) Descriptor() protoreflect.EnumDescriptor { - return file_ctrl_proto_enumTypes[4].Descriptor() + return file_ctrl_proto_enumTypes[5].Descriptor() } func (TerminatorInvalidReason) Type() protoreflect.EnumType { - return &file_ctrl_proto_enumTypes[4] + return &file_ctrl_proto_enumTypes[5] } func (x TerminatorInvalidReason) Number() protoreflect.EnumNumber { @@ -350,7 +393,7 @@ func (x TerminatorInvalidReason) Number() protoreflect.EnumNumber { // Deprecated: Use TerminatorInvalidReason.Descriptor instead. func (TerminatorInvalidReason) EnumDescriptor() ([]byte, []int) { - return file_ctrl_proto_rawDescGZIP(), []int{4} + return file_ctrl_proto_rawDescGZIP(), []int{5} } type FaultSubject int32 @@ -395,11 +438,11 @@ func (x FaultSubject) String() string { } func (FaultSubject) Descriptor() protoreflect.EnumDescriptor { - return file_ctrl_proto_enumTypes[5].Descriptor() + return file_ctrl_proto_enumTypes[6].Descriptor() } func (FaultSubject) Type() protoreflect.EnumType { - return &file_ctrl_proto_enumTypes[5] + return &file_ctrl_proto_enumTypes[6] } func (x FaultSubject) Number() protoreflect.EnumNumber { @@ -408,7 +451,7 @@ func (x FaultSubject) Number() protoreflect.EnumNumber { // Deprecated: Use FaultSubject.Descriptor instead. func (FaultSubject) EnumDescriptor() ([]byte, []int) { - return file_ctrl_proto_rawDescGZIP(), []int{5} + return file_ctrl_proto_rawDescGZIP(), []int{6} } type DestType int32 @@ -444,11 +487,11 @@ func (x DestType) String() string { } func (DestType) Descriptor() protoreflect.EnumDescriptor { - return file_ctrl_proto_enumTypes[6].Descriptor() + return file_ctrl_proto_enumTypes[7].Descriptor() } func (DestType) Type() protoreflect.EnumType { - return &file_ctrl_proto_enumTypes[6] + return &file_ctrl_proto_enumTypes[7] } func (x DestType) Number() protoreflect.EnumNumber { @@ -457,7 +500,7 @@ func (x DestType) Number() protoreflect.EnumNumber { // Deprecated: Use DestType.Descriptor instead. func (DestType) EnumDescriptor() ([]byte, []int) { - return file_ctrl_proto_rawDescGZIP(), []int{6} + return file_ctrl_proto_rawDescGZIP(), []int{7} } type PeerState int32 @@ -493,11 +536,11 @@ func (x PeerState) String() string { } func (PeerState) Descriptor() protoreflect.EnumDescriptor { - return file_ctrl_proto_enumTypes[7].Descriptor() + return file_ctrl_proto_enumTypes[8].Descriptor() } func (PeerState) Type() protoreflect.EnumType { - return &file_ctrl_proto_enumTypes[7] + return &file_ctrl_proto_enumTypes[8] } func (x PeerState) Number() protoreflect.EnumNumber { @@ -506,7 +549,7 @@ func (x PeerState) Number() protoreflect.EnumNumber { // Deprecated: Use PeerState.Descriptor instead. func (PeerState) EnumDescriptor() ([]byte, []int) { - return file_ctrl_proto_rawDescGZIP(), []int{7} + return file_ctrl_proto_rawDescGZIP(), []int{8} } // Settings are sent to to routers to configure arbitrary runtime settings. @@ -1475,8 +1518,9 @@ type Fault struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Subject FaultSubject `protobuf:"varint,1,opt,name=subject,proto3,enum=ziti.ctrl.pb.FaultSubject" json:"subject,omitempty"` - Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + Subject FaultSubject `protobuf:"varint,1,opt,name=subject,proto3,enum=ziti.ctrl.pb.FaultSubject" json:"subject,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + Iteration uint32 `protobuf:"varint,3,opt,name=iteration,proto3" json:"iteration,omitempty"` } func (x *Fault) Reset() { @@ -1525,6 +1569,13 @@ func (x *Fault) GetId() string { return "" } +func (x *Fault) GetIteration() uint32 { + if x != nil { + return x.Iteration + } + return 0 +} + type Context struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2259,6 +2310,7 @@ type RouterLinks_RouterLink struct { LinkProtocol string `protobuf:"bytes,3,opt,name=linkProtocol,proto3" json:"linkProtocol,omitempty"` LinkCostTags []string `protobuf:"bytes,4,rep,name=linkCostTags,proto3" json:"linkCostTags,omitempty"` DialAddress string `protobuf:"bytes,5,opt,name=dialAddress,proto3" json:"dialAddress,omitempty"` + Iteration uint32 `protobuf:"varint,6,opt,name=iteration,proto3" json:"iteration,omitempty"` } func (x *RouterLinks_RouterLink) Reset() { @@ -2328,6 +2380,13 @@ func (x *RouterLinks_RouterLink) GetDialAddress() string { return "" } +func (x *RouterLinks_RouterLink) GetIteration() uint32 { + if x != nil { + return x.Iteration + } + return 0 +} + type Route_Egress struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2663,12 +2722,12 @@ var file_ctrl_proto_rawDesc = []byte{ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, - 0x6e, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x6e, 0x73, 0x22, 0xf6, 0x01, 0x0a, 0x0b, 0x52, 0x6f, 0x75, + 0x6e, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x6e, 0x73, 0x22, 0x94, 0x02, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x05, 0x6c, - 0x69, 0x6e, 0x6b, 0x73, 0x1a, 0xaa, 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, + 0x69, 0x6e, 0x6b, 0x73, 0x1a, 0xc8, 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x52, @@ -2679,218 +2738,224 @@ var file_ctrl_proto_rawDesc = []byte{ 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x73, 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x22, 0x4d, 0x0a, 0x05, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x34, 0x0a, 0x07, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x7a, 0x69, - 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x75, 0x6c, 0x74, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x22, 0xa1, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x39, 0x0a, 0x06, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x7a, - 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4d, 0x61, 0x73, 0x6b, 0x1a, 0x39, 0x0a, 0x0b, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc4, 0x05, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, - 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x61, - 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x32, 0x0a, 0x06, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, - 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x45, 0x67, 0x72, 0x65, - 0x73, 0x73, 0x52, 0x06, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x6f, - 0x72, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x7a, - 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, - 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x31, - 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x7a, - 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, - 0x73, 0x1a, 0xe1, 0x01, 0x0a, 0x06, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, - 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, - 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x08, 0x70, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, - 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, - 0x70, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x50, 0x65, 0x65, 0x72, - 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x7b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x30, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x16, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, - 0x2e, 0x44, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x64, 0x73, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x39, 0x0a, 0x07, 0x55, - 0x6e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, - 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x69, 0x72, 0x63, 0x75, - 0x69, 0x74, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x03, 0x6e, 0x6f, 0x77, 0x22, 0x3a, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x12, 0x16, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, - 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x38, 0x0a, 0x0c, - 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4e, 0x0a, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, - 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x73, - 0x74, 0x54, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x73, - 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x22, 0x0a, - 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x22, 0x41, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x34, - 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x73, 0x22, 0x65, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x74, - 0x72, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, - 0x1a, 0x0a, 0x08, 0x69, 0x73, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x69, 0x73, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0xa0, 0x01, 0x0a, 0x0f, - 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, - 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x7a, 0x69, - 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x4b, - 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, - 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x0e, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x42, 0x0a, - 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, - 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x79, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x2a, 0xca, 0x06, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x65, 0x72, 0x6f, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x12, 0x43, - 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x10, 0xe8, 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x44, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, - 0x10, 0xea, 0x07, 0x12, 0x16, 0x0a, 0x11, 0x4c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xeb, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x46, - 0x61, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xec, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xed, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x55, - 0x6e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xee, 0x07, 0x12, 0x10, 0x0a, - 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0xef, 0x07, 0x12, - 0x20, 0x0a, 0x1b, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x54, 0x72, 0x61, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf0, - 0x07, 0x12, 0x13, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x10, 0xf2, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf3, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf4, 0x07, 0x12, 0x17, 0x0a, 0x12, 0x49, 0x6e, - 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x10, 0xf5, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf6, 0x07, 0x12, 0x23, 0x0a, - 0x1e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, - 0xf9, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, + 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0x6b, 0x0a, 0x05, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x34, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, + 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa1, 0x01, 0x0a, + 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x39, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4d, 0x61, + 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x4d, 0x61, 0x73, 0x6b, 0x1a, 0x39, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0xc4, 0x05, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x69, + 0x72, 0x63, 0x75, 0x69, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, + 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x74, 0x74, 0x65, + 0x6d, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, + 0x70, 0x74, 0x12, 0x32, 0x0a, 0x06, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, + 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x06, + 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, + 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x46, 0x6f, + 0x72, 0x77, 0x61, 0x72, 0x64, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x73, 0x12, + 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x61, + 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x54, 0x61, + 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0xe1, 0x01, + 0x0a, 0x06, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x69, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x69, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, + 0x0a, 0x08, 0x70, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x28, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x50, 0x65, 0x65, + 0x72, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, + 0x44, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x1a, 0x7b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x1e, 0x0a, 0x0a, + 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, + 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x30, 0x0a, 0x07, + 0x64, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, + 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x73, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x64, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x1a, 0x37, + 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x39, 0x0a, 0x07, 0x55, 0x6e, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x49, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x49, 0x64, + 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6e, + 0x6f, 0x77, 0x22, 0x3a, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, + 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xc1, + 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, + 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x38, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x4e, 0x0a, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, + 0x0a, 0x0c, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, + 0x74, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, + 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x73, 0x74, 0x54, 0x61, 0x67, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x73, 0x74, 0x54, 0x61, 0x67, + 0x73, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x22, 0x41, 0x0a, + 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x34, 0x0a, 0x09, 0x6c, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, + 0x22, 0x65, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x74, 0x72, 0x6c, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x69, + 0x73, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, + 0x73, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0xa0, 0x01, 0x0a, 0x0f, 0x50, 0x65, 0x65, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, + 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, + 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, + 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x4b, 0x0a, 0x10, 0x50, 0x65, + 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x37, + 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x07, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x42, 0x0a, 0x0c, 0x63, 0x61, 0x70, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, + 0x1e, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x63, 0x74, 0x72, 0x6c, 0x2e, 0x70, 0x62, 0x2e, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, + 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2a, 0x83, 0x06, + 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, + 0x04, 0x5a, 0x65, 0x72, 0x6f, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x12, 0x43, 0x69, 0x72, 0x63, 0x75, + 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xe8, 0x07, + 0x12, 0x0d, 0x0a, 0x08, 0x44, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x10, 0xea, 0x07, 0x12, + 0x16, 0x0a, 0x11, 0x4c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, + 0x54, 0x79, 0x70, 0x65, 0x10, 0xeb, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x61, 0x75, 0x6c, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x10, 0xec, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x10, 0xed, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x55, 0x6e, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xee, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0xef, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x54, + 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf0, 0x07, 0x12, 0x13, 0x0a, + 0x0e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, + 0xf2, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x10, 0xfa, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x54, 0x79, 0x70, 0x65, 0x10, 0xfc, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x43, 0x69, 0x72, 0x63, 0x75, - 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x10, 0x8a, 0x08, 0x12, 0x14, 0x0a, 0x0f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, - 0x69, 0x6e, 0x6b, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0x8b, 0x08, 0x12, 0x15, 0x0a, 0x10, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x10, - 0x8c, 0x08, 0x12, 0x1c, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x74, 0x72, 0x6c, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0x8d, 0x08, - 0x12, 0x21, 0x0a, 0x1c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x10, 0x8e, 0x08, 0x12, 0x1d, 0x0a, 0x18, 0x51, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x52, 0x6f, + 0x65, 0x10, 0xf3, 0x07, 0x12, 0x20, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x10, 0xf4, 0x07, 0x12, 0x17, 0x0a, 0x12, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf5, 0x07, 0x12, + 0x18, 0x0a, 0x13, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf6, 0x07, 0x12, 0x23, 0x0a, 0x1e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf9, 0x07, 0x12, 0x20, + 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xfa, 0x07, + 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65, + 0x10, 0xfc, 0x07, 0x12, 0x1c, 0x0a, 0x17, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x10, 0x8a, + 0x08, 0x12, 0x14, 0x0a, 0x0f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x73, + 0x54, 0x79, 0x70, 0x65, 0x10, 0x8b, 0x08, 0x12, 0x15, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x10, 0x8c, 0x08, 0x12, 0x1c, + 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x74, 0x72, 0x6c, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0x8d, 0x08, 0x12, 0x21, 0x0a, 0x1c, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0x8e, 0x08, 0x12, + 0x1d, 0x0a, 0x18, 0x51, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0x8f, 0x08, 0x12, 0x1f, + 0x0a, 0x1a, 0x44, 0x65, 0x71, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0x90, 0x08, 0x12, + 0x25, 0x0a, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, + 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x56, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x10, 0x91, 0x08, 0x12, 0x26, 0x0a, 0x21, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x56, 0x32, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0x92, 0x08, 0x12, 0x22, + 0x0a, 0x1d, 0x44, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, - 0x8f, 0x08, 0x12, 0x1f, 0x0a, 0x1a, 0x44, 0x65, 0x71, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x10, 0x90, 0x08, 0x12, 0x25, 0x0a, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x56, 0x32, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0x91, 0x08, 0x12, 0x26, 0x0a, 0x21, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x56, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, - 0x92, 0x08, 0x12, 0x22, 0x0a, 0x1d, 0x44, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x10, 0x93, 0x08, 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x10, 0x9a, 0x08, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x10, 0x0b, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x0c, 0x2a, 0x3a, - 0x0a, 0x10, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x5a, 0x65, 0x72, 0x6f, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x2a, 0x35, 0x0a, 0x0c, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x6e, - 0x75, 0x73, 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x12, 0x0a, - 0x0e, 0x4e, 0x65, 0x77, 0x43, 0x74, 0x72, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, - 0x01, 0x2a, 0x3d, 0x0a, 0x14, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x50, - 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x64, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x02, - 0x2a, 0x52, 0x0a, 0x17, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x0e, 0x55, - 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, - 0x15, 0x0a, 0x11, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x74, 0x6f, 0x72, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x61, 0x64, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x10, 0x02, 0x2a, 0x83, 0x01, 0x0a, 0x0c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x46, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x45, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x69, 0x6e, 0x6b, - 0x46, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x6e, 0x6b, - 0x6e, 0x6f, 0x77, 0x6e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x46, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x4c, 0x69, 0x6e, 0x6b, 0x44, - 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x05, 0x2a, 0x28, 0x0a, 0x08, 0x44, 0x65, - 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x10, - 0x00, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x6e, 0x64, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x69, - 0x6e, 0x6b, 0x10, 0x02, 0x2a, 0x34, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x10, 0x00, 0x12, 0x0d, - 0x0a, 0x09, 0x55, 0x6e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x10, 0x01, 0x12, 0x0b, 0x0a, - 0x07, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x10, 0x02, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, - 0x69, 0x2f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x2f, 0x63, 0x74, 0x72, 0x6c, - 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x93, 0x08, 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x10, 0x9a, 0x08, 0x2a, 0x67, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x6f, 0x6e, 0x65, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, + 0x72, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x10, 0x0b, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x0c, 0x2a, 0x3a, 0x0a, 0x10, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5a, 0x65, + 0x72, 0x6f, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x2a, 0x35, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x6e, 0x75, 0x73, + 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4e, + 0x65, 0x77, 0x43, 0x74, 0x72, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x01, 0x2a, + 0x3d, 0x0a, 0x14, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x65, + 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x02, 0x2a, 0x52, + 0x0a, 0x17, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x6e, 0x6b, + 0x6e, 0x6f, 0x77, 0x6e, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x15, 0x0a, + 0x11, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, + 0x6f, 0x72, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x10, 0x02, 0x2a, 0x83, 0x01, 0x0a, 0x0c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x46, 0x61, + 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x46, + 0x61, 0x75, 0x6c, 0x74, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x69, 0x6e, 0x6b, 0x46, 0x61, + 0x75, 0x6c, 0x74, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, + 0x46, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x46, 0x61, + 0x75, 0x6c, 0x74, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x4c, 0x69, 0x6e, 0x6b, 0x44, 0x75, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x05, 0x2a, 0x28, 0x0a, 0x08, 0x44, 0x65, 0x73, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x10, 0x00, 0x12, + 0x07, 0x0a, 0x03, 0x45, 0x6e, 0x64, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x6b, + 0x10, 0x02, 0x2a, 0x34, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x0b, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, + 0x55, 0x6e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x10, 0x02, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2f, + 0x66, 0x61, 0x62, 0x72, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x2f, 0x63, 0x74, 0x72, 0x6c, 0x5f, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2905,87 +2970,88 @@ func file_ctrl_proto_rawDescGZIP() []byte { return file_ctrl_proto_rawDescData } -var file_ctrl_proto_enumTypes = make([]protoimpl.EnumInfo, 8) +var file_ctrl_proto_enumTypes = make([]protoimpl.EnumInfo, 9) var file_ctrl_proto_msgTypes = make([]protoimpl.MessageInfo, 41) var file_ctrl_proto_goTypes = []interface{}{ (ContentType)(0), // 0: ziti.ctrl.pb.ContentType - (RouterCapability)(0), // 1: ziti.ctrl.pb.RouterCapability - (SettingTypes)(0), // 2: ziti.ctrl.pb.SettingTypes - (TerminatorPrecedence)(0), // 3: ziti.ctrl.pb.TerminatorPrecedence - (TerminatorInvalidReason)(0), // 4: ziti.ctrl.pb.TerminatorInvalidReason - (FaultSubject)(0), // 5: ziti.ctrl.pb.FaultSubject - (DestType)(0), // 6: ziti.ctrl.pb.DestType - (PeerState)(0), // 7: ziti.ctrl.pb.PeerState - (*Settings)(nil), // 8: ziti.ctrl.pb.Settings - (*CircuitRequest)(nil), // 9: ziti.ctrl.pb.CircuitRequest - (*CircuitConfirmation)(nil), // 10: ziti.ctrl.pb.CircuitConfirmation - (*CreateTerminatorRequest)(nil), // 11: ziti.ctrl.pb.CreateTerminatorRequest - (*RemoveTerminatorRequest)(nil), // 12: ziti.ctrl.pb.RemoveTerminatorRequest - (*RemoveTerminatorsRequest)(nil), // 13: ziti.ctrl.pb.RemoveTerminatorsRequest - (*Terminator)(nil), // 14: ziti.ctrl.pb.Terminator - (*ValidateTerminatorsRequest)(nil), // 15: ziti.ctrl.pb.ValidateTerminatorsRequest - (*ValidateTerminatorsV2Request)(nil), // 16: ziti.ctrl.pb.ValidateTerminatorsV2Request - (*RouterTerminatorState)(nil), // 17: ziti.ctrl.pb.RouterTerminatorState - (*ValidateTerminatorsV2Response)(nil), // 18: ziti.ctrl.pb.ValidateTerminatorsV2Response - (*UpdateTerminatorRequest)(nil), // 19: ziti.ctrl.pb.UpdateTerminatorRequest - (*Dial)(nil), // 20: ziti.ctrl.pb.Dial - (*LinkConn)(nil), // 21: ziti.ctrl.pb.LinkConn - (*LinkConnected)(nil), // 22: ziti.ctrl.pb.LinkConnected - (*RouterLinks)(nil), // 23: ziti.ctrl.pb.RouterLinks - (*Fault)(nil), // 24: ziti.ctrl.pb.Fault - (*Context)(nil), // 25: ziti.ctrl.pb.Context - (*Route)(nil), // 26: ziti.ctrl.pb.Route - (*Unroute)(nil), // 27: ziti.ctrl.pb.Unroute - (*InspectRequest)(nil), // 28: ziti.ctrl.pb.InspectRequest - (*InspectResponse)(nil), // 29: ziti.ctrl.pb.InspectResponse - (*VerifyRouter)(nil), // 30: ziti.ctrl.pb.VerifyRouter - (*Listener)(nil), // 31: ziti.ctrl.pb.Listener - (*Listeners)(nil), // 32: ziti.ctrl.pb.Listeners - (*UpdateCtrlAddresses)(nil), // 33: ziti.ctrl.pb.UpdateCtrlAddresses - (*PeerStateChange)(nil), // 34: ziti.ctrl.pb.PeerStateChange - (*PeerStateChanges)(nil), // 35: ziti.ctrl.pb.PeerStateChanges - (*RouterMetadata)(nil), // 36: ziti.ctrl.pb.RouterMetadata - nil, // 37: ziti.ctrl.pb.Settings.DataEntry - nil, // 38: ziti.ctrl.pb.CircuitRequest.PeerDataEntry - nil, // 39: ziti.ctrl.pb.CircuitConfirmation.IdleTimesEntry - nil, // 40: ziti.ctrl.pb.CreateTerminatorRequest.PeerDataEntry - nil, // 41: ziti.ctrl.pb.ValidateTerminatorsV2Response.StatesEntry - (*RouterLinks_RouterLink)(nil), // 42: ziti.ctrl.pb.RouterLinks.RouterLink - nil, // 43: ziti.ctrl.pb.Context.FieldsEntry - (*Route_Egress)(nil), // 44: ziti.ctrl.pb.Route.Egress - (*Route_Forward)(nil), // 45: ziti.ctrl.pb.Route.Forward - nil, // 46: ziti.ctrl.pb.Route.TagsEntry - nil, // 47: ziti.ctrl.pb.Route.Egress.PeerDataEntry - (*InspectResponse_InspectValue)(nil), // 48: ziti.ctrl.pb.InspectResponse.InspectValue + (ControlHeaders)(0), // 1: ziti.ctrl.pb.ControlHeaders + (RouterCapability)(0), // 2: ziti.ctrl.pb.RouterCapability + (SettingTypes)(0), // 3: ziti.ctrl.pb.SettingTypes + (TerminatorPrecedence)(0), // 4: ziti.ctrl.pb.TerminatorPrecedence + (TerminatorInvalidReason)(0), // 5: ziti.ctrl.pb.TerminatorInvalidReason + (FaultSubject)(0), // 6: ziti.ctrl.pb.FaultSubject + (DestType)(0), // 7: ziti.ctrl.pb.DestType + (PeerState)(0), // 8: ziti.ctrl.pb.PeerState + (*Settings)(nil), // 9: ziti.ctrl.pb.Settings + (*CircuitRequest)(nil), // 10: ziti.ctrl.pb.CircuitRequest + (*CircuitConfirmation)(nil), // 11: ziti.ctrl.pb.CircuitConfirmation + (*CreateTerminatorRequest)(nil), // 12: ziti.ctrl.pb.CreateTerminatorRequest + (*RemoveTerminatorRequest)(nil), // 13: ziti.ctrl.pb.RemoveTerminatorRequest + (*RemoveTerminatorsRequest)(nil), // 14: ziti.ctrl.pb.RemoveTerminatorsRequest + (*Terminator)(nil), // 15: ziti.ctrl.pb.Terminator + (*ValidateTerminatorsRequest)(nil), // 16: ziti.ctrl.pb.ValidateTerminatorsRequest + (*ValidateTerminatorsV2Request)(nil), // 17: ziti.ctrl.pb.ValidateTerminatorsV2Request + (*RouterTerminatorState)(nil), // 18: ziti.ctrl.pb.RouterTerminatorState + (*ValidateTerminatorsV2Response)(nil), // 19: ziti.ctrl.pb.ValidateTerminatorsV2Response + (*UpdateTerminatorRequest)(nil), // 20: ziti.ctrl.pb.UpdateTerminatorRequest + (*Dial)(nil), // 21: ziti.ctrl.pb.Dial + (*LinkConn)(nil), // 22: ziti.ctrl.pb.LinkConn + (*LinkConnected)(nil), // 23: ziti.ctrl.pb.LinkConnected + (*RouterLinks)(nil), // 24: ziti.ctrl.pb.RouterLinks + (*Fault)(nil), // 25: ziti.ctrl.pb.Fault + (*Context)(nil), // 26: ziti.ctrl.pb.Context + (*Route)(nil), // 27: ziti.ctrl.pb.Route + (*Unroute)(nil), // 28: ziti.ctrl.pb.Unroute + (*InspectRequest)(nil), // 29: ziti.ctrl.pb.InspectRequest + (*InspectResponse)(nil), // 30: ziti.ctrl.pb.InspectResponse + (*VerifyRouter)(nil), // 31: ziti.ctrl.pb.VerifyRouter + (*Listener)(nil), // 32: ziti.ctrl.pb.Listener + (*Listeners)(nil), // 33: ziti.ctrl.pb.Listeners + (*UpdateCtrlAddresses)(nil), // 34: ziti.ctrl.pb.UpdateCtrlAddresses + (*PeerStateChange)(nil), // 35: ziti.ctrl.pb.PeerStateChange + (*PeerStateChanges)(nil), // 36: ziti.ctrl.pb.PeerStateChanges + (*RouterMetadata)(nil), // 37: ziti.ctrl.pb.RouterMetadata + nil, // 38: ziti.ctrl.pb.Settings.DataEntry + nil, // 39: ziti.ctrl.pb.CircuitRequest.PeerDataEntry + nil, // 40: ziti.ctrl.pb.CircuitConfirmation.IdleTimesEntry + nil, // 41: ziti.ctrl.pb.CreateTerminatorRequest.PeerDataEntry + nil, // 42: ziti.ctrl.pb.ValidateTerminatorsV2Response.StatesEntry + (*RouterLinks_RouterLink)(nil), // 43: ziti.ctrl.pb.RouterLinks.RouterLink + nil, // 44: ziti.ctrl.pb.Context.FieldsEntry + (*Route_Egress)(nil), // 45: ziti.ctrl.pb.Route.Egress + (*Route_Forward)(nil), // 46: ziti.ctrl.pb.Route.Forward + nil, // 47: ziti.ctrl.pb.Route.TagsEntry + nil, // 48: ziti.ctrl.pb.Route.Egress.PeerDataEntry + (*InspectResponse_InspectValue)(nil), // 49: ziti.ctrl.pb.InspectResponse.InspectValue } var file_ctrl_proto_depIdxs = []int32{ - 37, // 0: ziti.ctrl.pb.Settings.data:type_name -> ziti.ctrl.pb.Settings.DataEntry - 38, // 1: ziti.ctrl.pb.CircuitRequest.peerData:type_name -> ziti.ctrl.pb.CircuitRequest.PeerDataEntry - 39, // 2: ziti.ctrl.pb.CircuitConfirmation.idleTimes:type_name -> ziti.ctrl.pb.CircuitConfirmation.IdleTimesEntry - 40, // 3: ziti.ctrl.pb.CreateTerminatorRequest.peerData:type_name -> ziti.ctrl.pb.CreateTerminatorRequest.PeerDataEntry - 3, // 4: ziti.ctrl.pb.CreateTerminatorRequest.precedence:type_name -> ziti.ctrl.pb.TerminatorPrecedence - 14, // 5: ziti.ctrl.pb.ValidateTerminatorsRequest.terminators:type_name -> ziti.ctrl.pb.Terminator - 14, // 6: ziti.ctrl.pb.ValidateTerminatorsV2Request.terminators:type_name -> ziti.ctrl.pb.Terminator - 4, // 7: ziti.ctrl.pb.RouterTerminatorState.reason:type_name -> ziti.ctrl.pb.TerminatorInvalidReason - 41, // 8: ziti.ctrl.pb.ValidateTerminatorsV2Response.states:type_name -> ziti.ctrl.pb.ValidateTerminatorsV2Response.StatesEntry - 3, // 9: ziti.ctrl.pb.UpdateTerminatorRequest.precedence:type_name -> ziti.ctrl.pb.TerminatorPrecedence - 21, // 10: ziti.ctrl.pb.LinkConnected.conns:type_name -> ziti.ctrl.pb.LinkConn - 42, // 11: ziti.ctrl.pb.RouterLinks.links:type_name -> ziti.ctrl.pb.RouterLinks.RouterLink - 5, // 12: ziti.ctrl.pb.Fault.subject:type_name -> ziti.ctrl.pb.FaultSubject - 43, // 13: ziti.ctrl.pb.Context.fields:type_name -> ziti.ctrl.pb.Context.FieldsEntry - 44, // 14: ziti.ctrl.pb.Route.egress:type_name -> ziti.ctrl.pb.Route.Egress - 45, // 15: ziti.ctrl.pb.Route.forwards:type_name -> ziti.ctrl.pb.Route.Forward - 25, // 16: ziti.ctrl.pb.Route.context:type_name -> ziti.ctrl.pb.Context - 46, // 17: ziti.ctrl.pb.Route.tags:type_name -> ziti.ctrl.pb.Route.TagsEntry - 48, // 18: ziti.ctrl.pb.InspectResponse.values:type_name -> ziti.ctrl.pb.InspectResponse.InspectValue - 31, // 19: ziti.ctrl.pb.Listeners.listeners:type_name -> ziti.ctrl.pb.Listener - 7, // 20: ziti.ctrl.pb.PeerStateChange.state:type_name -> ziti.ctrl.pb.PeerState - 31, // 21: ziti.ctrl.pb.PeerStateChange.listeners:type_name -> ziti.ctrl.pb.Listener - 34, // 22: ziti.ctrl.pb.PeerStateChanges.changes:type_name -> ziti.ctrl.pb.PeerStateChange - 1, // 23: ziti.ctrl.pb.RouterMetadata.capabilities:type_name -> ziti.ctrl.pb.RouterCapability - 17, // 24: ziti.ctrl.pb.ValidateTerminatorsV2Response.StatesEntry.value:type_name -> ziti.ctrl.pb.RouterTerminatorState - 47, // 25: ziti.ctrl.pb.Route.Egress.peerData:type_name -> ziti.ctrl.pb.Route.Egress.PeerDataEntry - 6, // 26: ziti.ctrl.pb.Route.Forward.dstType:type_name -> ziti.ctrl.pb.DestType + 38, // 0: ziti.ctrl.pb.Settings.data:type_name -> ziti.ctrl.pb.Settings.DataEntry + 39, // 1: ziti.ctrl.pb.CircuitRequest.peerData:type_name -> ziti.ctrl.pb.CircuitRequest.PeerDataEntry + 40, // 2: ziti.ctrl.pb.CircuitConfirmation.idleTimes:type_name -> ziti.ctrl.pb.CircuitConfirmation.IdleTimesEntry + 41, // 3: ziti.ctrl.pb.CreateTerminatorRequest.peerData:type_name -> ziti.ctrl.pb.CreateTerminatorRequest.PeerDataEntry + 4, // 4: ziti.ctrl.pb.CreateTerminatorRequest.precedence:type_name -> ziti.ctrl.pb.TerminatorPrecedence + 15, // 5: ziti.ctrl.pb.ValidateTerminatorsRequest.terminators:type_name -> ziti.ctrl.pb.Terminator + 15, // 6: ziti.ctrl.pb.ValidateTerminatorsV2Request.terminators:type_name -> ziti.ctrl.pb.Terminator + 5, // 7: ziti.ctrl.pb.RouterTerminatorState.reason:type_name -> ziti.ctrl.pb.TerminatorInvalidReason + 42, // 8: ziti.ctrl.pb.ValidateTerminatorsV2Response.states:type_name -> ziti.ctrl.pb.ValidateTerminatorsV2Response.StatesEntry + 4, // 9: ziti.ctrl.pb.UpdateTerminatorRequest.precedence:type_name -> ziti.ctrl.pb.TerminatorPrecedence + 22, // 10: ziti.ctrl.pb.LinkConnected.conns:type_name -> ziti.ctrl.pb.LinkConn + 43, // 11: ziti.ctrl.pb.RouterLinks.links:type_name -> ziti.ctrl.pb.RouterLinks.RouterLink + 6, // 12: ziti.ctrl.pb.Fault.subject:type_name -> ziti.ctrl.pb.FaultSubject + 44, // 13: ziti.ctrl.pb.Context.fields:type_name -> ziti.ctrl.pb.Context.FieldsEntry + 45, // 14: ziti.ctrl.pb.Route.egress:type_name -> ziti.ctrl.pb.Route.Egress + 46, // 15: ziti.ctrl.pb.Route.forwards:type_name -> ziti.ctrl.pb.Route.Forward + 26, // 16: ziti.ctrl.pb.Route.context:type_name -> ziti.ctrl.pb.Context + 47, // 17: ziti.ctrl.pb.Route.tags:type_name -> ziti.ctrl.pb.Route.TagsEntry + 49, // 18: ziti.ctrl.pb.InspectResponse.values:type_name -> ziti.ctrl.pb.InspectResponse.InspectValue + 32, // 19: ziti.ctrl.pb.Listeners.listeners:type_name -> ziti.ctrl.pb.Listener + 8, // 20: ziti.ctrl.pb.PeerStateChange.state:type_name -> ziti.ctrl.pb.PeerState + 32, // 21: ziti.ctrl.pb.PeerStateChange.listeners:type_name -> ziti.ctrl.pb.Listener + 35, // 22: ziti.ctrl.pb.PeerStateChanges.changes:type_name -> ziti.ctrl.pb.PeerStateChange + 2, // 23: ziti.ctrl.pb.RouterMetadata.capabilities:type_name -> ziti.ctrl.pb.RouterCapability + 18, // 24: ziti.ctrl.pb.ValidateTerminatorsV2Response.StatesEntry.value:type_name -> ziti.ctrl.pb.RouterTerminatorState + 48, // 25: ziti.ctrl.pb.Route.Egress.peerData:type_name -> ziti.ctrl.pb.Route.Egress.PeerDataEntry + 7, // 26: ziti.ctrl.pb.Route.Forward.dstType:type_name -> ziti.ctrl.pb.DestType 27, // [27:27] is the sub-list for method output_type 27, // [27:27] is the sub-list for method input_type 27, // [27:27] is the sub-list for extension type_name @@ -3401,7 +3467,7 @@ func file_ctrl_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ctrl_proto_rawDesc, - NumEnums: 8, + NumEnums: 9, NumMessages: 41, NumExtensions: 0, NumServices: 0, diff --git a/common/pb/ctrl_pb/ctrl.proto b/common/pb/ctrl_pb/ctrl.proto index f0bea8548..3d1d1d954 100644 --- a/common/pb/ctrl_pb/ctrl.proto +++ b/common/pb/ctrl_pb/ctrl.proto @@ -41,7 +41,10 @@ enum ContentType { DecommissionRouterRequestType = 1043; PeerStateChangeRequestType = 1050; +} +enum ControlHeaders { + NoneHeader = 0; ListenersHeader = 10; RouterMetadataHeader = 11; CapabilitiesHeader = 12; @@ -167,6 +170,7 @@ message RouterLinks { string linkProtocol = 3; repeated string linkCostTags = 4; string dialAddress = 5; + uint32 iteration = 6; } repeated RouterLink links = 1; @@ -184,6 +188,7 @@ enum FaultSubject { message Fault { FaultSubject subject = 1; string id = 2; + uint32 iteration = 3; } message Context { diff --git a/common/pb/ctrl_pb/decoder.go b/common/pb/ctrl_pb/decoder.go index 680501c85..d241f1101 100644 --- a/common/pb/ctrl_pb/decoder.go +++ b/common/pb/ctrl_pb/decoder.go @@ -20,8 +20,8 @@ import ( "fmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" - "github.com/openziti/ziti/common/ctrl_msg" "github.com/openziti/metrics/metrics_pb" + "github.com/openziti/ziti/common/ctrl_msg" "google.golang.org/protobuf/proto" "strconv" "strings" @@ -226,6 +226,7 @@ func (d Decoder) Decode(msg *channel.Message) ([]byte, bool) { meta := channel.NewTraceMessageDecode(DECODER, "Fault") meta["subject"] = fault.Subject.String() meta["id"] = fault.Id + meta["iteration"] = fault.Iteration data, err := meta.MarshalTraceMessageDecode() if err != nil { diff --git a/common/pb/mgmt_pb/impl.go b/common/pb/mgmt_pb/impl.go index 78756b4b8..2f6e08885 100644 --- a/common/pb/mgmt_pb/impl.go +++ b/common/pb/mgmt_pb/impl.go @@ -23,3 +23,15 @@ func (request *ValidateTerminatorsResponse) GetContentType() int32 { func (request *TerminatorDetail) GetContentType() int32 { return int32(ContentType_ValidateTerminatorResultType) } + +func (request *ValidateRouterLinksRequest) GetContentType() int32 { + return int32(ContentType_ValidateRouterLinksRequestType) +} + +func (request *ValidateRouterLinksResponse) GetContentType() int32 { + return int32(ContentType_ValidateRouterLinksResponseType) +} + +func (request *RouterLinkDetails) GetContentType() int32 { + return int32(ContentType_ValidateRouterLinksResultType) +} diff --git a/common/pb/mgmt_pb/mgmt.pb.go b/common/pb/mgmt_pb/mgmt.pb.go index f3711167d..2af6cd8ad 100644 --- a/common/pb/mgmt_pb/mgmt.pb.go +++ b/common/pb/mgmt_pb/mgmt.pb.go @@ -56,9 +56,12 @@ const ( ContentType_RaftTransferLeadershipRequestType ContentType = 10084 ContentType_RaftInitFromDb ContentType = 10085 // Validate - ContentType_ValidateTerminatorsRequestType ContentType = 10100 - ContentType_ValidateTerminatorResponseType ContentType = 10101 - ContentType_ValidateTerminatorResultType ContentType = 10102 + ContentType_ValidateTerminatorsRequestType ContentType = 10100 + ContentType_ValidateTerminatorResponseType ContentType = 10101 + ContentType_ValidateTerminatorResultType ContentType = 10102 + ContentType_ValidateRouterLinksRequestType ContentType = 10103 + ContentType_ValidateRouterLinksResponseType ContentType = 10104 + ContentType_ValidateRouterLinksResultType ContentType = 10105 ) // Enum value maps for ContentType. @@ -92,6 +95,9 @@ var ( 10100: "ValidateTerminatorsRequestType", 10101: "ValidateTerminatorResponseType", 10102: "ValidateTerminatorResultType", + 10103: "ValidateRouterLinksRequestType", + 10104: "ValidateRouterLinksResponseType", + 10105: "ValidateRouterLinksResultType", } ContentType_value = map[string]int32{ "Zero": 0, @@ -122,6 +128,9 @@ var ( "ValidateTerminatorsRequestType": 10100, "ValidateTerminatorResponseType": 10101, "ValidateTerminatorResultType": 10102, + "ValidateRouterLinksRequestType": 10103, + "ValidateRouterLinksResponseType": 10104, + "ValidateRouterLinksResultType": 10105, } ) @@ -360,6 +369,58 @@ func (TerminatorState) EnumDescriptor() ([]byte, []int) { return file_mgmt_proto_rawDescGZIP(), []int{4} } +type LinkState int32 + +const ( + LinkState_LinkUnknown LinkState = 0 + LinkState_LinkEstablished LinkState = 1 + LinkState_LinkPending LinkState = 2 + LinkState_LinkDialing LinkState = 3 +) + +// Enum value maps for LinkState. +var ( + LinkState_name = map[int32]string{ + 0: "LinkUnknown", + 1: "LinkEstablished", + 2: "LinkPending", + 3: "LinkDialing", + } + LinkState_value = map[string]int32{ + "LinkUnknown": 0, + "LinkEstablished": 1, + "LinkPending": 2, + "LinkDialing": 3, + } +) + +func (x LinkState) Enum() *LinkState { + p := new(LinkState) + *p = x + return p +} + +func (x LinkState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (LinkState) Descriptor() protoreflect.EnumDescriptor { + return file_mgmt_proto_enumTypes[5].Descriptor() +} + +func (LinkState) Type() protoreflect.EnumType { + return &file_mgmt_proto_enumTypes[5] +} + +func (x LinkState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use LinkState.Descriptor instead. +func (LinkState) EnumDescriptor() ([]byte, []int) { + return file_mgmt_proto_rawDescGZIP(), []int{5} +} + type StreamMetricsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1292,6 +1353,290 @@ func (x *TerminatorDetail) GetDetail() string { return "" } +type ValidateRouterLinksRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filter string `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` +} + +func (x *ValidateRouterLinksRequest) Reset() { + *x = ValidateRouterLinksRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ValidateRouterLinksRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ValidateRouterLinksRequest) ProtoMessage() {} + +func (x *ValidateRouterLinksRequest) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ValidateRouterLinksRequest.ProtoReflect.Descriptor instead. +func (*ValidateRouterLinksRequest) Descriptor() ([]byte, []int) { + return file_mgmt_proto_rawDescGZIP(), []int{13} +} + +func (x *ValidateRouterLinksRequest) GetFilter() string { + if x != nil { + return x.Filter + } + return "" +} + +type ValidateRouterLinksResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + RouterCount uint64 `protobuf:"varint,3,opt,name=routerCount,proto3" json:"routerCount,omitempty"` +} + +func (x *ValidateRouterLinksResponse) Reset() { + *x = ValidateRouterLinksResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ValidateRouterLinksResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ValidateRouterLinksResponse) ProtoMessage() {} + +func (x *ValidateRouterLinksResponse) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ValidateRouterLinksResponse.ProtoReflect.Descriptor instead. +func (*ValidateRouterLinksResponse) Descriptor() ([]byte, []int) { + return file_mgmt_proto_rawDescGZIP(), []int{14} +} + +func (x *ValidateRouterLinksResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *ValidateRouterLinksResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *ValidateRouterLinksResponse) GetRouterCount() uint64 { + if x != nil { + return x.RouterCount + } + return 0 +} + +type RouterLinkDetails struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RouterId string `protobuf:"bytes,1,opt,name=routerId,proto3" json:"routerId,omitempty"` + RouterName string `protobuf:"bytes,2,opt,name=routerName,proto3" json:"routerName,omitempty"` + ValidateSuccess bool `protobuf:"varint,3,opt,name=validateSuccess,proto3" json:"validateSuccess,omitempty"` + Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` + LinkDetails []*RouterLinkDetail `protobuf:"bytes,5,rep,name=linkDetails,proto3" json:"linkDetails,omitempty"` +} + +func (x *RouterLinkDetails) Reset() { + *x = RouterLinkDetails{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouterLinkDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouterLinkDetails) ProtoMessage() {} + +func (x *RouterLinkDetails) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RouterLinkDetails.ProtoReflect.Descriptor instead. +func (*RouterLinkDetails) Descriptor() ([]byte, []int) { + return file_mgmt_proto_rawDescGZIP(), []int{15} +} + +func (x *RouterLinkDetails) GetRouterId() string { + if x != nil { + return x.RouterId + } + return "" +} + +func (x *RouterLinkDetails) GetRouterName() string { + if x != nil { + return x.RouterName + } + return "" +} + +func (x *RouterLinkDetails) GetValidateSuccess() bool { + if x != nil { + return x.ValidateSuccess + } + return false +} + +func (x *RouterLinkDetails) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *RouterLinkDetails) GetLinkDetails() []*RouterLinkDetail { + if x != nil { + return x.LinkDetails + } + return nil +} + +type RouterLinkDetail struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LinkId string `protobuf:"bytes,1,opt,name=linkId,proto3" json:"linkId,omitempty"` + CtrlState LinkState `protobuf:"varint,2,opt,name=ctrlState,proto3,enum=ziti.mgmt_pb.LinkState" json:"ctrlState,omitempty"` + RouterState LinkState `protobuf:"varint,3,opt,name=routerState,proto3,enum=ziti.mgmt_pb.LinkState" json:"routerState,omitempty"` + DestConnected bool `protobuf:"varint,4,opt,name=destConnected,proto3" json:"destConnected,omitempty"` + IsValid bool `protobuf:"varint,5,opt,name=isValid,proto3" json:"isValid,omitempty"` + DestRouterId string `protobuf:"bytes,6,opt,name=destRouterId,proto3" json:"destRouterId,omitempty"` + Dialed bool `protobuf:"varint,7,opt,name=dialed,proto3" json:"dialed,omitempty"` +} + +func (x *RouterLinkDetail) Reset() { + *x = RouterLinkDetail{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouterLinkDetail) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouterLinkDetail) ProtoMessage() {} + +func (x *RouterLinkDetail) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RouterLinkDetail.ProtoReflect.Descriptor instead. +func (*RouterLinkDetail) Descriptor() ([]byte, []int) { + return file_mgmt_proto_rawDescGZIP(), []int{16} +} + +func (x *RouterLinkDetail) GetLinkId() string { + if x != nil { + return x.LinkId + } + return "" +} + +func (x *RouterLinkDetail) GetCtrlState() LinkState { + if x != nil { + return x.CtrlState + } + return LinkState_LinkUnknown +} + +func (x *RouterLinkDetail) GetRouterState() LinkState { + if x != nil { + return x.RouterState + } + return LinkState_LinkUnknown +} + +func (x *RouterLinkDetail) GetDestConnected() bool { + if x != nil { + return x.DestConnected + } + return false +} + +func (x *RouterLinkDetail) GetIsValid() bool { + if x != nil { + return x.IsValid + } + return false +} + +func (x *RouterLinkDetail) GetDestRouterId() string { + if x != nil { + return x.DestRouterId + } + return "" +} + +func (x *RouterLinkDetail) GetDialed() bool { + if x != nil { + return x.Dialed + } + return false +} + type StreamMetricsRequest_MetricMatcher struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1304,7 +1649,7 @@ type StreamMetricsRequest_MetricMatcher struct { func (x *StreamMetricsRequest_MetricMatcher) Reset() { *x = StreamMetricsRequest_MetricMatcher{} if protoimpl.UnsafeEnabled { - mi := &file_mgmt_proto_msgTypes[13] + mi := &file_mgmt_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1317,7 +1662,7 @@ func (x *StreamMetricsRequest_MetricMatcher) String() string { func (*StreamMetricsRequest_MetricMatcher) ProtoMessage() {} func (x *StreamMetricsRequest_MetricMatcher) ProtoReflect() protoreflect.Message { - mi := &file_mgmt_proto_msgTypes[13] + mi := &file_mgmt_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1361,7 +1706,7 @@ type StreamMetricsEvent_IntervalMetric struct { func (x *StreamMetricsEvent_IntervalMetric) Reset() { *x = StreamMetricsEvent_IntervalMetric{} if protoimpl.UnsafeEnabled { - mi := &file_mgmt_proto_msgTypes[17] + mi := &file_mgmt_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1374,7 +1719,7 @@ func (x *StreamMetricsEvent_IntervalMetric) String() string { func (*StreamMetricsEvent_IntervalMetric) ProtoMessage() {} func (x *StreamMetricsEvent_IntervalMetric) ProtoReflect() protoreflect.Message { - mi := &file_mgmt_proto_msgTypes[17] + mi := &file_mgmt_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1431,7 +1776,7 @@ type InspectResponse_InspectValue struct { func (x *InspectResponse_InspectValue) Reset() { *x = InspectResponse_InspectValue{} if protoimpl.UnsafeEnabled { - mi := &file_mgmt_proto_msgTypes[20] + mi := &file_mgmt_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1444,7 +1789,7 @@ func (x *InspectResponse_InspectValue) String() string { func (*InspectResponse_InspectValue) ProtoMessage() {} func (x *InspectResponse_InspectValue) ProtoReflect() protoreflect.Message { - mi := &file_mgmt_proto_msgTypes[20] + mi := &file_mgmt_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1684,92 +2029,146 @@ var file_mgmt_proto_rawDesc = []byte{ 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x69, 0x78, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x2a, 0xa6, 0x07, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x65, 0x72, 0x6f, 0x10, 0x00, 0x12, - 0x1c, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xb8, 0x4e, 0x12, 0x1a, 0x0a, - 0x15, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xb9, 0x4e, 0x12, 0x20, 0x0a, 0x1b, 0x54, 0x6f, 0x67, - 0x67, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbc, 0x4e, 0x12, 0x23, 0x0a, 0x1e, 0x54, - 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x54, 0x72, 0x61, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbd, 0x4e, - 0x12, 0x1c, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbe, 0x4e, 0x12, 0x1a, - 0x0a, 0x15, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbf, 0x4e, 0x12, 0x17, 0x0a, 0x12, 0x49, 0x6e, - 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x10, 0xc0, 0x4e, 0x12, 0x18, 0x0a, 0x13, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xc1, 0x4e, 0x12, 0x1a, 0x0a, - 0x15, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x44, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xd6, 0x4e, 0x12, 0x25, 0x0a, 0x20, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x72, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x4c, 0x69, - 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xd7, 0x4e, - 0x12, 0x2c, 0x0a, 0x27, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, - 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x43, 0x74, 0x72, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xd8, 0x4e, 0x12, 0x26, - 0x0a, 0x21, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x62, 0x75, 0x67, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x10, 0xd9, 0x4e, 0x12, 0x2e, 0x0a, 0x29, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x44, 0x65, 0x62, 0x75, 0x67, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x10, 0xda, 0x4e, 0x12, 0x24, 0x0a, 0x1f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x44, 0x65, 0x62, 0x75, 0x67, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xdb, 0x4e, 0x12, 0x22, 0x0a, 0x1d, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x62, 0x75, 0x67, 0x55, 0x6e, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xdc, 0x4e, - 0x12, 0x1d, 0x0a, 0x18, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x51, 0x75, 0x69, 0x65, 0x73, 0x63, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xdd, 0x4e, 0x12, - 0x1f, 0x0a, 0x1a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x71, 0x75, 0x69, 0x65, 0x73, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xde, 0x4e, - 0x12, 0x22, 0x0a, 0x1d, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x10, 0xdf, 0x4e, 0x12, 0x1f, 0x0a, 0x1a, 0x52, 0x61, 0x66, 0x74, 0x4c, 0x69, 0x73, 0x74, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x10, 0xe0, 0x4e, 0x12, 0x20, 0x0a, 0x1b, 0x52, 0x61, 0x66, 0x74, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x10, 0xe1, 0x4e, 0x12, 0x1b, 0x0a, 0x16, 0x52, 0x61, 0x66, 0x74, 0x41, - 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x10, 0xe2, 0x4e, 0x12, 0x1e, 0x0a, 0x19, 0x52, 0x61, 0x66, 0x74, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x10, 0xe3, 0x4e, 0x12, 0x26, 0x0a, 0x21, 0x52, 0x61, 0x66, 0x74, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x66, 0x65, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xe4, 0x4e, 0x12, 0x13, 0x0a, 0x0e, - 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x44, 0x62, 0x10, 0xe5, - 0x4e, 0x12, 0x23, 0x0a, 0x1e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x10, 0xf4, 0x4e, 0x12, 0x23, 0x0a, 0x1e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf5, 0x4e, 0x12, 0x21, 0x0a, 0x1c, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf6, 0x4e, 0x2a, 0x53, - 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x6f, 0x6e, 0x65, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x0a, 0x12, 0x12, 0x0a, - 0x0e, 0x43, 0x74, 0x72, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x10, - 0x0b, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x49, - 0x64, 0x10, 0x0c, 0x2a, 0x78, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x69, 0x72, - 0x63, 0x75, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, - 0x0e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x10, - 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x64, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, - 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x61, 0x74, - 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x69, - 0x72, 0x63, 0x75, 0x69, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x04, 0x2a, 0x2b, 0x0a, - 0x0f, 0x54, 0x72, 0x61, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, - 0x07, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x01, 0x2a, 0x77, 0x0a, 0x0f, 0x54, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x09, 0x0a, - 0x05, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, - 0x6f, 0x77, 0x6e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x02, - 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, - 0x77, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x10, 0x03, 0x12, 0x13, - 0x0a, 0x0f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x10, 0x04, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2f, 0x66, 0x61, 0x62, 0x72, 0x69, - 0x63, 0x2f, 0x70, 0x62, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x22, 0x34, 0x0a, 0x1a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x73, 0x0a, 0x1b, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, + 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x22, 0xd5, 0x01, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x44, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x6c, 0x69, 0x6e, 0x6b, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x7a, 0x69, + 0x74, 0x69, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x5f, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x0b, 0x6c, 0x69, 0x6e, + 0x6b, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x98, 0x02, 0x0a, 0x10, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x0a, + 0x06, 0x6c, 0x69, 0x6e, 0x6b, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, + 0x69, 0x6e, 0x6b, 0x49, 0x64, 0x12, 0x35, 0x0a, 0x09, 0x63, 0x74, 0x72, 0x6c, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x6d, 0x67, 0x6d, 0x74, 0x5f, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x52, 0x09, 0x63, 0x74, 0x72, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x39, 0x0a, 0x0b, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x17, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x5f, 0x70, 0x62, + 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x64, 0x65, 0x73, 0x74, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, + 0x64, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, + 0x07, 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, + 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, + 0x69, 0x61, 0x6c, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x69, 0x61, + 0x6c, 0x65, 0x64, 0x2a, 0x95, 0x08, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x65, 0x72, 0x6f, 0x10, 0x00, 0x12, 0x1c, 0x0a, + 0x17, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xb8, 0x4e, 0x12, 0x1a, 0x0a, 0x15, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x10, 0xb9, 0x4e, 0x12, 0x20, 0x0a, 0x1b, 0x54, 0x6f, 0x67, 0x67, 0x6c, + 0x65, 0x50, 0x69, 0x70, 0x65, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbc, 0x4e, 0x12, 0x23, 0x0a, 0x1e, 0x54, 0x6f, 0x67, + 0x67, 0x6c, 0x65, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbd, 0x4e, 0x12, 0x1c, + 0x0a, 0x17, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbe, 0x4e, 0x12, 0x1a, 0x0a, 0x15, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xbf, 0x4e, 0x12, 0x17, 0x0a, 0x12, 0x49, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xc0, + 0x4e, 0x12, 0x18, 0x0a, 0x13, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xc1, 0x4e, 0x12, 0x1a, 0x0a, 0x15, 0x53, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x44, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x10, 0xd6, 0x4e, 0x12, 0x25, 0x0a, 0x20, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x4c, 0x69, 0x6e, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xd7, 0x4e, 0x12, 0x2c, + 0x0a, 0x27, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x6f, 0x67, + 0x67, 0x6c, 0x65, 0x43, 0x74, 0x72, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xd8, 0x4e, 0x12, 0x26, 0x0a, 0x21, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x62, 0x75, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x10, 0xd9, 0x4e, 0x12, 0x2e, 0x0a, 0x29, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, + 0x62, 0x75, 0x67, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x10, 0xda, 0x4e, 0x12, 0x24, 0x0a, 0x1f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, + 0x62, 0x75, 0x67, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xdb, 0x4e, 0x12, 0x22, 0x0a, 0x1d, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x62, 0x75, 0x67, 0x55, 0x6e, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xdc, 0x4e, 0x12, 0x1d, + 0x0a, 0x18, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x51, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xdd, 0x4e, 0x12, 0x1f, 0x0a, + 0x1a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x71, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xde, 0x4e, 0x12, 0x22, + 0x0a, 0x1d, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x44, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, + 0xdf, 0x4e, 0x12, 0x1f, 0x0a, 0x1a, 0x52, 0x61, 0x66, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x10, 0xe0, 0x4e, 0x12, 0x20, 0x0a, 0x1b, 0x52, 0x61, 0x66, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x10, 0xe1, 0x4e, 0x12, 0x1b, 0x0a, 0x16, 0x52, 0x61, 0x66, 0x74, 0x41, 0x64, 0x64, + 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, + 0xe2, 0x4e, 0x12, 0x1e, 0x0a, 0x19, 0x52, 0x61, 0x66, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, + 0xe3, 0x4e, 0x12, 0x26, 0x0a, 0x21, 0x52, 0x61, 0x66, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, + 0x65, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xe4, 0x4e, 0x12, 0x13, 0x0a, 0x0e, 0x52, 0x61, + 0x66, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x44, 0x62, 0x10, 0xe5, 0x4e, 0x12, + 0x23, 0x0a, 0x1e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, + 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x10, 0xf4, 0x4e, 0x12, 0x23, 0x0a, 0x1e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf5, 0x4e, 0x12, 0x21, 0x0a, 0x1c, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf6, 0x4e, 0x12, 0x23, 0x0a, 0x1e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, + 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf7, + 0x4e, 0x12, 0x24, 0x0a, 0x1f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x10, 0xf8, 0x4e, 0x12, 0x22, 0x0a, 0x1d, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf9, 0x4e, 0x2a, 0x53, 0x0a, 0x06, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x6f, 0x6e, 0x65, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x10, 0x0a, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x74, + 0x72, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x10, 0x0b, 0x12, 0x10, + 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x10, 0x0c, + 0x2a, 0x78, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x69, + 0x72, 0x63, 0x75, 0x69, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x10, 0x00, 0x12, 0x12, + 0x0a, 0x0e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, + 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x50, 0x72, 0x65, + 0x73, 0x65, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x68, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x69, 0x72, 0x63, 0x75, + 0x69, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x04, 0x2a, 0x2b, 0x0a, 0x0f, 0x54, 0x72, + 0x61, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, + 0x07, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, + 0x43, 0x4c, 0x55, 0x44, 0x45, 0x10, 0x01, 0x2a, 0x77, 0x0a, 0x0f, 0x54, 0x65, 0x72, 0x6d, 0x69, + 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, + 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x6b, + 0x6e, 0x6f, 0x77, 0x6e, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x02, 0x12, 0x1c, 0x0a, + 0x18, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x54, + 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x49, + 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x10, 0x04, + 0x2a, 0x53, 0x0a, 0x09, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, + 0x0b, 0x4c, 0x69, 0x6e, 0x6b, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x13, + 0x0a, 0x0f, 0x4c, 0x69, 0x6e, 0x6b, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, + 0x64, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x69, 0x6e, 0x6b, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x69, 0x6e, 0x6b, 0x44, 0x69, 0x61, 0x6c, + 0x69, 0x6e, 0x67, 0x10, 0x03, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2f, 0x66, 0x61, 0x62, + 0x72, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x5f, 0x70, 0x62, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1784,59 +2183,67 @@ func file_mgmt_proto_rawDescGZIP() []byte { return file_mgmt_proto_rawDescData } -var file_mgmt_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_mgmt_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_mgmt_proto_enumTypes = make([]protoimpl.EnumInfo, 6) +var file_mgmt_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_mgmt_proto_goTypes = []interface{}{ (ContentType)(0), // 0: ziti.mgmt_pb.ContentType (Header)(0), // 1: ziti.mgmt_pb.Header (StreamCircuitEventType)(0), // 2: ziti.mgmt_pb.StreamCircuitEventType (TraceFilterType)(0), // 3: ziti.mgmt_pb.TraceFilterType (TerminatorState)(0), // 4: ziti.mgmt_pb.TerminatorState - (*StreamMetricsRequest)(nil), // 5: ziti.mgmt_pb.StreamMetricsRequest - (*StreamMetricsEvent)(nil), // 6: ziti.mgmt_pb.StreamMetricsEvent - (*Path)(nil), // 7: ziti.mgmt_pb.Path - (*StreamCircuitsEvent)(nil), // 8: ziti.mgmt_pb.StreamCircuitsEvent - (*ToggleCircuitTracesRequest)(nil), // 9: ziti.mgmt_pb.ToggleCircuitTracesRequest - (*StreamTracesRequest)(nil), // 10: ziti.mgmt_pb.StreamTracesRequest - (*InspectRequest)(nil), // 11: ziti.mgmt_pb.InspectRequest - (*InspectResponse)(nil), // 12: ziti.mgmt_pb.InspectResponse - (*RaftMember)(nil), // 13: ziti.mgmt_pb.RaftMember - (*RaftMemberListResponse)(nil), // 14: ziti.mgmt_pb.RaftMemberListResponse - (*ValidateTerminatorsRequest)(nil), // 15: ziti.mgmt_pb.ValidateTerminatorsRequest - (*ValidateTerminatorsResponse)(nil), // 16: ziti.mgmt_pb.ValidateTerminatorsResponse - (*TerminatorDetail)(nil), // 17: ziti.mgmt_pb.TerminatorDetail - (*StreamMetricsRequest_MetricMatcher)(nil), // 18: ziti.mgmt_pb.StreamMetricsRequest.MetricMatcher - nil, // 19: ziti.mgmt_pb.StreamMetricsEvent.TagsEntry - nil, // 20: ziti.mgmt_pb.StreamMetricsEvent.IntMetricsEntry - nil, // 21: ziti.mgmt_pb.StreamMetricsEvent.FloatMetricsEntry - (*StreamMetricsEvent_IntervalMetric)(nil), // 22: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric - nil, // 23: ziti.mgmt_pb.StreamMetricsEvent.MetricGroupEntry - nil, // 24: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.ValuesEntry - (*InspectResponse_InspectValue)(nil), // 25: ziti.mgmt_pb.InspectResponse.InspectValue - (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp + (LinkState)(0), // 5: ziti.mgmt_pb.LinkState + (*StreamMetricsRequest)(nil), // 6: ziti.mgmt_pb.StreamMetricsRequest + (*StreamMetricsEvent)(nil), // 7: ziti.mgmt_pb.StreamMetricsEvent + (*Path)(nil), // 8: ziti.mgmt_pb.Path + (*StreamCircuitsEvent)(nil), // 9: ziti.mgmt_pb.StreamCircuitsEvent + (*ToggleCircuitTracesRequest)(nil), // 10: ziti.mgmt_pb.ToggleCircuitTracesRequest + (*StreamTracesRequest)(nil), // 11: ziti.mgmt_pb.StreamTracesRequest + (*InspectRequest)(nil), // 12: ziti.mgmt_pb.InspectRequest + (*InspectResponse)(nil), // 13: ziti.mgmt_pb.InspectResponse + (*RaftMember)(nil), // 14: ziti.mgmt_pb.RaftMember + (*RaftMemberListResponse)(nil), // 15: ziti.mgmt_pb.RaftMemberListResponse + (*ValidateTerminatorsRequest)(nil), // 16: ziti.mgmt_pb.ValidateTerminatorsRequest + (*ValidateTerminatorsResponse)(nil), // 17: ziti.mgmt_pb.ValidateTerminatorsResponse + (*TerminatorDetail)(nil), // 18: ziti.mgmt_pb.TerminatorDetail + (*ValidateRouterLinksRequest)(nil), // 19: ziti.mgmt_pb.ValidateRouterLinksRequest + (*ValidateRouterLinksResponse)(nil), // 20: ziti.mgmt_pb.ValidateRouterLinksResponse + (*RouterLinkDetails)(nil), // 21: ziti.mgmt_pb.RouterLinkDetails + (*RouterLinkDetail)(nil), // 22: ziti.mgmt_pb.RouterLinkDetail + (*StreamMetricsRequest_MetricMatcher)(nil), // 23: ziti.mgmt_pb.StreamMetricsRequest.MetricMatcher + nil, // 24: ziti.mgmt_pb.StreamMetricsEvent.TagsEntry + nil, // 25: ziti.mgmt_pb.StreamMetricsEvent.IntMetricsEntry + nil, // 26: ziti.mgmt_pb.StreamMetricsEvent.FloatMetricsEntry + (*StreamMetricsEvent_IntervalMetric)(nil), // 27: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric + nil, // 28: ziti.mgmt_pb.StreamMetricsEvent.MetricGroupEntry + nil, // 29: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.ValuesEntry + (*InspectResponse_InspectValue)(nil), // 30: ziti.mgmt_pb.InspectResponse.InspectValue + (*timestamppb.Timestamp)(nil), // 31: google.protobuf.Timestamp } var file_mgmt_proto_depIdxs = []int32{ - 18, // 0: ziti.mgmt_pb.StreamMetricsRequest.matchers:type_name -> ziti.mgmt_pb.StreamMetricsRequest.MetricMatcher - 26, // 1: ziti.mgmt_pb.StreamMetricsEvent.timestamp:type_name -> google.protobuf.Timestamp - 19, // 2: ziti.mgmt_pb.StreamMetricsEvent.tags:type_name -> ziti.mgmt_pb.StreamMetricsEvent.TagsEntry - 20, // 3: ziti.mgmt_pb.StreamMetricsEvent.intMetrics:type_name -> ziti.mgmt_pb.StreamMetricsEvent.IntMetricsEntry - 21, // 4: ziti.mgmt_pb.StreamMetricsEvent.floatMetrics:type_name -> ziti.mgmt_pb.StreamMetricsEvent.FloatMetricsEntry - 22, // 5: ziti.mgmt_pb.StreamMetricsEvent.intervalMetrics:type_name -> ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric - 23, // 6: ziti.mgmt_pb.StreamMetricsEvent.metricGroup:type_name -> ziti.mgmt_pb.StreamMetricsEvent.MetricGroupEntry + 23, // 0: ziti.mgmt_pb.StreamMetricsRequest.matchers:type_name -> ziti.mgmt_pb.StreamMetricsRequest.MetricMatcher + 31, // 1: ziti.mgmt_pb.StreamMetricsEvent.timestamp:type_name -> google.protobuf.Timestamp + 24, // 2: ziti.mgmt_pb.StreamMetricsEvent.tags:type_name -> ziti.mgmt_pb.StreamMetricsEvent.TagsEntry + 25, // 3: ziti.mgmt_pb.StreamMetricsEvent.intMetrics:type_name -> ziti.mgmt_pb.StreamMetricsEvent.IntMetricsEntry + 26, // 4: ziti.mgmt_pb.StreamMetricsEvent.floatMetrics:type_name -> ziti.mgmt_pb.StreamMetricsEvent.FloatMetricsEntry + 27, // 5: ziti.mgmt_pb.StreamMetricsEvent.intervalMetrics:type_name -> ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric + 28, // 6: ziti.mgmt_pb.StreamMetricsEvent.metricGroup:type_name -> ziti.mgmt_pb.StreamMetricsEvent.MetricGroupEntry 2, // 7: ziti.mgmt_pb.StreamCircuitsEvent.eventType:type_name -> ziti.mgmt_pb.StreamCircuitEventType - 7, // 8: ziti.mgmt_pb.StreamCircuitsEvent.path:type_name -> ziti.mgmt_pb.Path + 8, // 8: ziti.mgmt_pb.StreamCircuitsEvent.path:type_name -> ziti.mgmt_pb.Path 3, // 9: ziti.mgmt_pb.StreamTracesRequest.filterType:type_name -> ziti.mgmt_pb.TraceFilterType - 25, // 10: ziti.mgmt_pb.InspectResponse.values:type_name -> ziti.mgmt_pb.InspectResponse.InspectValue - 13, // 11: ziti.mgmt_pb.RaftMemberListResponse.members:type_name -> ziti.mgmt_pb.RaftMember + 30, // 10: ziti.mgmt_pb.InspectResponse.values:type_name -> ziti.mgmt_pb.InspectResponse.InspectValue + 14, // 11: ziti.mgmt_pb.RaftMemberListResponse.members:type_name -> ziti.mgmt_pb.RaftMember 4, // 12: ziti.mgmt_pb.TerminatorDetail.state:type_name -> ziti.mgmt_pb.TerminatorState - 26, // 13: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.intervalStartUTC:type_name -> google.protobuf.Timestamp - 26, // 14: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.intervalEndUTC:type_name -> google.protobuf.Timestamp - 24, // 15: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.values:type_name -> ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.ValuesEntry - 16, // [16:16] is the sub-list for method output_type - 16, // [16:16] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name + 22, // 13: ziti.mgmt_pb.RouterLinkDetails.linkDetails:type_name -> ziti.mgmt_pb.RouterLinkDetail + 5, // 14: ziti.mgmt_pb.RouterLinkDetail.ctrlState:type_name -> ziti.mgmt_pb.LinkState + 5, // 15: ziti.mgmt_pb.RouterLinkDetail.routerState:type_name -> ziti.mgmt_pb.LinkState + 31, // 16: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.intervalStartUTC:type_name -> google.protobuf.Timestamp + 31, // 17: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.intervalEndUTC:type_name -> google.protobuf.Timestamp + 29, // 18: ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.values:type_name -> ziti.mgmt_pb.StreamMetricsEvent.IntervalMetric.ValuesEntry + 19, // [19:19] is the sub-list for method output_type + 19, // [19:19] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name } func init() { file_mgmt_proto_init() } @@ -2002,7 +2409,43 @@ func file_mgmt_proto_init() { } } file_mgmt_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StreamMetricsRequest_MetricMatcher); i { + switch v := v.(*ValidateRouterLinksRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ValidateRouterLinksResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouterLinkDetails); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouterLinkDetail); i { case 0: return &v.state case 1: @@ -2014,6 +2457,18 @@ func file_mgmt_proto_init() { } } file_mgmt_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StreamMetricsRequest_MetricMatcher); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StreamMetricsEvent_IntervalMetric); i { case 0: return &v.state @@ -2025,7 +2480,7 @@ func file_mgmt_proto_init() { return nil } } - file_mgmt_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_mgmt_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InspectResponse_InspectValue); i { case 0: return &v.state @@ -2044,8 +2499,8 @@ func file_mgmt_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_mgmt_proto_rawDesc, - NumEnums: 5, - NumMessages: 21, + NumEnums: 6, + NumMessages: 25, NumExtensions: 0, NumServices: 0, }, diff --git a/common/pb/mgmt_pb/mgmt.proto b/common/pb/mgmt_pb/mgmt.proto index 8377a43c6..7290097a1 100644 --- a/common/pb/mgmt_pb/mgmt.proto +++ b/common/pb/mgmt_pb/mgmt.proto @@ -49,6 +49,11 @@ enum ContentType { ValidateTerminatorsRequestType = 10100; ValidateTerminatorResponseType = 10101; ValidateTerminatorResultType = 10102; + + ValidateRouterLinksRequestType = 10103; + ValidateRouterLinksResponseType = 10104; + ValidateRouterLinksResultType = 10105; + } enum Header { @@ -196,4 +201,39 @@ message TerminatorDetail { TerminatorState state = 10; bool fixed = 11; string detail = 12; -} \ No newline at end of file +} + +message ValidateRouterLinksRequest { + string filter = 1; +} + +message ValidateRouterLinksResponse { + bool success = 1; + string message = 2; + uint64 routerCount = 3; +} + +message RouterLinkDetails { + string routerId = 1; + string routerName = 2; + bool validateSuccess = 3; + string message = 4; + repeated RouterLinkDetail linkDetails = 5; +} + +enum LinkState { + LinkUnknown = 0; + LinkEstablished = 1; + LinkPending = 2; + LinkDialing = 3; +} + +message RouterLinkDetail { + string linkId = 1; + LinkState ctrlState = 2; + LinkState routerState = 3; + bool destConnected = 4; + bool isValid = 5; + string destRouterId = 6; + bool dialed = 7; +} diff --git a/controller/api/api.go b/controller/api/api.go index 85e9bacd6..251066e91 100644 --- a/controller/api/api.go +++ b/controller/api/api.go @@ -18,15 +18,15 @@ package api import ( "github.com/go-openapi/runtime" + "github.com/openziti/foundation/v2/errorz" "github.com/openziti/ziti/controller/apierror" "github.com/openziti/ziti/controller/change" - "github.com/openziti/foundation/v2/errorz" "net/http" ) type Responder interface { Respond(data interface{}, httpStatus int) - RespondWithProducer(producer runtime.Producer, data interface{}, httpStatus int) + RespondWithProducer(producer runtime.Producer, data interface{}, httpStatus int) bool RespondWithEmptyOk() RespondWithError(err error) RespondWithApiError(err *errorz.ApiError) diff --git a/controller/api/responder.go b/controller/api/responder.go index 67a6fb5c9..b67bee463 100644 --- a/controller/api/responder.go +++ b/controller/api/responder.go @@ -21,8 +21,8 @@ import ( "fmt" "github.com/go-openapi/runtime" "github.com/michaelquigley/pfxlog" - "github.com/openziti/ziti/controller/apierror" "github.com/openziti/foundation/v2/errorz" + "github.com/openziti/ziti/controller/apierror" "net/http" "strconv" "strings" @@ -84,7 +84,7 @@ func (responder *ResponderImpl) Respond(data interface{}, httpStatus int) { responder.RespondWithProducer(responder.GetProducer(), data, httpStatus) } -func (responder *ResponderImpl) RespondWithProducer(producer runtime.Producer, data interface{}, httpStatus int) { +func (responder *ResponderImpl) RespondWithProducer(producer runtime.Producer, data interface{}, httpStatus int) bool { w := responder.rc.GetResponseWriter() buff := &bytes.Buffer{} err := producer.Produce(buff, data) @@ -106,9 +106,10 @@ func (responder *ResponderImpl) RespondWithProducer(producer runtime.Producer, d WithField("path", responder.rc.GetRequest().URL.Path). WithError(err). Error("could not respond with producer error") + return false } - return + return true } w.Header().Set("Content-Length", strconv.Itoa(buff.Len())) @@ -123,6 +124,7 @@ func (responder *ResponderImpl) RespondWithProducer(producer runtime.Producer, d WithError(err). Error("could not respond, writing to response failed") } + return err == nil } func (responder *ResponderImpl) RespondWithError(err error) { diff --git a/controller/api/timeouts.go b/controller/api/timeouts.go index 33ede137a..b4126e16b 100644 --- a/controller/api/timeouts.go +++ b/controller/api/timeouts.go @@ -21,16 +21,17 @@ import ( "context" "errors" "fmt" - "github.com/go-openapi/runtime" - "github.com/michaelquigley/pfxlog" - "github.com/openziti/foundation/v2/debugz" - "github.com/openziti/foundation/v2/errorz" "net/http" "path" goruntime "runtime" "strings" "sync" "time" + + "github.com/go-openapi/runtime" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/foundation/v2/debugz" + "github.com/openziti/foundation/v2/errorz" ) // TimeoutHandler will create a http.Handler that wraps the given http.Handler. If the given timeout is reached, the @@ -70,7 +71,7 @@ func (h *timeoutHandler) errorBody(w http.ResponseWriter, r *http.Request) error return err } - return errors.New("no timout api error specified") + return errors.New("no timeout api error specified") } func (h *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/controller/api_impl/circuit_router.go b/controller/api_impl/circuit_router.go index 964f15d2d..d12209ffc 100644 --- a/controller/api_impl/circuit_router.go +++ b/controller/api_impl/circuit_router.go @@ -63,6 +63,10 @@ func (r *CircuitRouter) ListCircuits(n *network.Network, rc api.RequestContext) return nil, err } + if query.GetLimit() == nil { + query.SetLimit(10) + } + circuits, count, err := n.GetCircuitStore().QueryEntitiesC(query) if err != nil { return nil, err diff --git a/controller/api_impl/link_api_model.go b/controller/api_impl/link_api_model.go index 97c720505..2059df50d 100644 --- a/controller/api_impl/link_api_model.go +++ b/controller/api_impl/link_api_model.go @@ -41,7 +41,8 @@ func (factory *LinkLinkFactoryIml) Links(entity LinkEntity) rest_model.Links { return links } -func MapLinkToRestModel(_ *network.Network, _ api.RequestContext, link *network.Link) (*rest_model.LinkDetail, error) { +func MapLinkToRestModel(n *network.Network, _ api.RequestContext, link *network.Link) (*rest_model.LinkDetail, error) { + iteration := int64(link.Iteration) staticCost := int64(link.StaticCost) linkState := link.CurrentState() linkStateStr := "" @@ -51,10 +52,19 @@ func MapLinkToRestModel(_ *network.Network, _ api.RequestContext, link *network. down := link.IsDown() + destRouter := link.GetDest() + if destRouter == nil { + var err error + destRouter, err = n.Routers.Read(link.DstId) + if err != nil { + return nil, err + } + } + ret := &rest_model.LinkDetail{ Cost: &link.Cost, DestLatency: &link.DstLatency, - DestRouter: ToEntityRef(link.Dst.Name, link.Dst, RouterLinkFactory), + DestRouter: ToEntityRef(destRouter.Name, destRouter, RouterLinkFactory), Down: &down, ID: &link.Id, SourceLatency: &link.SrcLatency, @@ -62,6 +72,7 @@ func MapLinkToRestModel(_ *network.Network, _ api.RequestContext, link *network. State: &linkStateStr, StaticCost: &staticCost, Protocol: &link.Protocol, + Iteration: &iteration, } return ret, nil } diff --git a/controller/api_impl/link_router.go b/controller/api_impl/link_router.go index 910ee534d..cf2e6062c 100644 --- a/controller/api_impl/link_router.go +++ b/controller/api_impl/link_router.go @@ -68,6 +68,10 @@ func (r *LinkRouter) ListLinks(n *network.Network, rc api.RequestContext) { return nil, err } + if query.GetLimit() == nil { + query.SetLimit(10) + } + links, count, err := n.GetLinkStore().QueryEntitiesC(query) if err != nil { return nil, err diff --git a/controller/command/rate_limiter.go b/controller/command/rate_limiter.go index 197611c67..9ddf08846 100644 --- a/controller/command/rate_limiter.go +++ b/controller/command/rate_limiter.go @@ -17,16 +17,18 @@ package command import ( + "fmt" "github.com/openziti/metrics" "github.com/openziti/ziti/controller/apierror" "github.com/pkg/errors" + "sync" "sync/atomic" "time" ) const ( - MetricLimiterCurrentQueuedCount = "command.limiter.queued_count" - MetricLimiterWorkTimer = "command.limiter.work_timer" + MetricCommandLimiterCurrentQueuedCount = "command.limiter.queued_count" + MetricCommandLimiterWorkTimer = "command.limiter.work_timer" DefaultLimiterSize = 100 MinLimiterSize = 10 @@ -49,14 +51,14 @@ func NewRateLimiter(config RateLimiterConfig, registry metrics.Registry, closeNo result := &DefaultRateLimiter{ queue: make(chan *rateLimitedWork, config.QueueSize), closeNotify: closeNotify, - workRate: registry.Timer(MetricLimiterWorkTimer), + workRate: registry.Timer(MetricCommandLimiterWorkTimer), } - if existing := registry.GetGauge(MetricLimiterCurrentQueuedCount); existing != nil { + if existing := registry.GetGauge(MetricCommandLimiterCurrentQueuedCount); existing != nil { existing.Dispose() } - registry.FuncGauge(MetricLimiterCurrentQueuedCount, func() int64 { + registry.FuncGauge(MetricCommandLimiterCurrentQueuedCount, func() int64 { return int64(result.currentSize.Load()) }) @@ -65,16 +67,46 @@ func NewRateLimiter(config RateLimiterConfig, registry metrics.Registry, closeNo return result } +// A RateLimiter allows running arbitrary, sequential operations with a limiter, so that only N operations +// can be queued to run at any given time. If the system is too busy, the rate limiter will return +// an ApiError indicating that the server is too busy type RateLimiter interface { RunRateLimited(func() error) error } +// An AdaptiveRateLimiter allows running arbitrary, sequential operations with a limiter, so that only N operations +// can be queued to run at any given time. If the system is too busy, the rate limiter will return +// an ApiError indicating that the server is too busy. +// +// The rate limiter returns a RateLimitControl, allow the calling code to indicate if the operation finished in +// time. If operations are timing out before the results are available, the rate limiter should allow fewer +// operations in, as they will likely time out before the results can be used. +// +// The rate limiter doesn't have a set queue size, it has a window which can grow and shrink. When +// a timeout is signaled, using the RateLimitControl, it shrinks the window based on queue position +// of the timed out operation. For example, if an operation was queued at position 200, but the times +// out, we assume that we need to limit the queue size to something less than 200 for now. +// +// The limiter will also reject already queued operations if the window size changes and the operation +// was queued at a position larger than the current window size. +// +// The window size will slowly grow back towards the max as successes are noted in the RateLimitControl. +type AdaptiveRateLimiter interface { + RunRateLimited(f func() error) (RateLimitControl, error) +} + type NoOpRateLimiter struct{} func (self NoOpRateLimiter) RunRateLimited(f func() error) error { return f() } +type NoOpAdaptiveRateLimiter struct{} + +func (self NoOpAdaptiveRateLimiter) RunRateLimited(f func() error) (RateLimitControl, error) { + return noOpRateLimitControl{}, f() +} + type rateLimitedWork struct { wrapped func() error result chan error @@ -127,3 +159,216 @@ func (self *DefaultRateLimiter) run() { } } } + +// AdaptiveRateLimiterConfig contains configuration values used to create a new AdaptiveRateLimiter +type AdaptiveRateLimiterConfig struct { + // Enabled - if false, a no-op rate limiter will be created, which doesn't enforce any rate limiting + Enabled bool + + // MaxSize - the maximum window size to allow + MaxSize uint32 + + // MinSize - the smallest window size to allow + MinSize uint32 + + // WorkTimerMetric - the name of the timer metric for timing how long operations take to execute + WorkTimerMetric string + + // QueueSize - the name of the gauge metric showing the current number of operations queued + QueueSizeMetric string + + // WindowSizeMetric - the name of the metric show the current window size + WindowSizeMetric string +} + +func (self *AdaptiveRateLimiterConfig) Validate() error { + if !self.Enabled { + return nil + } + + if self.MinSize < 1 { + return errors.New("adaptive rate limiter min size is 1") + } + if self.MinSize > self.MaxSize { + return fmt.Errorf("adaptive rate limiter min size must be <- max size. min: %v, max: %v", self.MinSize, self.MaxSize) + } + return nil +} + +func NewAdaptiveRateLimiter(config AdaptiveRateLimiterConfig, registry metrics.Registry, closeNotify <-chan struct{}) AdaptiveRateLimiter { + if !config.Enabled { + return NoOpAdaptiveRateLimiter{} + } + + result := &adaptiveRateLimiter{ + currentWindow: atomic.Int32{}, + minWindow: int32(config.MinSize), + maxWindow: int32(config.MaxSize), + queue: make(chan *adaptiveRateLimitedWork, config.MaxSize), + closeNotify: closeNotify, + workRate: registry.Timer(config.WorkTimerMetric), + } + + if existing := registry.GetGauge(config.QueueSizeMetric); existing != nil { + existing.Dispose() + } + + registry.FuncGauge(config.QueueSizeMetric, func() int64 { + return int64(result.currentSize.Load()) + }) + + if existing := registry.GetGauge(config.WindowSizeMetric); existing != nil { + existing.Dispose() + } + + registry.FuncGauge(config.WindowSizeMetric, func() int64 { + return int64(result.currentWindow.Load()) + }) + + result.currentWindow.Store(int32(config.MaxSize)) + + go result.run() + + return result +} + +type adaptiveRateLimitedWork struct { + queuePosition int32 + wrapped func() error + result chan error +} + +type adaptiveRateLimiter struct { + currentWindow atomic.Int32 + minWindow int32 + maxWindow int32 + lock sync.Mutex + successCounter atomic.Uint32 + + currentSize atomic.Int32 + queue chan *adaptiveRateLimitedWork + closeNotify <-chan struct{} + workRate metrics.Timer +} + +func (self *adaptiveRateLimiter) success() { + if self.currentWindow.Load() >= self.maxWindow { + return + } + + self.lock.Lock() + defer self.lock.Unlock() + + if self.successCounter.Add(1)%10 == 0 { + if nextVal := self.currentWindow.Add(1); nextVal > self.maxWindow { + self.currentWindow.Store(self.maxWindow) + } + } +} + +func (self *adaptiveRateLimiter) failure(queuePosition int32) { + if self.currentWindow.Load() <= self.minWindow { + return + } + + self.lock.Lock() + defer self.lock.Unlock() + + current := self.currentWindow.Load() + nextWindow := queuePosition - 10 + if nextWindow < current { + if nextWindow < self.minWindow { + nextWindow = self.minWindow + } + self.currentWindow.Store(nextWindow) + } +} + +func (self *adaptiveRateLimiter) RunRateLimited(f func() error) (RateLimitControl, error) { + work := &adaptiveRateLimitedWork{ + wrapped: f, + result: make(chan error, 1), + } + + self.lock.Lock() + queuePosition := self.currentSize.Add(1) + hasRoom := queuePosition <= self.currentWindow.Load() + if !hasRoom { + self.currentSize.Add(-1) + } + self.lock.Unlock() + + if !hasRoom { + return noOpRateLimitControl{}, apierror.NewTooManyUpdatesError() + } + + work.queuePosition = queuePosition + + defer self.currentSize.Add(-1) + + select { + case self.queue <- work: + select { + case result := <-work.result: + return rateLimitControl{limiter: self, queuePosition: work.queuePosition}, result + case <-self.closeNotify: + return noOpRateLimitControl{}, errors.New("rate limiter shutting down") + } + case <-self.closeNotify: + return noOpRateLimitControl{}, errors.New("rate limiter shutting down") + default: + return noOpRateLimitControl{}, apierror.NewTooManyUpdatesError() + } +} + +func (self *adaptiveRateLimiter) run() { + defer self.workRate.Dispose() + + for { + select { + case work := <-self.queue: + + // if we're likely to discard the work because things have been timing out, + // skip it, and return an error instead + if work.queuePosition > self.currentWindow.Load()+10 { + work.result <- apierror.NewTooManyUpdatesError() + close(work.result) + continue + } + + startTime := time.Now() + result := work.wrapped() + self.workRate.UpdateSince(startTime) + if result != nil { + work.result <- result + } + close(work.result) + case <-self.closeNotify: + return + } + } +} + +type RateLimitControl interface { + Success() + Timeout() +} + +type rateLimitControl struct { + limiter *adaptiveRateLimiter + queuePosition int32 +} + +func (r rateLimitControl) Success() { + r.limiter.success() +} + +func (r rateLimitControl) Timeout() { + r.limiter.failure(r.queuePosition) +} + +type noOpRateLimitControl struct{} + +func (noOpRateLimitControl) Success() {} + +func (noOpRateLimitControl) Timeout() {} diff --git a/controller/command/rate_limiter_test.go b/controller/command/rate_limiter_test.go new file mode 100644 index 000000000..b5738dc89 --- /dev/null +++ b/controller/command/rate_limiter_test.go @@ -0,0 +1,145 @@ +//go:build perf + +/* + 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 command + +import ( + "errors" + "fmt" + "github.com/openziti/foundation/v2/errorz" + "github.com/openziti/metrics" + "github.com/openziti/sdk-golang/ziti" + "github.com/openziti/ziti/controller/apierror" + "sync" + "sync/atomic" + "testing" + "time" +) + +func Test_AdaptiveRateLimiter(t *testing.T) { + cfg := AdaptiveRateLimiterConfig{ + Enabled: true, + MaxSize: 250, + MinSize: 5, + } + + registry := metrics.NewRegistry("test", nil) + closeNotify := make(chan struct{}) + limiter := NewAdaptiveRateLimiter(cfg, registry, closeNotify).(*adaptiveRateLimiter) + + var queueFull atomic.Uint32 + var timedOut atomic.Uint32 + var completed atomic.Uint32 + + countdown := &sync.WaitGroup{} + + logStats := func() { + fmt.Printf("queueFulls: %v\n", queueFull.Load()) + fmt.Printf("timedOut: %v\n", timedOut.Load()) + fmt.Printf("completed: %v\n", completed.Load()) + fmt.Printf("queueSize: %v\n", limiter.currentSize.Load()) + fmt.Printf("windowSize: %v\n", limiter.currentWindow.Load()) + } + + go func() { + for { + select { + case <-closeNotify: + return + case <-time.After(time.Second): + logStats() + } + } + }() + + for i := 0; i < 300; i++ { + countdown.Add(1) + + go func() { + defer countdown.Done() + count := 0 + for count < 1000 { + start := time.Now() + ctrl, err := limiter.RunRateLimited(func() error { + time.Sleep(25 * time.Millisecond) + return nil + }) + + if err == nil { + elapsed := time.Since(start) + if elapsed > time.Second*5 { + timedOut.Add(1) + ctrl.Timeout() + } else { + count++ + completed.Add(1) + ctrl.Success() + } + } else { + apiError := &errorz.ApiError{} + if errors.As(err, &apiError) && apiError.Code == apierror.ServerTooManyRequestsCode { + queueFull.Add(1) + } else { + panic(err) + } + } + } + }() + } + + countdown.Wait() + close(closeNotify) + logStats() +} + +func Test_AuthFlood(t *testing.T) { + countdown := &sync.WaitGroup{} + + var complete atomic.Int32 + var errCount atomic.Int32 + + for i := 0; i < 100; i++ { + countdown.Add(1) + idx := i + go func() { + defer countdown.Done() + + ctx, err := ziti.NewContextFromFile("/home/plorenz/work/demo/zcat.json") + if err != nil { + panic(err) + } + + ctxImpl := ctx.(*ziti.ContextImpl) + + for j := 0; j < 10; j++ { + for { + _, err = ctxImpl.CtrlClt.Authenticate() + if err == nil { + break + } else { + errCount.Add(1) + } + } + done := complete.Add(1) + fmt.Printf("%v done!, competed: %v, errs: %v\n", idx, done, errCount.Load()) + } + }() + } + + countdown.Wait() +} diff --git a/controller/config/config.go b/controller/config/config.go index e2662c5b7..be1e92368 100644 --- a/controller/config/config.go +++ b/controller/config/config.go @@ -24,6 +24,7 @@ import ( "fmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/identity" + "github.com/openziti/ziti/controller/command" "github.com/pkg/errors" "net" "net/url" @@ -55,6 +56,13 @@ const ( DefaultHttpWriteTimeout = 100000 * time.Millisecond DefaultTotpDomain = "openziti.io" + + DefaultAuthRateLimiterEnabled = true + DefaultAuthRateLimiterMaxSize = 250 + DefaultAuthRateLimiterMinSize = 5 + + AuthRateLimiterMinSizeValue = 5 + AuthRateLimiterMaxSizeValue = 1000 ) type Enrollment struct { @@ -89,9 +97,10 @@ type Config struct { Api Api Enrollment Enrollment - caPems *bytes.Buffer - caPemsOnce sync.Once - Totp Totp + caPems *bytes.Buffer + caPemsOnce sync.Once + Totp Totp + AuthRateLimiter command.AdaptiveRateLimiterConfig } type HttpTimeouts struct { @@ -392,6 +401,56 @@ func (c *Config) loadEnrollmentSection(edgeConfigMap map[interface{}]interface{} return nil } +func (c *Config) loadAuthRateLimiter(cfgmap map[interface{}]interface{}) error { + c.AuthRateLimiter.Enabled = DefaultAuthRateLimiterEnabled + c.AuthRateLimiter.MaxSize = DefaultAuthRateLimiterMaxSize + c.AuthRateLimiter.MinSize = DefaultAuthRateLimiterMinSize + + if value, found := cfgmap["authRateLimiter"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["enabled"]; found { + c.AuthRateLimiter.Enabled = strings.EqualFold("true", fmt.Sprintf("%v", value)) + } + + if value, found := submap["maxSize"]; found { + if intVal, ok := value.(int); ok { + v := int64(intVal) + if v < AuthRateLimiterMinSizeValue { + return errors.Errorf("invalid value %v for authRateLimiter.maxSize, must be at least %v", value, AuthRateLimiterMinSizeValue) + } + if v > AuthRateLimiterMaxSizeValue { + return errors.Errorf("invalid value %v for authRateLimiter.maxSize, must be at most %v", value, AuthRateLimiterMaxSizeValue) + } + c.AuthRateLimiter.MaxSize = uint32(v) + } else { + return errors.Errorf("invalid value %v for authRateLimiter.maxSize, must be integer value", value) + } + } + + if value, found := submap["minSize"]; found { + if intVal, ok := value.(int); ok { + v := int64(intVal) + if v < AuthRateLimiterMinSizeValue { + return errors.Errorf("invalid value %v for authRateLimiter.minSize, must be at least %v", value, AuthRateLimiterMinSizeValue) + } + if v > AuthRateLimiterMaxSizeValue { + return errors.Errorf("invalid value %v for authRateLimiter.minSize, must be at most %v", value, AuthRateLimiterMaxSizeValue) + } + c.AuthRateLimiter.MinSize = uint32(v) + } else { + return errors.Errorf("invalid value %v for authRateLimiter.minSize, must be integer value", value) + } + } + + if c.AuthRateLimiter.MinSize > c.AuthRateLimiter.MaxSize { + return errors.Errorf("invalid values, %v, %v for authRateLimiter minSize and maxSize, min must be <= max", + c.AuthRateLimiter.MinSize, c.AuthRateLimiter.MaxSize) + } + } + } + return nil +} + func LoadFromMap(configMap map[interface{}]interface{}) (*Config, error) { edgeConfig := NewConfig() @@ -425,6 +484,10 @@ func LoadFromMap(configMap map[interface{}]interface{}) (*Config, error) { return nil, err } + if err = edgeConfig.loadAuthRateLimiter(edgeConfigMap); err != nil { + return nil, err + } + return edgeConfig, nil } diff --git a/controller/controller.go b/controller/controller.go index 00931edc9..5c3cf0eab 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -264,9 +264,10 @@ func (c *Controller) Run() error { capabilityMask := &big.Int{} capabilityMask.SetBit(capabilityMask, capabilities.ControllerCreateTerminatorV2, 1) + capabilityMask.SetBit(capabilityMask, capabilities.ControllerSingleRouterLinkSource, 1) headers := map[int32][]byte{ - channel.HelloVersionHeader: versionHeader, - int32(ctrl_pb.ContentType_CapabilitiesHeader): capabilityMask.Bytes(), + channel.HelloVersionHeader: versionHeader, + int32(ctrl_pb.ControlHeaders_CapabilitiesHeader): capabilityMask.Bytes(), } if c.raftController != nil { diff --git a/controller/db/migration_v16.go b/controller/db/migration_v16.go index 5894f9041..1e5b00193 100644 --- a/controller/db/migration_v16.go +++ b/controller/db/migration_v16.go @@ -2,6 +2,7 @@ package db import ( "fmt" + "github.com/michaelquigley/pfxlog" "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" @@ -17,7 +18,7 @@ func (m *Migrations) removeOrphanedOttCaEnrollments(step *boltz.MigrationStep) { enrollment, err := m.stores.Enrollment.LoadOneById(step.Ctx.Tx(), currentEnrollmentId) if err != nil { - step.SetError(fmt.Errorf("error interating ids of enrollments, enrollment [%s]: %v", currentEnrollmentId, err)) + step.SetError(fmt.Errorf("error iterating ids of enrollments, enrollment [%s]: %v", currentEnrollmentId, err)) return } diff --git a/controller/db/migration_v17.go b/controller/db/migration_v17.go index 633b77cce..c7d6c42ed 100644 --- a/controller/db/migration_v17.go +++ b/controller/db/migration_v17.go @@ -2,6 +2,7 @@ package db import ( "fmt" + "github.com/openziti/storage/ast" "github.com/openziti/storage/boltz" ) @@ -14,7 +15,7 @@ func (m *Migrations) removeAllSessions(step *boltz.MigrationStep) { currentSessionId := string(current) if err := m.stores.Session.DeleteById(step.Ctx, currentSessionId); err != nil { - step.SetError(fmt.Errorf("error cleaing up sessions for migration: %v", err)) + step.SetError(fmt.Errorf("error cleaning up sessions for migration: %v", err)) return } } @@ -24,7 +25,7 @@ func (m *Migrations) removeAllSessions(step *boltz.MigrationStep) { currentApiSessionId := string(current) if err := m.stores.ApiSession.DeleteById(step.Ctx, currentApiSessionId); err != nil { - step.SetError(fmt.Errorf("error cleaing up api sessions for migration: %v", err)) + step.SetError(fmt.Errorf("error cleaning up api sessions for migration: %v", err)) return } } diff --git a/controller/env/appenv.go b/controller/env/appenv.go index d538e1bf4..c4e5bd314 100644 --- a/controller/env/appenv.go +++ b/controller/env/appenv.go @@ -48,6 +48,7 @@ import ( "github.com/openziti/ziti/common/cert" "github.com/openziti/ziti/common/eid" "github.com/openziti/ziti/controller/api" + "github.com/openziti/ziti/controller/command" edgeConfig "github.com/openziti/ziti/controller/config" "github.com/openziti/ziti/controller/db" "github.com/openziti/ziti/controller/event" @@ -74,6 +75,12 @@ var _ model.Env = &AppEnv{} const ZitiSession = "zt-session" +const ( + metricAuthLimiterCurrentQueuedCount = "auth.limiter.queued_count" + metricAuthLimiterCurrentWindowSize = "auth.limiter.window_size" + metricAuthLimiterWorkTimer = "auth.limiter.work_timer" +) + type AppEnv struct { Managers *model.Managers Config *edgeConfig.Config @@ -99,6 +106,7 @@ type AppEnv struct { TraceManager *TraceManager ServerCert *tls.Certificate ServerCertSigningMethod jwt.SigningMethod + AuthRateLimiter command.AdaptiveRateLimiter } // JwtSignerKeyFunc is used in combination with jwt.Parse or jwt.ParseWithClaims to @@ -537,6 +545,14 @@ func NewAppEnv(c *edgeConfig.Config, host HostController) *AppEnv { ClientApi: clientApi, IdentityRefreshMap: cmap.New[time.Time](), StartupTime: time.Now().UTC(), + AuthRateLimiter: command.NewAdaptiveRateLimiter(command.AdaptiveRateLimiterConfig{ + Enabled: c.AuthRateLimiter.Enabled, + MinSize: c.AuthRateLimiter.MinSize, + MaxSize: c.AuthRateLimiter.MaxSize, + WorkTimerMetric: metricAuthLimiterWorkTimer, + QueueSizeMetric: metricAuthLimiterCurrentQueuedCount, + WindowSizeMetric: metricAuthLimiterCurrentWindowSize, + }, host.GetNetwork().GetMetricsRegistry(), host.GetCloseNotifyChannel()), } ae.identityRefreshMeter = ae.GetHostController().GetNetwork().GetMetricsRegistry().Meter("identity.refresh") diff --git a/controller/events/metrics_mappers.go b/controller/events/metrics_mappers.go index a957d1589..acb5783a6 100644 --- a/controller/events/metrics_mappers.go +++ b/controller/events/metrics_mappers.go @@ -58,7 +58,7 @@ func (self *linkMetricsMapper) mapMetrics(_ *metrics_pb.MetricsMessage, event *e event.Tags[k] = v } event.Tags["sourceRouterId"] = link.Src.Id - event.Tags["targetRouterId"] = link.Dst.Id + event.Tags["targetRouterId"] = link.DstId } } } diff --git a/controller/handler_ctrl/accept.go b/controller/handler_ctrl/accept.go index 50b9f14c0..78d4279e5 100644 --- a/controller/handler_ctrl/accept.go +++ b/controller/handler_ctrl/accept.go @@ -87,7 +87,7 @@ func (self *CtrlAccepter) Bind(binding channel.Binding) error { } r.Listeners = nil - if val, found := ch.Underlay().Headers()[int32(ctrl_pb.ContentType_ListenersHeader)]; found { + if val, found := ch.Underlay().Headers()[int32(ctrl_pb.ControlHeaders_ListenersHeader)]; found { listeners := &ctrl_pb.Listeners{} if err = proto.Unmarshal(val, listeners); err != nil { log.WithError(err).Error("unable to unmarshall listeners value") @@ -104,7 +104,7 @@ func (self *CtrlAccepter) Bind(binding channel.Binding) error { log.Debug("no advertised listeners") } - if val, found := ch.Underlay().Headers()[int32(ctrl_pb.ContentType_RouterMetadataHeader)]; found { + if val, found := ch.Underlay().Headers()[int32(ctrl_pb.ControlHeaders_RouterMetadataHeader)]; found { routerMetadata := &ctrl_pb.RouterMetadata{} if err = proto.Unmarshal(val, routerMetadata); err != nil { log.WithError(err).Error("unable to unmarshall router metadata value") diff --git a/controller/handler_ctrl/circuit_confirmation.go b/controller/handler_ctrl/circuit_confirmation.go index 407cff396..13ca3a711 100644 --- a/controller/handler_ctrl/circuit_confirmation.go +++ b/controller/handler_ctrl/circuit_confirmation.go @@ -87,7 +87,7 @@ func (self *circuitConfirmationHandler) checkCircuitMaxIdle(circuit *network.Cir return } - log.Infof("removing idle circuit, idle time of %s exceedes max idle time of %s", + log.Infof("removing idle circuit, idle time of %s exceeds max idle time of %s", time.Duration(idleTime).String(), service.MaxIdleTime.String()) if err := self.n.RemoveCircuit(circuit.Id, true); err != nil { diff --git a/controller/handler_ctrl/fault.go b/controller/handler_ctrl/fault.go index 18333b460..ab040c946 100644 --- a/controller/handler_ctrl/fault.go +++ b/controller/handler_ctrl/fault.go @@ -21,9 +21,9 @@ import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" "github.com/openziti/channel/v2/protobufs" + "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/controller/event" "github.com/openziti/ziti/controller/network" - "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/sirupsen/logrus" "google.golang.org/protobuf/proto" "strings" @@ -55,7 +55,7 @@ func (h *faultHandler) HandleReceive(msg *channel.Message, ch channel.Channel) { } func (h *faultHandler) handleFault(_ *channel.Message, ch channel.Channel, fault *ctrl_pb.Fault) { - log := pfxlog.ContextLogger(ch.Label()).Entry + log := pfxlog.ContextLogger(ch.Label()).WithField("routerId", h.r.Id) switch fault.Subject { case ctrl_pb.FaultSubject_LinkFault: @@ -110,17 +110,25 @@ func (h *faultHandler) handleFault(_ *channel.Message, ch channel.Channel, fault func (h *faultHandler) handleFaultedLink(log *logrus.Entry, fault *ctrl_pb.Fault) { linkId := fault.Id + log = log.WithField("linkId", linkId).WithField("fault.iteration", fault.Iteration) + if link, found := h.network.GetLink(linkId); found { - log = log.WithField("linkId", linkId) + log = log.WithField("link.iteration", link.Iteration) + + if fault.Iteration != 0 && link.Iteration != 0 && fault.Iteration < link.Iteration { + log.Info("fault reported, but iteration is older than current link, ignoring") + return + } + wasConnected := link.IsUsable() - if err := h.network.LinkFaulted(linkId, fault.Subject == ctrl_pb.FaultSubject_LinkDuplicate); err == nil { + if err := h.network.LinkFaulted(link, fault.Subject == ctrl_pb.FaultSubject_LinkDuplicate); err == nil { h.network.LinkChanged(link) otherRouter := link.Src if link.Src.Id == h.r.Id { - otherRouter = link.Dst + otherRouter = link.GetDest() } - if wasConnected { + if wasConnected && otherRouter != nil { fault.Subject = ctrl_pb.FaultSubject_LinkFault if ctrl := otherRouter.Control; ctrl != nil && otherRouter.Connected.Load() { if err := protobufs.MarshalTyped(fault).Send(ctrl); err != nil { @@ -135,7 +143,7 @@ func (h *faultHandler) handleFaultedLink(log *logrus.Entry, fault *ctrl_pb.Fault log.WithError(err).Error("error handling link fault") } } else { + log.Info("link fault for unknown link") h.network.NotifyLinkIdEvent(linkId, event.LinkFault) } - } diff --git a/controller/handler_ctrl/router_link.go b/controller/handler_ctrl/router_link.go index 85b62e1e7..dc1bd71cc 100644 --- a/controller/handler_ctrl/router_link.go +++ b/controller/handler_ctrl/router_link.go @@ -19,8 +19,8 @@ package handler_ctrl import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" - "github.com/openziti/ziti/controller/network" "github.com/openziti/ziti/common/pb/ctrl_pb" + "github.com/openziti/ziti/controller/network" "google.golang.org/protobuf/proto" ) @@ -46,23 +46,11 @@ func (h *routerLinkHandler) HandleReceive(msg *channel.Message, ch channel.Chann return } - go h.HandleLinks(ch, link) + go h.HandleLinks(link) } -func (h *routerLinkHandler) HandleLinks(ch channel.Channel, links *ctrl_pb.RouterLinks) { - log := pfxlog.ContextLogger(ch.Label()).WithField("routerId", ch.Id()) - +func (h *routerLinkHandler) HandleLinks(links *ctrl_pb.RouterLinks) { for _, link := range links.Links { - linkLog := log.WithField("linkId", link.Id). - WithField("destRouterId", link.DestRouterId) - - created, err := h.network.NotifyExistingLink(link.Id, link.LinkProtocol, link.DialAddress, h.r, link.DestRouterId) - if err != nil { - linkLog.WithError(err).Error("unexpected error adding router reported link") - } else if created { - linkLog.Info("router reported link added") - } else { - linkLog.Info("router reported link already known") - } + h.network.NotifyExistingLink(link.Id, link.Iteration, link.LinkProtocol, link.DialAddress, h.r, link.DestRouterId) } } diff --git a/controller/handler_edge_ctrl/common.go b/controller/handler_edge_ctrl/common.go index 3b82dd831..ea93243f4 100644 --- a/controller/handler_edge_ctrl/common.go +++ b/controller/handler_edge_ctrl/common.go @@ -10,16 +10,16 @@ import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" - "github.com/openziti/ziti/controller/env" - "github.com/openziti/ziti/controller/model" - "github.com/openziti/ziti/controller/db" - "github.com/openziti/ziti/controller/network" - "github.com/openziti/ziti/controller/xt" - "github.com/openziti/ziti/common/logcontext" "github.com/openziti/foundation/v2/stringz" "github.com/openziti/identity" "github.com/openziti/sdk-golang/ziti/edge" "github.com/openziti/storage/boltz" + "github.com/openziti/ziti/common/logcontext" + "github.com/openziti/ziti/controller/db" + "github.com/openziti/ziti/controller/env" + "github.com/openziti/ziti/controller/model" + "github.com/openziti/ziti/controller/network" + "github.com/openziti/ziti/controller/xt" "github.com/sirupsen/logrus" ) @@ -367,6 +367,14 @@ func (self *baseSessionRequestContext) verifyTerminator(terminatorId string, bin return nil } +func (self *baseSessionRequestContext) verifyTerminatorId(id string) { + if self.err == nil { + if id == "" { + self.err = invalidTerminator("provided terminator id is blank") + } + } +} + func (self *baseSessionRequestContext) updateTerminator(terminator *network.Terminator, request UpdateTerminatorRequest, ctx *change.Context) { if self.err == nil { checker := fields.UpdatedFieldsMap{} diff --git a/controller/handler_edge_ctrl/create_terminator_v2.go b/controller/handler_edge_ctrl/create_terminator_v2.go index be396e450..119ef87e1 100644 --- a/controller/handler_edge_ctrl/create_terminator_v2.go +++ b/controller/handler_edge_ctrl/create_terminator_v2.go @@ -80,6 +80,7 @@ func (self *createTerminatorV2Handler) CreateTerminatorV2(ctx *CreateTerminatorV if !ctx.loadRouter() { return } + ctx.verifyTerminatorId(ctx.req.Address) ctx.loadSession(ctx.req.SessionToken) ctx.checkSessionType(db.SessionTypeBind) ctx.checkSessionFingerprints(ctx.req.Fingerprints) diff --git a/controller/handler_mgmt/bind.go b/controller/handler_mgmt/bind.go index 251f09d77..a8a1b9539 100644 --- a/controller/handler_mgmt/bind.go +++ b/controller/handler_mgmt/bind.go @@ -45,6 +45,12 @@ func (bindHandler *BindHandler) BindChannel(binding channel.Binding) error { Handler: validateTerminatorsRequestHandler.HandleReceive, }) + validateLinksRequestHandler := newValidateRouterLinksHandler(bindHandler.network) + binding.AddTypedReceiveHandler(&channel.AsyncFunctionReceiveAdapter{ + Type: validateLinksRequestHandler.ContentType(), + Handler: validateLinksRequestHandler.HandleReceive, + }) + tracesHandler := newStreamTracesHandler(bindHandler.network) binding.AddTypedReceiveHandler(tracesHandler) binding.AddCloseHandler(tracesHandler) diff --git a/controller/handler_mgmt/stream_toggle_pipe_traces.go b/controller/handler_mgmt/stream_toggle_pipe_traces.go index 682f6abb3..d8dda7799 100644 --- a/controller/handler_mgmt/stream_toggle_pipe_traces.go +++ b/controller/handler_mgmt/stream_toggle_pipe_traces.go @@ -18,16 +18,17 @@ package handler_mgmt import ( "fmt" + "sync" + "time" + "github.com/openziti/channel/v2" - "github.com/openziti/channel/v2/trace/pb" + trace_pb "github.com/openziti/channel/v2/trace/pb" "github.com/openziti/ziti/common/handler_common" "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/common/pb/mgmt_pb" - "github.com/openziti/ziti/controller/network" "github.com/openziti/ziti/common/trace" + "github.com/openziti/ziti/controller/network" "google.golang.org/protobuf/proto" - "sync" - "time" ) type traceTogglePipeHandler struct { @@ -124,7 +125,7 @@ func checkMatch(appId string, matchers *trace.PipeToggleMatchers, verbosity trac } func getApplyResults(resultChan chan trace.ToggleApplyResult, verbosity trace.ToggleVerbosity, result *trace.ToggleResult) { - timout := time.After(time.Second * 5) + timeout := time.After(time.Second * 5) for { select { case applyResult, chanOpen := <-resultChan: @@ -132,7 +133,7 @@ func getApplyResults(resultChan chan trace.ToggleApplyResult, verbosity trace.To return } applyResult.Append(result, verbosity) - case <-timout: + case <-timeout: result.Success = false result.Append("Timed out waiting for toggle to be applied to controller") return diff --git a/controller/handler_mgmt/validate_router_links.go b/controller/handler_mgmt/validate_router_links.go new file mode 100644 index 000000000..22c6914e3 --- /dev/null +++ b/controller/handler_mgmt/validate_router_links.go @@ -0,0 +1,88 @@ +/* + 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 handler_mgmt + +import ( + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/channel/v2" + "github.com/openziti/channel/v2/protobufs" + "github.com/openziti/ziti/common/pb/mgmt_pb" + "github.com/openziti/ziti/controller/network" + "google.golang.org/protobuf/proto" + "time" +) + +type validateRouterLinksHandler struct { + network *network.Network +} + +func newValidateRouterLinksHandler(network *network.Network) *validateRouterLinksHandler { + return &validateRouterLinksHandler{network: network} +} + +func (*validateRouterLinksHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_ValidateRouterLinksRequestType) +} + +func (handler *validateRouterLinksHandler) HandleReceive(msg *channel.Message, ch channel.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + request := &mgmt_pb.ValidateRouterLinksRequest{} + + var err error + + var count int64 + var evalF func() + if err = proto.Unmarshal(msg.Body, request); err == nil { + count, evalF, err = handler.network.ValidateLinks(request.Filter, func(detail *mgmt_pb.RouterLinkDetails) { + if !ch.IsClosed() { + if sendErr := protobufs.MarshalTyped(detail).WithTimeout(15 * time.Second).SendAndWaitForWire(ch); sendErr != nil { + log.WithError(sendErr).Error("send of link detail failed, closing channel") + if closeErr := ch.Close(); closeErr != nil { + log.WithError(closeErr).Error("failed to close channel") + } + } + } else { + log.Info("channel closed, unable to send link detail") + } + }) + } + + response := &mgmt_pb.ValidateRouterLinksResponse{ + Success: err == nil, + RouterCount: uint64(count), + } + if err != nil { + response.Message = fmt.Sprintf("%v: failed to unmarshall request: %v", handler.network.GetAppId(), err) + } + + body, err := proto.Marshal(response) + if err != nil { + pfxlog.Logger().WithError(err).Error("unexpected error serializing ValidateRouterLinksResponse") + return + } + + responseMsg := channel.NewMessage(int32(mgmt_pb.ContentType_ValidateRouterLinksResponseType), body) + responseMsg.ReplyTo(msg) + if err = ch.Send(responseMsg); err != nil { + pfxlog.Logger().WithError(err).Error("unexpected error sending ValidateRouterLinksResponse") + } + + if evalF != nil { + evalF() + } +} diff --git a/controller/internal/routes/authenticate_router.go b/controller/internal/routes/authenticate_router.go index 6be058eca..3dcdee71a 100644 --- a/controller/internal/routes/authenticate_router.go +++ b/controller/internal/routes/authenticate_router.go @@ -24,13 +24,14 @@ import ( clientApiAuthentication "github.com/openziti/edge-api/rest_client_api_server/operations/authentication" managementApiAuthentication "github.com/openziti/edge-api/rest_management_api_server/operations/authentication" "github.com/openziti/edge-api/rest_model" + "github.com/openziti/foundation/v2/concurrenz" + "github.com/openziti/foundation/v2/errorz" + "github.com/openziti/metrics" + "github.com/openziti/ziti/controller/apierror" "github.com/openziti/ziti/controller/env" "github.com/openziti/ziti/controller/internal/permissions" "github.com/openziti/ziti/controller/model" "github.com/openziti/ziti/controller/response" - "github.com/openziti/ziti/controller/apierror" - "github.com/openziti/foundation/v2/errorz" - "github.com/openziti/metrics" "net" "net/http" "time" @@ -178,13 +179,21 @@ func (ro *AuthRouter) authHandler(ae *env.AppEnv, rc *response.RequestContext, h sessionCerts = append(sessionCerts, sessionCert) } - sessionId, err := ae.Managers.ApiSession.Create(changeCtx.NewMutateContext(), newApiSession, sessionCerts) + var sessionIdHolder concurrenz.AtomicValue[string] + + ctrl, err := ae.AuthRateLimiter.RunRateLimited(func() error { + sessionId, err := ae.Managers.ApiSession.Create(changeCtx.NewMutateContext(), newApiSession, sessionCerts) + sessionIdHolder.Store(sessionId) + return err + }) if err != nil { rc.RespondWithError(err) return } + sessionId := sessionIdHolder.Load() + filledApiSession, err := ae.Managers.ApiSession.Read(sessionId) if err != nil { @@ -210,7 +219,12 @@ func (ro *AuthRouter) authHandler(ae *env.AppEnv, rc *response.RequestContext, h ro.createTimer.UpdateSince(start) - rc.Respond(envelope, http.StatusOK) + writeOk := rc.RespondWithProducer(rc.GetProducer(), envelope, http.StatusOK) + if writeOk { + ctrl.Success() + } else { + ctrl.Timeout() + } } func (ro *AuthRouter) authMfa(ae *env.AppEnv, rc *response.RequestContext, mfaCode *rest_model.MfaCode) { diff --git a/controller/internal/routes/ca_router.go b/controller/internal/routes/ca_router.go index fa876d109..42fb0a454 100644 --- a/controller/internal/routes/ca_router.go +++ b/controller/internal/routes/ca_router.go @@ -20,20 +20,21 @@ import ( "crypto/x509" "encoding/pem" "fmt" + "net/http" + "github.com/go-openapi/runtime/middleware" "github.com/golang-jwt/jwt/v5" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_management_api_server/operations/certificate_authority" + "github.com/openziti/sdk-golang/ziti" + "github.com/openziti/storage/boltz" "github.com/openziti/ziti/controller/apierror" "github.com/openziti/ziti/controller/env" + "github.com/openziti/ziti/controller/fields" "github.com/openziti/ziti/controller/internal/permissions" "github.com/openziti/ziti/controller/model" "github.com/openziti/ziti/controller/response" - "github.com/openziti/ziti/controller/fields" - "github.com/openziti/sdk-golang/ziti" - "github.com/openziti/storage/boltz" "github.com/pkg/errors" - "net/http" ) func init() { @@ -176,7 +177,7 @@ func (r *CaRouter) VerifyCert(ae *env.AppEnv, rc *response.RequestContext, param if der.Type != "CERTIFICATE" { apiErr := apierror.NewExpectedPemBlockCertificate() - apiErr.Cause = fmt.Errorf("ecountered PEM block type %s", der.Type) + apiErr.Cause = fmt.Errorf("encountered PEM block type %s", der.Type) rc.RespondWithApiError(apiErr) return } diff --git a/controller/internal/routes/posture_data_api_model.go b/controller/internal/routes/posture_data_api_model.go index 344891b43..26f0ce298 100644 --- a/controller/internal/routes/posture_data_api_model.go +++ b/controller/internal/routes/posture_data_api_model.go @@ -17,12 +17,13 @@ package routes import ( + "time" + "github.com/go-openapi/strfmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" "github.com/openziti/ziti/controller/env" "github.com/openziti/ziti/controller/model" - "time" ) func MapPostureDataToRestModel(_ *env.AppEnv, postureData *model.PostureData) *rest_model.PostureData { @@ -54,7 +55,7 @@ func MapPostureDataProcessesToRestModel(postureData *model.PostureData) []*rest_ process.SignerFingerprints = pdProcess.SignerFingerprints process.BinaryHash = pdProcess.BinaryHash } else { - pfxlog.Logger().Errorf("could not convery posture data process (%s) to subtype, got %T", genericProcess.PostureCheckId, genericProcess.SubType) + pfxlog.Logger().Errorf("could not convert posture data process (%s) to subtype, got %T", genericProcess.PostureCheckId, genericProcess.SubType) } processes = append(processes, process) @@ -75,7 +76,7 @@ func MapPostureDataDomainToRestModel(domain *model.PostureResponseDomain) *rest_ if pdDomain, ok := domain.SubType.(*model.PostureResponseDomain); ok { ret.Domain = &pdDomain.Name } else { - pfxlog.Logger().Errorf("could not convery posture data domain to subtype, got %T", domain.SubType) + pfxlog.Logger().Errorf("could not convert posture data domain to subtype, got %T", domain.SubType) } return ret @@ -93,7 +94,7 @@ func MapPostureDataMacToRestModel(mac *model.PostureResponseMac) *rest_model.Pos if pdMac, ok := mac.SubType.(*model.PostureResponseMac); ok { ret.Addresses = pdMac.Addresses } else { - pfxlog.Logger().Errorf("could not convery posture data mac to subtype, got %T", mac.SubType) + pfxlog.Logger().Errorf("could not convert posture data mac to subtype, got %T", mac.SubType) } return ret @@ -112,7 +113,7 @@ func MapPostureDataOsToRestModel(os *model.PostureResponseOs) *rest_model.Postur ret.Type = &pdOs.Type ret.Version = &pdOs.Version } else { - pfxlog.Logger().Errorf("could not convery posture data mac to subtype, got %T", os.SubType) + pfxlog.Logger().Errorf("could not convert posture data mac to subtype, got %T", os.SubType) } return ret diff --git a/controller/ioc/registry.go b/controller/ioc/registry.go index 09212d60f..b1b2326cb 100644 --- a/controller/ioc/registry.go +++ b/controller/ioc/registry.go @@ -30,7 +30,7 @@ type Provider interface { Get() any } -// ProviderF is a function implemenation of the Provider interface +// ProviderF is a function implementation of the Provider interface type ProviderF func() any func (f ProviderF) Get() any { diff --git a/controller/model/api_session_manager.go b/controller/model/api_session_manager.go index 61f6378e7..6469240e9 100644 --- a/controller/model/api_session_manager.go +++ b/controller/model/api_session_manager.go @@ -18,6 +18,8 @@ package model import ( "fmt" + "time" + "github.com/lucsky/cuid" "github.com/michaelquigley/pfxlog" "github.com/openziti/storage/ast" @@ -27,7 +29,6 @@ import ( "github.com/openziti/ziti/controller/models" "github.com/pkg/errors" "go.etcd.io/bbolt" - "time" ) func NewApiSessionManager(env Env) *ApiSessionManager { @@ -210,7 +211,7 @@ func (self *ApiSessionManager) Stream(query string, collect func(*ApiSession, er filter, err := ast.Parse(self.Store, query) if err != nil { - return fmt.Errorf("could not parse query for streaming api sesions: %v", err) + return fmt.Errorf("could not parse query for streaming api sessions: %v", err) } return self.env.GetDbProvider().GetDb().View(func(tx *bbolt.Tx) error { @@ -230,7 +231,7 @@ func (self *ApiSessionManager) StreamIds(query string, collect func(string, erro filter, err := ast.Parse(self.Store, query) if err != nil { - return fmt.Errorf("could not parse query for streaming api sesions ids: %v", err) + return fmt.Errorf("could not parse query for streaming api sessions ids: %v", err) } return self.env.GetDbProvider().GetDb().View(func(tx *bbolt.Tx) error { diff --git a/controller/model/posture_check_model_mac.go b/controller/model/posture_check_model_mac.go index 287a2f8b0..d3cbc65c9 100644 --- a/controller/model/posture_check_model_mac.go +++ b/controller/model/posture_check_model_mac.go @@ -18,11 +18,12 @@ package model import ( "fmt" + "time" + "github.com/openziti/ziti/common/pb/edge_cmd_pb" "github.com/openziti/ziti/controller/db" "github.com/pkg/errors" "go.etcd.io/bbolt" - "time" ) var _ PostureCheckSubType = &PostureCheckMacAddresses{} @@ -100,7 +101,7 @@ func (p *PostureCheckMacAddresses) fillFrom(_ Env, tx *bbolt.Tx, check *db.Postu subCheck := subType.(*db.PostureCheckMacAddresses) if subCheck == nil { - return fmt.Errorf("could not covert mac address check to bolt type") + return fmt.Errorf("could not convert mac address check to bolt type") } p.MacAddresses = subCheck.MacAddresses diff --git a/controller/model/posture_check_model_mfa.go b/controller/model/posture_check_model_mfa.go index 69ed9a36c..1911099aa 100644 --- a/controller/model/posture_check_model_mfa.go +++ b/controller/model/posture_check_model_mfa.go @@ -18,12 +18,13 @@ package model import ( "fmt" + "time" + "github.com/blang/semver" "github.com/openziti/ziti/common/pb/edge_cmd_pb" "github.com/openziti/ziti/controller/db" "github.com/pkg/errors" "go.etcd.io/bbolt" - "time" ) var _ PostureCheckSubType = &PostureCheckMfa{} @@ -320,7 +321,7 @@ func (p *PostureCheckMfa) fillFrom(_ Env, tx *bbolt.Tx, check *db.PostureCheck, subCheck := subType.(*db.PostureCheckMfa) if subCheck == nil { - return fmt.Errorf("could not covert mfa check to bolt type") + return fmt.Errorf("could not convert mfa check to bolt type") } p.TimeoutSeconds = subCheck.TimeoutSeconds diff --git a/controller/model/posture_check_model_os.go b/controller/model/posture_check_model_os.go index 0dc25cddc..1832fbc27 100644 --- a/controller/model/posture_check_model_os.go +++ b/controller/model/posture_check_model_os.go @@ -18,6 +18,9 @@ package model import ( "fmt" + "strings" + "time" + "github.com/blang/semver" "github.com/michaelquigley/pfxlog" "github.com/openziti/foundation/v2/errorz" @@ -25,8 +28,6 @@ import ( "github.com/openziti/ziti/controller/db" "github.com/pkg/errors" "go.etcd.io/bbolt" - "strings" - "time" ) var _ PostureCheckSubType = &PostureCheckOperatingSystem{} @@ -152,7 +153,7 @@ func (p *PostureCheckOperatingSystem) fillFrom(_ Env, tx *bbolt.Tx, check *db.Po subCheck := subType.(*db.PostureCheckOperatingSystem) if subCheck == nil { - return fmt.Errorf("could not covert os check to bolt type") + return fmt.Errorf("could not convert os check to bolt type") } for _, osMatch := range subCheck.OperatingSystems { diff --git a/controller/model/posture_check_model_os_test.go b/controller/model/posture_check_model_os_test.go index 03892b062..4952eaff8 100644 --- a/controller/model/posture_check_model_os_test.go +++ b/controller/model/posture_check_model_os_test.go @@ -17,9 +17,10 @@ package model import ( - "github.com/stretchr/testify/require" "testing" "time" + + "github.com/stretchr/testify/require" ) func TestPostureCheckModelOs_Evaluate(t *testing.T) { @@ -33,7 +34,7 @@ func TestPostureCheckModelOs_Evaluate(t *testing.T) { req.True(result) }) - t.Run("returns true for valid os type and is higer than the min and lower than max", func(t *testing.T) { + t.Run("returns true for valid os type and is higher than the min and lower than max", func(t *testing.T) { osCheck, postureData := newMatchingOsCheckAndData() osCheck.OperatingSystems[0].OsVersions[0] = ">=10.5.0 <=10.6.0" @@ -43,7 +44,6 @@ func TestPostureCheckModelOs_Evaluate(t *testing.T) { req.True(result) }) - t.Run("returns true for valid os type and is the min and lower than max", func(t *testing.T) { osCheck, postureData := newMatchingOsCheckAndData() osCheck.OperatingSystems[0].OsVersions[0] = ">=10.5.19041 <=10.6.0" @@ -54,7 +54,7 @@ func TestPostureCheckModelOs_Evaluate(t *testing.T) { req.True(result) }) - t.Run("returns true for valid os type and higer than min and is the max", func(t *testing.T) { + t.Run("returns true for valid os type and higher than min and is the max", func(t *testing.T) { osCheck, postureData := newMatchingOsCheckAndData() osCheck.OperatingSystems[0].OsVersions[0] = ">=10.0.0 <=10.5.19041" @@ -64,7 +64,6 @@ func TestPostureCheckModelOs_Evaluate(t *testing.T) { req.True(result) }) - t.Run("returns false for valid os type and lower than min", func(t *testing.T) { osCheck, postureData := newMatchingOsCheckAndData() osCheck.OperatingSystems[0].OsVersions[0] = ">=10.8.0 <=10.9.0" @@ -335,7 +334,7 @@ func newMatchingOsCheckAndData() (*PostureCheckOperatingSystem, *PostureData) { postureResponseOs.PostureResponse = postureResponse validPostureData := &PostureData{ - Os: *postureResponseOs, + Os: *postureResponseOs, } processCheck := &PostureCheckOperatingSystem{ diff --git a/controller/model/posture_check_model_process.go b/controller/model/posture_check_model_process.go index c9e3b8b90..5e475c226 100644 --- a/controller/model/posture_check_model_process.go +++ b/controller/model/posture_check_model_process.go @@ -18,12 +18,13 @@ package model import ( "fmt" + "strings" + "time" + "github.com/openziti/ziti/common/pb/edge_cmd_pb" "github.com/openziti/ziti/controller/db" "github.com/pkg/errors" "go.etcd.io/bbolt" - "strings" - "time" ) var _ PostureCheckSubType = &PostureCheckProcess{} @@ -152,7 +153,7 @@ func (p *PostureCheckProcess) fillFrom(_ Env, tx *bbolt.Tx, check *db.PostureChe subCheck := subType.(*db.PostureCheckProcess) if subCheck == nil { - return fmt.Errorf("could not covert process check to bolt type") + return fmt.Errorf("could not convert process check to bolt type") } p.PostureCheckId = check.Id diff --git a/controller/model/posture_check_model_process_multi.go b/controller/model/posture_check_model_process_multi.go index 1f2881dca..71aacf52d 100644 --- a/controller/model/posture_check_model_process_multi.go +++ b/controller/model/posture_check_model_process_multi.go @@ -19,12 +19,13 @@ package model import ( "fmt" + "time" + "github.com/michaelquigley/pfxlog" "github.com/openziti/ziti/common/pb/edge_cmd_pb" "github.com/openziti/ziti/controller/db" "github.com/pkg/errors" "go.etcd.io/bbolt" - "time" ) var _ PostureCheckSubType = &PostureCheckProcessMulti{} @@ -188,7 +189,7 @@ func (p *PostureCheckProcessMulti) fillFrom(_ Env, _ *bbolt.Tx, check *db.Postur subCheck := subType.(*db.PostureCheckProcessMulti) if subCheck == nil { - return fmt.Errorf("could not covert process check process multi to bolt type") + return fmt.Errorf("could not convert process check process multi to bolt type") } p.PostureCheckId = check.Id diff --git a/controller/model/posture_check_model_windows_domain.go b/controller/model/posture_check_model_windows_domain.go index 4ea1b5342..5ab8585a0 100644 --- a/controller/model/posture_check_model_windows_domain.go +++ b/controller/model/posture_check_model_windows_domain.go @@ -18,12 +18,13 @@ package model import ( "fmt" + "strings" + "time" + "github.com/openziti/ziti/common/pb/edge_cmd_pb" "github.com/openziti/ziti/controller/db" "github.com/pkg/errors" "go.etcd.io/bbolt" - "strings" - "time" ) var _ PostureCheckSubType = &PostureCheckDomains{} @@ -106,7 +107,7 @@ func (p *PostureCheckDomains) fillFrom(_ Env, _ *bbolt.Tx, _ *db.PostureCheck, s subCheck := subType.(*db.PostureCheckWindowsDomains) if subCheck == nil { - return fmt.Errorf("could not covert domain check to bolt type") + return fmt.Errorf("could not convert domain check to bolt type") } p.Domains = subCheck.Domains diff --git a/controller/network/assembly.go b/controller/network/assembly.go index f171b9e14..0a8bf5213 100644 --- a/controller/network/assembly.go +++ b/controller/network/assembly.go @@ -19,9 +19,9 @@ package network import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2/protobufs" - "github.com/openziti/ziti/controller/event" - "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/foundation/v2/info" + "github.com/openziti/ziti/common/pb/ctrl_pb" + "github.com/openziti/ziti/controller/event" "time" ) @@ -43,23 +43,23 @@ func (network *Network) assemble() { dial := &ctrl_pb.Dial{ LinkId: missingLink.Id, Address: missingLink.DialAddress, - RouterId: missingLink.Dst.Id, + RouterId: missingLink.DstId, LinkProtocol: missingLink.Protocol, } - if versionInfo := missingLink.Dst.VersionInfo; versionInfo != nil { - dial.RouterVersion = missingLink.Dst.VersionInfo.Version + if versionInfo := missingLink.GetDest().VersionInfo; versionInfo != nil { + dial.RouterVersion = missingLink.GetDest().VersionInfo.Version } if err = protobufs.MarshalTyped(dial).Send(missingLink.Src.Control); err != nil { log.WithField("linkId", missingLink.Id). WithField("srcRouterId", missingLink.Src.Id). - WithField("dstRouterId", missingLink.Dst.Id). + WithField("dstRouterId", missingLink.DstId). WithError(err).Error("unexpected error sending dial") } else { log.WithField("linkId", missingLink.Id). WithField("srcRouterId", missingLink.Src.Id). - WithField("dstRouterId", missingLink.Dst.Id). + WithField("dstRouterId", missingLink.DstId). Info("sending link dial") network.NotifyLinkEvent(missingLink, event.LinkDialed) } @@ -79,7 +79,7 @@ func (network *Network) NotifyLinkEvent(link *Link, eventType event.LinkEventTyp Timestamp: time.Now(), LinkId: link.Id, SrcRouterId: link.Src.Id, - DstRouterId: link.Dst.Id, + DstRouterId: link.DstId, Protocol: link.Protocol, Cost: link.GetStaticCost(), DialAddress: link.DialAddress, @@ -94,7 +94,7 @@ func (network *Network) NotifyLinkConnected(link *Link, msg *ctrl_pb.LinkConnect Timestamp: time.Now(), LinkId: link.Id, SrcRouterId: link.Src.Id, - DstRouterId: link.Dst.Id, + DstRouterId: link.DstId, Protocol: link.Protocol, Cost: link.GetStaticCost(), DialAddress: link.DialAddress, diff --git a/controller/network/link.go b/controller/network/link.go index ec25a40e5..db56db3dd 100644 --- a/controller/network/link.go +++ b/controller/network/link.go @@ -17,6 +17,7 @@ package network import ( + "github.com/openziti/foundation/v2/concurrenz" "github.com/openziti/foundation/v2/info" "sync" "sync/atomic" @@ -28,8 +29,10 @@ type Link struct { DstLatency int64 Cost int64 Id string + Iteration uint32 Src *Router - Dst *Router + DstId string + Dst concurrenz.AtomicValue[*Router] Protocol string DialAddress string state []*LinkState @@ -59,6 +62,10 @@ func (link *Link) GetId() string { return link.Id } +func (link *Link) GetDest() *Router { + return link.Dst.Load() +} + func (link *Link) CurrentState() *LinkState { link.lock.Lock() defer link.lock.Unlock() diff --git a/controller/network/link_controller.go b/controller/network/link_controller.go index c6dccc813..599680fe2 100644 --- a/controller/network/link_controller.go +++ b/controller/network/link_controller.go @@ -17,12 +17,19 @@ package network import ( + "encoding/json" + "errors" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/channel/v2/protobufs" "github.com/openziti/foundation/v2/info" "github.com/openziti/storage/objectz" + "github.com/openziti/ziti/common/inspect" "github.com/openziti/ziti/common/pb/ctrl_pb" + "github.com/openziti/ziti/common/pb/mgmt_pb" "github.com/openziti/ziti/controller/idgen" "github.com/orcaman/concurrent-map/v2" "math" + "strings" "sync" "time" ) @@ -64,7 +71,7 @@ func newLinkController(options *Options) *linkController { return &entity.Src.Id }) result.store.AddStringSymbol("destRouter", func(entity *Link) *string { - return &entity.Dst.Id + return &entity.DstId }) result.store.AddInt64Symbol("cost", func(entity *Link) *int64 { val := entity.GetCost() @@ -89,31 +96,62 @@ func newLinkController(options *Options) *linkController { } return nil }) + result.store.AddInt64Symbol("iteration", func(entity *Link) *int64 { + val := int64(entity.Iteration) + return &val + }) return result } +func (linkController *linkController) buildRouterLinks(router *Router) { + for entry := range linkController.linkTable.links.IterBuffered() { + link := entry.Val + if link.DstId == router.Id { + router.routerLinks.Add(link, link.Src.Id) + link.Dst.Store(router) + } + } +} + func (linkController *linkController) add(link *Link) { linkController.linkTable.add(link) - link.Src.routerLinks.Add(link, link.Dst) - link.Dst.routerLinks.Add(link, link.Src) + link.Src.routerLinks.Add(link, link.DstId) + if dest := link.GetDest(); dest != nil { + dest.routerLinks.Add(link, link.Src.Id) + } } func (linkController *linkController) has(link *Link) bool { return linkController.linkTable.has(link) } -func (linkController *linkController) routerReportedLink(linkId, linkProtocol, dialAddress string, src, dst *Router) (*Link, bool) { +func (linkController *linkController) routerReportedLink(linkId string, iteration uint32, linkProtocol, dialAddress string, src, dst *Router, dstId string) (*Link, bool) { linkController.lock.Lock() defer linkController.lock.Unlock() - if link, found := linkController.get(linkId); found { + link, _ := linkController.get(linkId) + if link != nil && link.Iteration >= iteration { return link, false } - link := newLink(linkId, linkProtocol, dialAddress, linkController.initialLatency) + // remove the older link before adding the new one + if link != nil { + log := pfxlog.Logger(). + WithField("routerId", src.Id). + WithField("linkId", linkId). + WithField("destRouterId", dstId). + WithField("iteration", iteration) + + linkController.remove(link) + log.Infof("replaced link with newer iteration %v => %v", link.Iteration, iteration) + } + + link = newLink(linkId, linkProtocol, dialAddress, linkController.initialLatency) + link.Iteration = iteration link.Src = src - link.Dst = dst + link.Dst.Store(dst) + link.DstId = dstId link.addState(newLinkState(Connected)) linkController.add(link) return link, true @@ -128,9 +166,12 @@ func (linkController *linkController) all() []*Link { } func (linkController *linkController) remove(link *Link) { - linkController.linkTable.remove(link) - link.Src.routerLinks.Remove(link, link.Dst) - link.Dst.routerLinks.Remove(link, link.Src) + if linkController.linkTable.remove(link) { + link.Src.routerLinks.Remove(link, link.DstId) + if dest := link.GetDest(); dest != nil { + dest.routerLinks.Remove(link, link.Src.Id) + } + } } func (linkController *linkController) connectedNeighborsOfRouter(router *Router) []*Router { @@ -138,12 +179,13 @@ func (linkController *linkController) connectedNeighborsOfRouter(router *Router) links := router.routerLinks.GetLinks() for _, link := range links { - if link.IsUsable() { - if link.Src != router { + dstRouter := link.GetDest() + if dstRouter != nil && dstRouter.Connected.Load() && link.IsUsable() { + if link.Src.Id != router.Id { neighborMap[link.Src.Id] = link.Src } - if link.Dst != router { - neighborMap[link.Dst.Id] = link.Dst + if link.DstId != router.Id { + neighborMap[link.DstId] = dstRouter } } } @@ -164,7 +206,7 @@ func (linkController *linkController) leastExpensiveLink(a, b *Router) (*Link, b for _, link := range links { if link.IsUsable() { linkCost := link.GetCost() - if link.Dst == b { + if link.DstId == b.Id { if linkCost < cost { selected = link cost = linkCost @@ -205,7 +247,8 @@ func (linkController *linkController) missingLinks(routers []*Router, pendingTim id := idgen.NewUUIDString() link := newLink(id, listener.GetProtocol(), listener.GetAddress(), linkController.initialLatency) link.Src = srcR - link.Dst = dstR + link.Dst.Store(dstR) + link.DstId = dstR.Id missingLinks = append(missingLinks, link) } } @@ -237,7 +280,7 @@ func (linkController *linkController) hasDirectedLink(a, b *Router, linkProtocol links := a.routerLinks.GetLinks() for _, link := range links { state := link.CurrentState() - if link.Src == a && link.Dst == b && state != nil && link.Protocol == linkProtocol { + if link.Src == a && link.DstId == b.Id && state != nil && link.Protocol == linkProtocol { if state.Mode == Connected || (state.Mode == Pending && state.Timestamp > pendingLimit) { return true } @@ -250,6 +293,104 @@ func (linkController *linkController) linksInMode(mode LinkMode) []*Link { return linkController.linkTable.allInMode(mode) } +func (self *linkController) ValidateRouterLinks(n *Network, router *Router, cb LinkValidationCallback) { + request := &ctrl_pb.InspectRequest{RequestedValues: []string{"links"}} + resp := &ctrl_pb.InspectResponse{} + respMsg, err := protobufs.MarshalTyped(request).WithTimeout(time.Minute).SendForReply(router.Control) + if err = protobufs.TypedResponse(resp).Unmarshall(respMsg, err); err != nil { + self.reportRouterLinksError(router, err, cb) + return + } + + var linkDetails *inspect.LinksInspectResult + for _, val := range resp.Values { + if val.Name == "links" { + if err = json.Unmarshal([]byte(val.Value), &linkDetails); err != nil { + self.reportRouterLinksError(router, err, cb) + return + } + } + } + + if linkDetails == nil { + if len(resp.Errors) > 0 { + err = errors.New(strings.Join(resp.Errors, ",")) + self.reportRouterLinksError(router, err, cb) + return + } + self.reportRouterLinksError(router, errors.New("no link details returned from router"), cb) + return + } + + linkMap := map[string]*Link{} + + for entry := range self.linkTable.links.IterBuffered() { + linkMap[entry.Key] = entry.Val + } + + result := &mgmt_pb.RouterLinkDetails{ + RouterId: router.Id, + RouterName: router.Name, + ValidateSuccess: true, + } + + for _, link := range linkDetails.Links { + detail := &mgmt_pb.RouterLinkDetail{ + LinkId: link.Id, + RouterState: mgmt_pb.LinkState_LinkEstablished, + DestRouterId: link.Dest, + Dialed: link.Dialed, + } + detail.DestConnected = n.ConnectedRouter(link.Dest) + if _, found := linkMap[link.Id]; found { + detail.CtrlState = mgmt_pb.LinkState_LinkEstablished + detail.IsValid = detail.DestConnected + } else { + detail.CtrlState = mgmt_pb.LinkState_LinkUnknown + detail.IsValid = !detail.DestConnected + } + delete(linkMap, link.Id) + result.LinkDetails = append(result.LinkDetails, detail) + } + + for _, link := range linkMap { + related := false + dest := "" + if link.Src.Id == router.Id { + related = true + dest = link.DstId + } else if link.DstId == router.Id { + related = true + dest = link.Src.Id + } + + if related { + detail := &mgmt_pb.RouterLinkDetail{ + LinkId: link.Id, + CtrlState: mgmt_pb.LinkState_LinkEstablished, + DestConnected: n.ConnectedRouter(dest), + RouterState: mgmt_pb.LinkState_LinkUnknown, + IsValid: false, + DestRouterId: dest, + Dialed: link.Src.Id == router.Id, + } + result.LinkDetails = append(result.LinkDetails, detail) + } + } + + cb(result) +} + +func (self *linkController) reportRouterLinksError(router *Router, err error, cb LinkValidationCallback) { + result := &mgmt_pb.RouterLinkDetails{ + RouterId: router.Id, + RouterName: router.Name, + ValidateSuccess: false, + Message: err.Error(), + } + cb(result) +} + /* * linkTable */ @@ -306,6 +447,8 @@ func (lt *linkTable) matching(f func(*Link) bool) []*Link { return links } -func (lt *linkTable) remove(link *Link) { - lt.links.Remove(link.Id) +func (lt *linkTable) remove(link *Link) bool { + return lt.links.RemoveCb(link.Id, func(key string, v *Link, exists bool) bool { + return v != nil && v.Iteration == link.Iteration + }) } diff --git a/controller/network/link_controller_test.go b/controller/network/link_controller_test.go index d0ebdeff5..2a91e91a5 100644 --- a/controller/network/link_controller_test.go +++ b/controller/network/link_controller_test.go @@ -44,10 +44,11 @@ func TestLifecycle(t *testing.T) { r0 := NewRouter("r0", "", "", 0, true) r1 := NewRouter("r1", "", "", 0, true) l0 := &Link{ - Id: "l0", - Src: r0, - Dst: r1, + Id: "l0", + Src: r0, + DstId: r1.Id, } + l0.Dst.Store(r1) linkController.add(l0) assert.True(t, linkController.has(l0)) @@ -75,11 +76,7 @@ func TestNeighbors(t *testing.T) { r0 := newRouterForTest("r0", "", nil, nil, 0, true) r1 := newRouterForTest("r1", "", nil, nil, 0, true) - l0 := &Link{ - Id: "l0", - Src: r0, - Dst: r1, - } + l0 := newTestLink("l0", r0, r1) l0.addState(newLinkState(Connected)) linkController.add(l0) @@ -88,6 +85,12 @@ func TestNeighbors(t *testing.T) { assert.Equal(t, r1, neighbors[0]) } -func newTestLink(id string, linkProtocol string) *Link { - return newLink(id, linkProtocol, "tcp:localhost:1234", 0) +func newTestLink(id string, src, dst *Router) *Link { + l := newLink(id, "tls", "tcp:localhost:1234", 0) + l.Src = src + l.DstId = dst.Id + l.Dst.Store(dst) + src.Connected.Store(true) + dst.Connected.Store(true) + return l } diff --git a/controller/network/network.go b/controller/network/network.go index 49bd937d1..2818fbc86 100644 --- a/controller/network/network.go +++ b/controller/network/network.go @@ -21,9 +21,11 @@ import ( "compress/gzip" "encoding/json" "fmt" + "github.com/openziti/foundation/v2/concurrenz" "github.com/openziti/foundation/v2/goroutines" "github.com/openziti/storage/objectz" fabricMetrics "github.com/openziti/ziti/common/metrics" + "github.com/openziti/ziti/common/pb/mgmt_pb" "github.com/openziti/ziti/controller/event" "os" "path/filepath" @@ -314,15 +316,12 @@ func (network *Network) GetCloseNotify() <-chan struct{} { return network.closeNotify } -func (network *Network) RouterChanged(r *Router) { - network.routerChanged <- r -} - func (network *Network) ConnectedRouter(id string) bool { return network.Routers.IsConnected(id) } func (network *Network) ConnectRouter(r *Router) { + network.linkController.buildRouterLinks(r) network.Routers.markConnected(r) time.AfterFunc(250*time.Millisecond, func() { network.routerChanged <- r }) @@ -365,10 +364,40 @@ func (network *Network) ValidateTerminators(r *Router) { } } +type LinkValidationCallback func(detail *mgmt_pb.RouterLinkDetails) + +func (n *Network) ValidateLinks(filter string, cb LinkValidationCallback) (int64, func(), error) { + result, err := n.Routers.BaseList(filter) + if err != nil { + return 0, nil, err + } + + sem := concurrenz.NewSemaphore(10) + + evalF := func() { + for _, router := range result.Entities { + connectedRouter := n.GetConnectedRouter(router.Id) + if connectedRouter != nil { + sem.Acquire() + go func() { + defer sem.Release() + n.linkController.ValidateRouterLinks(n, connectedRouter, cb) + }() + } else { + n.linkController.reportRouterLinksError(router, errors.New("router not connected"), cb) + } + } + } + + return int64(len(result.Entities)), evalF, nil +} + func (network *Network) DisconnectRouter(r *Router) { // 1: remove Links for Router for _, l := range r.routerLinks.GetLinks() { - network.linkController.remove(l) + if l.Src == r { + network.linkController.remove(l) + } network.LinkChanged(l) } // 2: remove Router @@ -381,19 +410,26 @@ func (network *Network) DisconnectRouter(r *Router) { network.routerChanged <- r } -func (network *Network) NotifyExistingLink(id, linkProtocol, dialAddress string, srcRouter *Router, dstRouterId string) (bool, error) { +func (network *Network) NotifyExistingLink(id string, iteration uint32, linkProtocol, dialAddress string, srcRouter *Router, dstRouterId string) { + log := pfxlog.Logger(). + WithField("routerId", srcRouter.Id). + WithField("linkId", id). + WithField("destRouterId", dstRouterId). + WithField("iteration", iteration) + dst := network.Routers.getConnected(dstRouterId) if dst == nil { network.NotifyLinkIdEvent(id, event.LinkFromRouterDisconnectedDest) - return false, errors.New("destination router not connected") } - link, created := network.linkController.routerReportedLink(id, linkProtocol, dialAddress, srcRouter, dst) + + link, created := network.linkController.routerReportedLink(id, iteration, linkProtocol, dialAddress, srcRouter, dst, dstRouterId) if created { network.NotifyLinkEvent(link, event.LinkFromRouterNew) + log.Info("router reported link added") } else { network.NotifyLinkEvent(link, event.LinkFromRouterKnown) + log.Info("router reported link already known") } - return created, nil } func (network *Network) LinkConnected(msg *ctrl_pb.LinkConnected) error { @@ -409,43 +445,16 @@ func (network *Network) LinkConnected(msg *ctrl_pb.LinkConnected) error { return errors.Errorf("no such link [l/%s]", msg.Id) } -func (network *Network) LinkFaulted(id string, dupe bool) error { - if l, found := network.linkController.get(id); found { - l.addState(newLinkState(Failed)) - if dupe { - network.NotifyLinkEvent(l, event.LinkDuplicate) - } else { - network.NotifyLinkEvent(l, event.LinkFault) - } - pfxlog.Logger().WithField("linkId", id).Info("removing failed link") - network.linkController.remove(l) - return nil - } - return errors.Errorf("no such link [l/%s]", id) -} - -func (network *Network) VerifyLinkSource(targetRouter *Router, linkId string, fingerprints []string) error { - l, found := network.linkController.get(linkId) - if !found { - return errors.Errorf("invalid link %v", linkId) - } - - if l.Dst.Id != targetRouter.Id { - return errors.Errorf("incorrect link target router. link=%v, expected router=%v, actual router=%v", l.Id, l.Dst.Id, targetRouter.Id) - } - - routerFingerprint := l.Src.Fingerprint - if routerFingerprint == nil { - return errors.Errorf("invalid source router %v for link %v, not yet enrolled", l.Src.Id, l.Id) - } - - for _, fp := range fingerprints { - if fp == *routerFingerprint { - return nil - } +func (network *Network) LinkFaulted(l *Link, dupe bool) error { + l.addState(newLinkState(Failed)) + if dupe { + network.NotifyLinkEvent(l, event.LinkDuplicate) + } else { + network.NotifyLinkEvent(l, event.LinkFault) } - - return errors.Errorf("could not verify fingerprint for router %v on link %v", l.Src.Id, l.Id) + pfxlog.Logger().WithField("linkId", l.Id).Info("removing failed link") + network.linkController.remove(l) + return nil } func (network *Network) VerifyRouter(routerId string, fingerprints []string) error { @@ -970,11 +979,18 @@ func (network *Network) RemoveLink(linkId string) { log := pfxlog.Logger().WithField("linkId", linkId) link, _ := network.linkController.get(linkId) + var iteration uint32 var routerList []*Router if link != nil { - routerList = []*Router{link.Src, link.Dst} - log = log.WithField("srcRouterId", link.Src.Id).WithField("dstRouterId", link.Dst.Id) + iteration = link.Iteration + routerList = []*Router{link.Src} + if dst := link.GetDest(); dst != nil { + routerList = append(routerList, dst) + } + log = log.WithField("srcRouterId", link.Src.Id). + WithField("dstRouterId", link.DstId). + WithField("iteration", iteration) log.Info("deleting known link") } else { routerList = network.AllConnectedRouters() @@ -982,7 +998,12 @@ func (network *Network) RemoveLink(linkId string) { } for _, router := range routerList { - fault := &ctrl_pb.Fault{Subject: ctrl_pb.FaultSubject_LinkFault, Id: linkId} + fault := &ctrl_pb.Fault{ + Subject: ctrl_pb.FaultSubject_LinkFault, + Id: linkId, + Iteration: iteration, + } + if ctrl := router.Control; ctrl != nil { if err := protobufs.MarshalTyped(fault).WithTimeout(15 * time.Second).Send(ctrl); err != nil { log.WithField("faultDestRouterId", router.Id).WithError(err). @@ -1127,7 +1148,7 @@ func (network *Network) AcceptMetricsMsg(metrics *metrics_pb.MetricsMessage) { if found { if link.Src.Id == router.Id { link.SetSrcLatency(latencyCost) // latency is in nanoseconds - } else if link.Dst.Id == router.Id { + } else if link.DstId == router.Id { link.SetDstLatency(latencyCost) // latency is in nanoseconds } else { log.Warnf("link not for router") diff --git a/controller/network/options.go b/controller/network/options.go index c0f3334ab..791d4f1b1 100644 --- a/controller/network/options.go +++ b/controller/network/options.go @@ -27,7 +27,7 @@ import ( const ( DefaultOptionsCreateCircuitRetries = 2 DefaultOptionsCycleSeconds = 60 - DefaultOptionsEnableLegacyLinkMgmt = true + DefaultOptionsEnableLegacyLinkMgmt = false DefaultOptionsInitialLinkLatency = 65 * time.Second DefaultOptionsPendingLinkTimeout = 10 * time.Second DefaultOptionsMetricsReportInterval = time.Minute diff --git a/controller/network/path_test.go b/controller/network/path_test.go index 37f9dc555..678428c22 100644 --- a/controller/network/path_test.go +++ b/controller/network/path_test.go @@ -23,10 +23,10 @@ import ( "github.com/stretchr/testify/require" "github.com/openziti/channel/v2" - "github.com/openziti/ziti/controller/db" - "github.com/openziti/ziti/controller/models" "github.com/openziti/transport/v2" "github.com/openziti/transport/v2/tcp" + "github.com/openziti/ziti/controller/db" + "github.com/openziti/ziti/controller/models" "github.com/stretchr/testify/assert" ) @@ -50,9 +50,7 @@ func TestSimplePath2(t *testing.T) { r1 := newRouterForTest("r1", "", transportAddr, nil, 0, false) network.Routers.markConnected(r1) - l0 := newTestLink("l0", "tls") - l0.Src = r0 - l0.Dst = r1 + l0 := newTestLink("l0", r0, r1) l0.addState(newLinkState(Connected)) network.linkController.add(l0) @@ -116,15 +114,11 @@ func TestTransitPath2(t *testing.T) { r2 := newRouterForTest("r2", "", transportAddr, nil, 0, false) network.Routers.markConnected(r2) - l0 := newTestLink("l0", "tls") - l0.Src = r0 - l0.Dst = r1 + l0 := newTestLink("l0", r0, r1) l0.addState(newLinkState(Connected)) network.linkController.add(l0) - l1 := newTestLink("l1", "tls") - l1.Src = r1 - l1.Dst = r2 + l1 := newTestLink("l1", r1, r2) l1.addState(newLinkState(Connected)) network.linkController.add(l1) @@ -220,39 +214,31 @@ func TestShortestPath(t *testing.T) { r3 := newRouterForTest("r3", "", transportAddr, nil, 4, false) network.Routers.markConnected(r3) - link := newTestLink("l0", "tls") + link := newTestLink("l0", r0, r1) link.SetStaticCost(2) link.SetDstLatency(10 * 1_000_000) link.SetSrcLatency(11 * 1_000_000) - link.Src = r0 - link.Dst = r1 link.addState(newLinkState(Connected)) network.linkController.add(link) - link = newTestLink("l1", "tls") + link = newTestLink("l1", r0, r2) link.SetStaticCost(5) link.SetDstLatency(15 * 1_000_000) link.SetSrcLatency(16 * 1_000_000) - link.Src = r0 - link.Dst = r2 link.addState(newLinkState(Connected)) network.linkController.add(link) - link = newTestLink("l2", "tls") + link = newTestLink("l2", r1, r3) link.SetStaticCost(9) link.SetDstLatency(20 * 1_000_000) link.SetSrcLatency(21 * 1_000_000) - link.Src = r1 - link.Dst = r3 link.addState(newLinkState(Connected)) network.linkController.add(link) - link = newTestLink("l3", "tls") + link = newTestLink("l3", r2, r3) link.SetStaticCost(13) link.SetDstLatency(25 * 1_000_000) link.SetSrcLatency(26 * 1_000_000) - link.Src = r2 - link.Dst = r3 link.addState(newLinkState(Connected)) network.linkController.add(link) @@ -296,39 +282,31 @@ func TestShortestPathWithUntraversableRouter(t *testing.T) { r3 := newRouterForTest("r3", "", transportAddr, nil, 4, false) network.Routers.markConnected(r3) - link := newTestLink("l0", "tls") + link := newTestLink("l0", r0, r1) link.SetStaticCost(2) link.SetDstLatency(10 * 1_000_000) link.SetSrcLatency(11 * 1_000_000) - link.Src = r0 - link.Dst = r1 link.addState(newLinkState(Connected)) network.linkController.add(link) - link = newTestLink("l1", "tls") + link = newTestLink("l1", r0, r2) link.SetStaticCost(5) link.SetDstLatency(15 * 1_000_000) link.SetSrcLatency(16 * 1_000_000) - link.Src = r0 - link.Dst = r2 link.addState(newLinkState(Connected)) network.linkController.add(link) - link = newTestLink("l2", "tls") + link = newTestLink("l2", r1, r3) link.SetStaticCost(9) link.SetDstLatency(20 * 1_000_000) link.SetSrcLatency(21 * 1_000_000) - link.Src = r1 - link.Dst = r3 link.addState(newLinkState(Connected)) network.linkController.add(link) - link = newTestLink("l3", "tls") + link = newTestLink("l3", r2, r3) link.SetStaticCost(13) link.SetDstLatency(25 * 1_000_000) link.SetSrcLatency(26 * 1_000_000) - link.Src = r2 - link.Dst = r3 link.addState(newLinkState(Connected)) network.linkController.add(link) @@ -366,12 +344,10 @@ func TestShortestPathWithOnlyUntraversableRouter(t *testing.T) { r1 := newRouterForTest("r1", "", transportAddr, nil, 2, true) network.Routers.markConnected(r1) - link := newTestLink("l0", "tls") + link := newTestLink("l0", r0, r1) link.SetStaticCost(2) link.SetDstLatency(10 * 1_000_000) link.SetSrcLatency(11 * 1_000_000) - link.Src = r0 - link.Dst = r1 link.addState(newLinkState(Connected)) network.linkController.add(link) @@ -408,12 +384,10 @@ func TestShortestPathWithUntraversableEdgeRouters(t *testing.T) { r1 := newRouterForTest("r1", "", transportAddr, nil, 2, true) network.Routers.markConnected(r1) - link := newTestLink("l0", "tls") + link := newTestLink("l0", r0, r1) link.SetStaticCost(3) link.SetDstLatency(10 * 1_000_000) link.SetSrcLatency(11 * 1_000_000) - link.Src = r0 - link.Dst = r1 link.addState(newLinkState(Connected)) network.linkController.add(link) @@ -453,21 +427,17 @@ func TestShortestPathWithUntraversableEdgeRoutersAndTraversableMiddle(t *testing r2 := newRouterForTest("r2", "", transportAddr, nil, 3, true) network.Routers.markConnected(r2) - link := newTestLink("l0", "tls") + link := newTestLink("l0", r0, r1) link.SetStaticCost(2) link.SetDstLatency(10 * 1_000_000) link.SetSrcLatency(11 * 1_000_000) - link.Src = r0 - link.Dst = r1 link.addState(newLinkState(Connected)) network.linkController.add(link) - link = newTestLink("l1", "tls") + link = newTestLink("l1", r1, r2) link.SetStaticCost(3) link.SetDstLatency(12 * 1_000_000) link.SetSrcLatency(15 * 1_000_000) - link.Src = r1 - link.Dst = r2 link.addState(newLinkState(Connected)) network.linkController.add(link) @@ -509,21 +479,17 @@ func TestShortestPathWithUntraversableEdgeRoutersAndUntraversableMiddle(t *testi r2 := newRouterForTest("r2", "", transportAddr, nil, 2, true) network.Routers.markConnected(r2) - link := newTestLink("l0", "tls") + link := newTestLink("l0", r0, r1) link.SetStaticCost(2) link.SetDstLatency(10 * 1_000_000) link.SetSrcLatency(11 * 1_000_000) - link.Src = r0 - link.Dst = r1 link.addState(newLinkState(Connected)) network.linkController.add(link) - link = newTestLink("l2", "tls") + link = newTestLink("l2", r1, r2) link.SetStaticCost(2) link.SetDstLatency(10 * 1_000_000) link.SetSrcLatency(11 * 1_000_000) - link.Src = r1 - link.Dst = r2 link.addState(newLinkState(Connected)) network.linkController.add(link) @@ -649,9 +615,7 @@ func TestMinRouterCost(t *testing.T) { } func newPathTestLink(network *Network, id string, srcR, destR *Router) *Link { - l := newTestLink(id, "tls") - l.Src = srcR - l.Dst = destR + l := newTestLink(id, srcR, destR) l.SrcLatency = 0 l.DstLatency = 0 l.recalculateCost() diff --git a/controller/network/route_perf_test.go b/controller/network/route_perf_test.go index b60ba4fc1..c28daf0ef 100644 --- a/controller/network/route_perf_test.go +++ b/controller/network/route_perf_test.go @@ -58,12 +58,10 @@ func TestShortestPathAgainstEstablished(t *testing.T) { addLink := func(srcRouter, dstRouter *Router) { if srcRouter != dstRouter { - link := newTestLink(fmt.Sprintf("link-%04d", linkIdx), "tls") + link := newTestLink(fmt.Sprintf("link-%04d", linkIdx), srcRouter, dstRouter) link.SetStaticCost(int32(nextCost())) link.SetDstLatency(nextCost() * 100_000) link.SetSrcLatency(nextCost() * 100_000) - link.Src = srcRouter - link.Dst = dstRouter link.addState(newLinkState(Connected)) network.linkController.add(link) linkIdx++ @@ -184,12 +182,10 @@ func BenchmarkShortestPathPerfWithRouterChanges(b *testing.B) { addLink := func(srcRouter, dstRouter *Router) { if srcRouter != dstRouter { - link := newTestLink(fmt.Sprintf("link-%04d", linkIdx), "tls") + link := newTestLink(fmt.Sprintf("link-%04d", linkIdx), srcRouter, dstRouter) link.SetStaticCost(int32(nextCost())) link.SetDstLatency(nextCost() * 100_000) link.SetSrcLatency(nextCost() * 100_000) - link.Src = srcRouter - link.Dst = dstRouter link.addState(newLinkState(Connected)) network.linkController.add(link) linkIdx++ @@ -278,12 +274,10 @@ func BenchmarkShortestPathPerf(b *testing.B) { addLink := func(srcRouter, dstRouter *Router) { if srcRouter != dstRouter { - link := newTestLink(fmt.Sprintf("link-%04d", linkIdx), "tls") + link := newTestLink(fmt.Sprintf("link-%04d", linkIdx), srcRouter, dstRouter) link.SetStaticCost(int32(nextCost())) link.SetDstLatency(nextCost() * 100_000) link.SetSrcLatency(nextCost() * 100_000) - link.Src = srcRouter - link.Dst = dstRouter link.addState(newLinkState(Connected)) network.linkController.add(link) linkIdx++ @@ -352,12 +346,10 @@ func BenchmarkMoreRealisticShortestPathPerf(b *testing.B) { addLink := func(srcRouter, dstRouter *Router) { if srcRouter != dstRouter { - link := newTestLink(fmt.Sprintf("link-%04d", linkIdx), "tls") + link := newTestLink(fmt.Sprintf("link-%04d", linkIdx), srcRouter, dstRouter) link.SetStaticCost(int32(nextCost())) link.SetDstLatency(nextCost() * 100_000) link.SetSrcLatency(nextCost() * 100_000) - link.Src = srcRouter - link.Dst = dstRouter link.addState(newLinkState(Connected)) network.linkController.add(link) linkIdx++ diff --git a/controller/network/router.go b/controller/network/router.go index ad8af5d46..c086591fa 100644 --- a/controller/network/router.go +++ b/controller/network/router.go @@ -17,14 +17,14 @@ package network import ( + "github.com/openziti/foundation/v2/genext" + "github.com/openziti/foundation/v2/versions" + "github.com/openziti/ziti/common/pb/cmd_pb" + "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/controller/change" "github.com/openziti/ziti/controller/command" "github.com/openziti/ziti/controller/fields" "github.com/openziti/ziti/controller/xt" - "github.com/openziti/ziti/common/pb/cmd_pb" - "github.com/openziti/ziti/common/pb/ctrl_pb" - "github.com/openziti/foundation/v2/genext" - "github.com/openziti/foundation/v2/versions" "google.golang.org/protobuf/proto" "reflect" "sync" @@ -33,9 +33,9 @@ import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" + "github.com/openziti/storage/boltz" "github.com/openziti/ziti/controller/db" "github.com/openziti/ziti/controller/models" - "github.com/openziti/storage/boltz" cmap "github.com/orcaman/concurrent-map/v2" "github.com/pkg/errors" "go.etcd.io/bbolt" @@ -473,7 +473,7 @@ func (self *RouterLinks) GetLinksByRouter() map[string][]*Link { return result.(map[string][]*Link) } -func (self *RouterLinks) Add(link *Link, other *Router) { +func (self *RouterLinks) Add(link *Link, otherRouterId string) { self.Lock() defer self.Unlock() links := self.GetLinks() @@ -487,13 +487,13 @@ func (self *RouterLinks) Add(link *Link, other *Router) { for k, v := range byRouter { newLinksByRouter[k] = v } - forRouterList := newLinksByRouter[other.Id] + forRouterList := newLinksByRouter[otherRouterId] newForRouterList := append([]*Link{link}, forRouterList...) - newLinksByRouter[other.Id] = newForRouterList + newLinksByRouter[otherRouterId] = newForRouterList self.linkByRouter.Store(newLinksByRouter) } -func (self *RouterLinks) Remove(link *Link, other *Router) { +func (self *RouterLinks) Remove(link *Link, otherRouterId string) { self.Lock() defer self.Unlock() links := self.GetLinks() @@ -510,7 +510,7 @@ func (self *RouterLinks) Remove(link *Link, other *Router) { for k, v := range byRouter { newLinksByRouter[k] = v } - forRouterList := newLinksByRouter[other.Id] + forRouterList := newLinksByRouter[otherRouterId] var newForRouterList []*Link for _, l := range forRouterList { if l != link { @@ -518,9 +518,9 @@ func (self *RouterLinks) Remove(link *Link, other *Router) { } } if len(newForRouterList) == 0 { - delete(newLinksByRouter, other.Id) + delete(newLinksByRouter, otherRouterId) } else { - newLinksByRouter[other.Id] = newForRouterList + newLinksByRouter[otherRouterId] = newForRouterList } self.linkByRouter.Store(newLinksByRouter) diff --git a/controller/network/terminator.go b/controller/network/terminator.go index 257227b17..af432aff5 100644 --- a/controller/network/terminator.go +++ b/controller/network/terminator.go @@ -375,9 +375,9 @@ func (self *TerminatorManager) Unmarshall(bytes []byte) (*Terminator, error) { return result, nil } -type ValidationCallback func(detail *mgmt_pb.TerminatorDetail) +type TerminatorValidationCallback func(detail *mgmt_pb.TerminatorDetail) -func (self *TerminatorManager) ValidateTerminators(filter string, fixInvalid bool, cb ValidationCallback) (uint64, error) { +func (self *TerminatorManager) ValidateTerminators(filter string, fixInvalid bool, cb TerminatorValidationCallback) (uint64, error) { if filter == "" { filter = "true limit none" } @@ -407,7 +407,7 @@ func (self *TerminatorManager) ValidateTerminators(filter string, fixInvalid boo return uint64(len(result.Entities)), nil } -func (self *TerminatorManager) validateTerminatorBatch(fixInvalid bool, routerId string, batch []*Terminator, cb ValidationCallback) { +func (self *TerminatorManager) validateTerminatorBatch(fixInvalid bool, routerId string, batch []*Terminator, cb TerminatorValidationCallback) { router := self.Managers.Routers.getConnected(routerId) if router == nil { self.reportError(router, batch, cb, "router off-line") @@ -448,7 +448,7 @@ func (self *TerminatorManager) validateTerminatorBatch(fixInvalid bool, routerId } } -func (self *TerminatorManager) reportError(router *Router, batch []*Terminator, cb ValidationCallback, err string) { +func (self *TerminatorManager) reportError(router *Router, batch []*Terminator, cb TerminatorValidationCallback, err string) { for _, terminator := range batch { detail := self.newTerminatorDetail(router, terminator) detail.State = mgmt_pb.TerminatorState_Unknown @@ -546,7 +546,7 @@ type ValidateTerminatorRequestSendable struct { mgr *TerminatorManager router *Router terminators []*Terminator - cb ValidationCallback + cb TerminatorValidationCallback ctx context.Context cancelF func() } diff --git a/controller/oidc_auth/storage.go b/controller/oidc_auth/storage.go index 47fcffcc9..bcf7d249f 100644 --- a/controller/oidc_auth/storage.go +++ b/controller/oidc_auth/storage.go @@ -6,18 +6,19 @@ import ( "crypto/sha1" "errors" "fmt" + "net/http" + "strings" + "sync" + "time" + "github.com/golang-jwt/jwt/v5" "github.com/michaelquigley/pfxlog" + "github.com/openziti/foundation/v2/stringz" "github.com/openziti/ziti/controller/apierror" - "github.com/openziti/ziti/controller/model" "github.com/openziti/ziti/controller/change" + "github.com/openziti/ziti/controller/model" "github.com/openziti/ziti/controller/models" - "github.com/openziti/foundation/v2/stringz" cmap "github.com/orcaman/concurrent-map/v2" - "net/http" - "strings" - "sync" - "time" "github.com/google/uuid" "gopkg.in/square/go-jose.v2" @@ -534,7 +535,7 @@ func (s *HybridStorage) RevokeToken(_ context.Context, tokenIDOrToken string, _ _, claims, err := s.parseRefreshToken(tokenIDOrToken) if err != nil { - return nil //not a valid toke ignore + return nil //not a valid token ignore } revocation := NewRevocation(claims.JWTID, claims.Expiration.AsTime()) if err := s.saveRevocation(revocation); err != nil { diff --git a/controller/raft/member.go b/controller/raft/member.go index 0fc44a42d..712a8571a 100644 --- a/controller/raft/member.go +++ b/controller/raft/member.go @@ -17,9 +17,10 @@ package raft import ( + "time" + "github.com/openziti/channel/v2/protobufs" "github.com/openziti/ziti/common/pb/cmd_pb" - "time" "github.com/hashicorp/raft" "github.com/pkg/errors" @@ -182,7 +183,7 @@ func (self *Controller) HandleTransferLeadershipAsLeader(req *cmd_pb.TransferLea } if err := future.Error(); err != nil { - return errors.Wrapf(err, "error transfering leadership") + return errors.Wrapf(err, "error transferring leadership") } return nil } diff --git a/controller/rest_model/link_detail.go b/controller/rest_model/link_detail.go index 8b75648c7..0baac243a 100644 --- a/controller/rest_model/link_detail.go +++ b/controller/rest_model/link_detail.go @@ -63,6 +63,10 @@ type LinkDetail struct { // Required: true ID *string `json:"id"` + // iteration + // Required: true + Iteration *int64 `json:"iteration"` + // protocol // Required: true Protocol *string `json:"protocol"` @@ -108,6 +112,10 @@ func (m *LinkDetail) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateIteration(formats); err != nil { + res = append(res, err) + } + if err := m.validateProtocol(formats); err != nil { res = append(res, err) } @@ -190,6 +198,15 @@ func (m *LinkDetail) validateID(formats strfmt.Registry) error { return nil } +func (m *LinkDetail) validateIteration(formats strfmt.Registry) error { + + if err := validate.Required("iteration", "body", m.Iteration); err != nil { + return err + } + + return nil +} + func (m *LinkDetail) validateProtocol(formats strfmt.Registry) error { if err := validate.Required("protocol", "body", m.Protocol); err != nil { diff --git a/controller/rest_server/embedded_spec.go b/controller/rest_server/embedded_spec.go index 23bddce72..9fad1fb08 100644 --- a/controller/rest_server/embedded_spec.go +++ b/controller/rest_server/embedded_spec.go @@ -1729,7 +1729,8 @@ func init() { "sourceLatency", "destLatency", "cost", - "down" + "down", + "iteration" ], "properties": { "cost": { @@ -1747,6 +1748,9 @@ func init() { "id": { "type": "string" }, + "iteration": { + "type": "integer" + }, "protocol": { "type": "string" }, @@ -7320,7 +7324,8 @@ func init() { "sourceLatency", "destLatency", "cost", - "down" + "down", + "iteration" ], "properties": { "cost": { @@ -7338,6 +7343,9 @@ func init() { "id": { "type": "string" }, + "iteration": { + "type": "integer" + }, "protocol": { "type": "string" }, diff --git a/controller/server/oidc-api.go b/controller/server/oidc-api.go index b13961b38..218ed36ba 100644 --- a/controller/server/oidc-api.go +++ b/controller/server/oidc-api.go @@ -19,14 +19,15 @@ package server import ( "context" "fmt" + "net/http" + "strings" + + "github.com/openziti/foundation/v2/stringz" + "github.com/openziti/xweb/v2" "github.com/openziti/ziti/controller" + "github.com/openziti/ziti/controller/api" "github.com/openziti/ziti/controller/env" "github.com/openziti/ziti/controller/oidc_auth" - "github.com/openziti/ziti/controller/api" - "github.com/openziti/foundation/v2/stringz" - "github.com/openziti/xweb/v2" - "net/http" - "strings" ) var _ xweb.ApiHandlerFactory = &OidcApiFactory{} @@ -122,7 +123,7 @@ func NewOidcApiHandler(serverConfig *xweb.ServerConfig, ae *env.AppEnv, options return nil, fmt.Errorf("[edge-oidc.options.secret] must be a string") } } else { - return nil, fmt.Errorf("[edge-oidc.options.secret] must be definded") + return nil, fmt.Errorf("[edge-oidc.options.secret] must be defined") } if redirectVal, ok := options["redirectURIs"]; ok { diff --git a/controller/specs/swagger.yml b/controller/specs/swagger.yml index 86b7cf3b7..53ef15c41 100644 --- a/controller/specs/swagger.yml +++ b/controller/specs/swagger.yml @@ -1811,6 +1811,7 @@ definitions: - destLatency - cost - down + - iteration properties: id: type: string @@ -1832,6 +1833,8 @@ definitions: type: integer cost: type: integer + iteration: + type: integer linkPatch: type: object properties: diff --git a/controller/xt/costs.go b/controller/xt/costs.go index 2b34a0f6e..11f99e692 100644 --- a/controller/xt/costs.go +++ b/controller/xt/costs.go @@ -17,8 +17,9 @@ package xt import ( - cmap "github.com/orcaman/concurrent-map/v2" "math" + + cmap "github.com/orcaman/concurrent-map/v2" ) const ( @@ -81,7 +82,7 @@ func (p *precedence) GetBiasedCost(cost uint32) uint32 { // Precedences define the precedence levels var Precedences = struct { // Required terminators should always be used in preference to non-required terminators - // Example: The current active node in an active/passive setup. If the strategy determintes + // Example: The current active node in an active/passive setup. If the strategy determines // that the current active has failed, it will drop the precedence and mark some other // terminator as Required Required Precedence diff --git a/dist/cloudfront/get.openziti.io/README.md b/dist/cloudfront/get.openziti.io/README.md new file mode 100644 index 000000000..ccc9e297d --- /dev/null +++ b/dist/cloudfront/get.openziti.io/README.md @@ -0,0 +1,7 @@ + +# CloudFront Function for get.openziti.io + +This function provides the routing logic for the GitHub raw reverse proxy for downloading specific versions of OpenZiti +files that are checked in to GitHub. + +[Documented as part of the quickstart release](../../../quickstart/README.md#github-raw-reverse-proxy) \ No newline at end of file diff --git a/dist/cloudfront/get.openziti.io/routes.yml b/dist/cloudfront/get.openziti.io/routes.yml index f9ae6bf08..b6e5a1d75 100644 --- a/dist/cloudfront/get.openziti.io/routes.yml +++ b/dist/cloudfront/get.openziti.io/routes.yml @@ -1,4 +1,5 @@ -# this is a list of shortcut routes at get.openziti.io for raw.githubusercontent.com +# this is a list of shortcut routes at get.openziti.io for raw.githubusercontent.com and is documented in +# https://github.com/openziti/ziti/tree/main/quickstart#github-raw-reverse-proxy # these are file shortcuts, so the shortcut is the test file - get: /ziti-cli-functions.sh diff --git a/dist/dist-packages/linux/install.bash b/dist/dist-packages/linux/install.bash index d32a0f2d5..6be1a3055 100644 --- a/dist/dist-packages/linux/install.bash +++ b/dist/dist-packages/linux/install.bash @@ -134,7 +134,7 @@ main(){ elif [ -f /etc/debian_version ]; then installDebian "$@" else - echo "ERROR: Unsupported Linux distribution family. The zrok-share package is availabe as a Debian or Red Hat package." >&2 + echo "ERROR: Unsupported Linux distribution family. The zrok-share package is available as a Debian or Red Hat package." >&2 exit 1 fi } diff --git a/dist/dist-packages/linux/nfpm-openziti.yaml b/dist/dist-packages/linux/nfpm-openziti.yaml index c17ee3cd0..f7dd43be0 100644 --- a/dist/dist-packages/linux/nfpm-openziti.yaml +++ b/dist/dist-packages/linux/nfpm-openziti.yaml @@ -24,7 +24,7 @@ contents: replaces: - ziti-cli -# packager-neutral scripts may be overriden by packager-specific scripts +# packager-neutral scripts may be overridden by packager-specific scripts # scripts: # preinstall: ./scripts/preinstall.sh # postinstall: ./scripts/postinstall.sh diff --git a/doc/003-local-deploy.md b/doc/003-local-deploy.md index 989cecf95..f26745a31 100644 --- a/doc/003-local-deploy.md +++ b/doc/003-local-deploy.md @@ -66,7 +66,7 @@ You will need a new terminal with current directory set to the top-level of this ziti edge login -u ADMIN_NAME -p ADMIN_PW ``` -Subsequent `ziti` CLI commands will automatically re-use this session token. You'll need to perform this login step again when the token expires. +Subsequent `ziti` CLI commands will automatically reuse this session token. You'll need to perform this login step again when the token expires. ## Initialize an Edge Router diff --git a/doc/004-controller-pki.md b/doc/004-controller-pki.md index 236fab577..8788630cd 100644 --- a/doc/004-controller-pki.md +++ b/doc/004-controller-pki.md @@ -45,7 +45,7 @@ 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. +The environment variables ZITI_HOME and ZITI_NETWORK will be used to bootstrap 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. diff --git a/doc/ha/dev-setup.md b/doc/ha/dev-setup.md index 1e86a7aba..ea8e72d66 100644 --- a/doc/ha/dev-setup.md +++ b/doc/ha/dev-setup.md @@ -22,7 +22,7 @@ the [HA PKI Guide](./dev-setup-ha-pki.md) 5. The ctrl1.yml config file has the other two controllers as bootstrap members, so when it starts the first controller will start trying form the raft cluster. 3. Initialize the edge using the agent - 1. `ziti agent controller init admin admin 'Default Admin'` + 1. `ziti agent controller init -p admin admin 'Default Admin'` 2. You can of course use different values if you desire You should now have a three node cluster running. You can log into each controller individually. diff --git a/doc/ha/overview.md b/doc/ha/overview.md index 3d7404bac..fc059bcfa 100644 --- a/doc/ha/overview.md +++ b/doc/ha/overview.md @@ -61,7 +61,7 @@ Note that `bootstrapMembers` can only be used when setting the cluster up for th should only be used on a single node. It cannot be used later to add additional nodes to an existing cluster. -**Agent Comands** +**Agent Commands** There are now three new agent commands specific to the controller. diff --git a/doc/transwarp_b1/transwarp_b1.md b/doc/transwarp_b1/transwarp_b1.md index 372848021..b89d9fea1 100644 --- a/doc/transwarp_b1/transwarp_b1.md +++ b/doc/transwarp_b1/transwarp_b1.md @@ -251,7 +251,7 @@ $ dilithium influx load /home/michael/.fablab/instances/transwarp/forensics/1616 [ 0.142] INFO main.main: finished ``` -`dilithium influx load` is designed to take the root of the filesystem tree where the directory structure created by the metrics intrument is located. It will automatically traverse the tree and load any metrics it finds into the analyzer database. +`dilithium influx load` is designed to take the root of the filesystem tree where the directory structure created by the metrics instrument is located. It will automatically traverse the tree and load any metrics it finds into the analyzer database. ### Analyze @@ -418,7 +418,7 @@ Transwarp is the integration of `westworld3` into Ziti's `transport` framework, ## Transwarp vs TranswarpTLS -The `transport` integration means that Ziti now has support for the `transwarp:` and `transwarptls:` transports. These `transwarp:` is analagous to `tcp:` and `transwarptls:` is conceptually similar to `tls:`. `transwarptls:` wraps the `westworld3` protocol in a TLS wrapper, providing the same privacy and authentication mechanisms as `tls:`. +The `transport` integration means that Ziti now has support for the `transwarp:` and `transwarptls:` transports. These `transwarp:` is analogous to `tcp:` and `transwarptls:` is conceptually similar to `tls:`. `transwarptls:` wraps the `westworld3` protocol in a TLS wrapper, providing the same privacy and authentication mechanisms as `tls:`. ## Link Listener @@ -592,4 +592,4 @@ Happy Transwarp-ing. [dilithium]: https://github.com/openziti/dilithium [dilithium-concepts]: https://github.com/openziti/dilithium/blob/main/docs/concepts.md [tuning-guide]: https://github.com/openziti/dilithium/blob/main/docs/tuning.md -[fabric]: https://github.com/openziti/fabric \ No newline at end of file +[fabric]: https://github.com/openziti/fabric diff --git a/etc/ctrl.with.edge.yml b/etc/ctrl.with.edge.yml index 7e99f9678..e7a82abec 100644 --- a/etc/ctrl.with.edge.yml +++ b/etc/ctrl.with.edge.yml @@ -108,6 +108,15 @@ healthChecks: # By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this # section, commenting out, or altering the name of the section will cause the edge to not run. edge: + # This section allows configurating the rate limiter for auth attempts + authRateLimiter: + # if disabled, no auth rate limiting with be enforced + enabled: true + # the smallest window size for auth attempts + minSize: 5 + # the largest allowed window size for auth attempts + maxSize: 250 + # This section represents the configuration of the Edge API that is served over HTTPS api: #(optional, default 90s) Alters how frequently heartbeat and last activity values are persisted diff --git a/etc/ubuntu-snap/README.md b/etc/ubuntu-snap/README.md index c36dc6736..2150693c3 100755 --- a/etc/ubuntu-snap/README.md +++ b/etc/ubuntu-snap/README.md @@ -1,9 +1,9 @@ -# quick notes on builing a snap from scratch... +# quick notes on building a snap from scratch... * checkout branch * install snapd if needed - https://docs.snapcraft.io/installing-snapd/6735 -* install snapcraft --classic to build snaps - +* install snapcraft --classic to build snaps + snap install snapcraft --classic hash -r @@ -13,17 +13,17 @@ Cleaning later steps and re-staging ziti ('build' step changed) Priming ziti - Snapping 'netfoundry' - + Snapping 'netfoundry' - Snapped netfoundry_0.0.1_amd64.snap -* install the snap in spoooky 'dangerous' and 'devmode': +* install the snap in spoooky 'dangerous' and 'devmode': sudo snap install --devmode --dangerous netfoundry*.snap * ensure the snap is listed: snap list | grep netfoundry - + should return something like: netfoundry 0.0.1 x1 - - devmode diff --git a/etc/ubuntu-snap/create-3rdparty.sh b/etc/ubuntu-snap/create-3rdparty.sh index 62c52c160..3dc00dd25 100755 --- a/etc/ubuntu-snap/create-3rdparty.sh +++ b/etc/ubuntu-snap/create-3rdparty.sh @@ -72,7 +72,7 @@ ca_id=$(echo $ca_registration_result | jq -r '.data.id') echo "CA ID set to: ${ca_id}" sleep 1 #trying to avoid edge race conditions? -# fetch the verificationToken from the edge controller. this token needs to be put into a certifiate +# fetch the verificationToken from the edge controller. this token needs to be put into a certificate # signed by the CA just registered verificationResponse=$(curl -X GET -sk -H "Content-Type: application/json" -H "zt-session: ${zt_session}" "${edge_controller_uri}/cas/${ca_id}") verificationToken=$(echo ${verificationResponse} | jq -r ".data.verificationToken") @@ -99,7 +99,7 @@ the_ca=$(curl -X GET -sk -H "Content-Type: application/json" -H "zt-session: ${z sleep 1 #trying to avoid edge race conditions? echo "at this point the ca _*SHOULD*_ be verified. is ca verified? $(echo ${the_ca} | jq -r ".isVerified")" -echo "acuiring the jwt from ${edge_controller_uri}/cas/${ca_id}/jwt into ${pki_root}/auto.jwt" +echo "acquiring the jwt from ${edge_controller_uri}/cas/${ca_id}/jwt into ${pki_root}/auto.jwt" curl -X GET -sk -H "Content-Type: application/json" -H "zt-session: ${zt_session}" "${edge_controller_uri}/cas/${ca_id}/jwt" -o ${pki_root}/auto.jwt ################################################### diff --git a/go.mod b/go.mod index ffde24fd5..4291a68c6 100644 --- a/go.mod +++ b/go.mod @@ -18,14 +18,14 @@ require ( github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa github.com/go-acme/lego/v4 v4.14.2 github.com/go-openapi/errors v0.21.0 - github.com/go-openapi/loads v0.21.3 + github.com/go-openapi/loads v0.21.5 github.com/go-openapi/runtime v0.26.2 - github.com/go-openapi/spec v0.20.12 - github.com/go-openapi/strfmt v0.21.10 - github.com/go-openapi/swag v0.22.5 - github.com/go-openapi/validate v0.22.3 - github.com/go-resty/resty/v2 v2.10.0 - github.com/golang-jwt/jwt/v5 v5.0.0 + github.com/go-openapi/spec v0.20.14 + github.com/go-openapi/strfmt v0.22.0 + github.com/go-openapi/swag v0.22.7 + github.com/go-openapi/validate v0.22.6 + github.com/go-resty/resty/v2 v2.11.0 + github.com/golang-jwt/jwt/v5 v5.2.0 github.com/google/go-cmp v0.6.0 github.com/google/gopacket v1.1.19 github.com/google/uuid v1.5.0 @@ -36,7 +36,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/hashicorp/raft v1.6.0 github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 - github.com/jedib0t/go-pretty/v6 v6.4.9 + github.com/jedib0t/go-pretty/v6 v6.5.3 github.com/jessevdk/go-flags v1.5.0 github.com/jinzhu/copier v0.4.0 github.com/kataras/go-events v0.0.3 @@ -47,17 +47,17 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/natefinch/lumberjack v2.0.0+incompatible github.com/openziti/agent v1.0.16 - github.com/openziti/channel/v2 v2.0.111 - github.com/openziti/edge-api v0.26.6 - github.com/openziti/foundation/v2 v2.0.35 - github.com/openziti/identity v1.0.68 + github.com/openziti/channel/v2 v2.0.116 + github.com/openziti/edge-api v0.26.8 + github.com/openziti/foundation/v2 v2.0.36 + github.com/openziti/identity v1.0.69 github.com/openziti/jwks v1.0.3 - github.com/openziti/metrics v1.2.41 - github.com/openziti/runzmd v1.0.36 - github.com/openziti/sdk-golang v0.22.0 - github.com/openziti/secretstream v0.1.14 - github.com/openziti/storage v0.2.27 - github.com/openziti/transport/v2 v2.0.119 + github.com/openziti/metrics v1.2.43 + github.com/openziti/runzmd v1.0.37 + github.com/openziti/sdk-golang v0.22.17 + github.com/openziti/secretstream v0.1.16 + github.com/openziti/storage v0.2.28 + github.com/openziti/transport/v2 v2.0.121 github.com/openziti/x509-claims v1.0.3 github.com/openziti/xweb/v2 v2.1.0 github.com/openziti/ziti-db-explorer v1.1.3 @@ -66,24 +66,24 @@ require ( github.com/rabbitmq/amqp091-go v1.8.1 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 github.com/russross/blackfriday v1.6.0 - github.com/shirou/gopsutil/v3 v3.23.11 + github.com/shirou/gopsutil/v3 v3.23.12 github.com/sirupsen/logrus v1.9.3 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.18.1 + github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.8.4 github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 github.com/xeipuuv/gojsonschema v1.2.0 - github.com/zitadel/oidc/v2 v2.7.0 + github.com/zitadel/oidc/v2 v2.12.0 go.etcd.io/bbolt v1.3.8 go4.org v0.0.0-20180809161055-417644f6feb5 - golang.org/x/crypto v0.16.0 - golang.org/x/net v0.19.0 + golang.org/x/crypto v0.18.0 + golang.org/x/net v0.20.0 golang.org/x/sync v0.5.0 - golang.org/x/sys v0.15.0 + golang.org/x/sys v0.16.0 golang.org/x/text v0.14.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 gopkg.in/AlecAivazis/survey.v1 v1.8.7 gopkg.in/resty.v1 v1.12.0 gopkg.in/square/go-jose.v2 v2.6.0 @@ -112,12 +112,12 @@ require ( github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-jose/go-jose/v3 v3.0.1 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-openapi/analysis v0.21.5 // indirect - github.com/go-openapi/jsonpointer v0.20.1 // indirect - github.com/go-openapi/jsonreference v0.20.3 // indirect + github.com/go-openapi/analysis v0.22.2 // indirect + github.com/go-openapi/jsonpointer v0.20.2 // indirect + github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 // indirect github.com/gorilla/schema v1.2.0 // indirect @@ -146,6 +146,7 @@ require ( github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect github.com/muhlemmer/gu v0.3.1 // indirect + github.com/muhlemmer/httpforwarded v0.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openziti/dilithium v0.3.3 // indirect @@ -156,7 +157,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rodaine/table v1.0.1 // indirect - github.com/rs/cors v1.9.0 // indirect + github.com/rs/cors v1.10.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -181,11 +182,11 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/image v0.13.0 // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/term v0.15.0 // indirect - golang.org/x/tools v0.14.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/tools v0.16.0 // indirect + google.golang.org/appengine v1.6.8 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect nhooyr.io/websocket v1.8.10 // indirect diff --git a/go.sum b/go.sum index 8d57a7e96..c0c66fee2 100644 --- a/go.sum +++ b/go.sum @@ -89,7 +89,6 @@ github.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4 github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -210,69 +209,42 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/analysis v0.21.5 h1:3tHfEBh6Ia8eKc4M7khOGjPOAlWKJ10d877Cr9teujI= -github.com/go-openapi/analysis v0.21.5/go.mod h1:25YcZosX9Lwz2wBsrFrrsL8bmjjXdlyP6zsr2AMy29M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M= -github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= +github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0= +github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo= github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY= github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonpointer v0.20.1 h1:MkK4VEIEZMj4wT9PmjaUmGflVBr9nvud4Q4UVFbDoBE= -github.com/go-openapi/jsonpointer v0.20.1/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/jsonreference v0.20.3 h1:EjGcjTW8pD1mRis6+w/gmoBdqv5+RbE9B85D1NgDOVQ= -github.com/go-openapi/jsonreference v0.20.3/go.mod h1:FviDZ46i9ivh810gqzFLl5NttD5q3tSlMLqLr6okedM= -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/loads v0.21.3 h1:8sSH2FIm/SnbDUGv572md4YqVMFne/a9Eubvcd3anew= -github.com/go-openapi/loads v0.21.3/go.mod h1:Y3aMR24iHbKHppOj91nQ/SHc0cuPbAr4ndY4a02xydc= +github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= +github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= +github.com/go-openapi/loads v0.21.5 h1:jDzF4dSoHw6ZFADCGltDb2lE4F6De7aWSpe+IcsRzT0= +github.com/go-openapi/loads v0.21.5/go.mod h1:PxTsnFBoBe+z89riT+wYt3prmSBP6GDAQh2l9H1Flz8= github.com/go-openapi/runtime v0.26.2 h1:elWyB9MacRzvIVgAZCBJmqTi7hBzU0hlKD4IvfX0Zl0= github.com/go-openapi/runtime v0.26.2/go.mod h1:O034jyRZ557uJKzngbMDJXkcKJVzXJiymdSfgejrcRw= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.11 h1:J/TzFDLTt4Rcl/l1PmyErvkqlJDncGvPTMnCI39I4gY= -github.com/go-openapi/spec v0.20.11/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.12 h1:cgSLbrsmziAP2iais+Vz7kSazwZ8rsUZd6TUzdDgkVI= -github.com/go-openapi/spec v0.20.12/go.mod h1:iSCgnBcwbMW9SfzJb8iYynXvcY6C/QFrI7otzF7xGM4= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/strfmt v0.21.9 h1:LnEGOO9qyEC1v22Bzr323M98G13paIUGPU7yeJtG9Xs= -github.com/go-openapi/strfmt v0.21.9/go.mod h1:0k3v301mglEaZRJdDDGSlN6Npq4VMVU69DE0LUyf7uA= -github.com/go-openapi/strfmt v0.21.10 h1:JIsly3KXZB/Qf4UzvzJpg4OELH/0ASDQsyk//TTBDDk= -github.com/go-openapi/strfmt v0.21.10/go.mod h1:vNDMwbilnl7xKiO/Ve/8H8Bb2JIInBnH+lqiw6QWgis= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.5 h1:fVS63IE3M0lsuWRzuom3RLwUMVI2peDH01s6M70ugys= -github.com/go-openapi/swag v0.22.5/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= -github.com/go-openapi/validate v0.22.3 h1:KxG9mu5HBRYbecRb37KRCihvGGtND2aXziBAv0NNfyI= -github.com/go-openapi/validate v0.22.3/go.mod h1:kVxh31KbfsxU8ZyoHaDbLBWU5CnMdqBUEtadQ2G4d5M= -github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo= -github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= +github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= +github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/strfmt v0.22.0 h1:Ew9PnEYc246TwrEspvBdDHS4BVKXy/AOVsfqGDgAcaI= +github.com/go-openapi/strfmt v0.22.0/go.mod h1:HzJ9kokGIju3/K6ap8jL+OlGAbjpSv27135Yr9OivU4= +github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR8= +github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= +github.com/go-openapi/validate v0.22.6 h1:+NhuwcEYpWdO5Nm4bmvhGLW0rt1Fcc532Mu3wpypXfo= +github.com/go-openapi/validate v0.22.6/go.mod h1:eaddXSqKeTg5XpSmj1dYyFTK/95n/XHwcOY+BMxKMyM= +github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= +github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= -github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= +github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -351,7 +323,6 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -429,9 +400,11 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb-client-go/v2 v2.2.2/go.mod h1:fa/d1lAdUHxuc1jedx30ZfNG573oQTQmUni3N6pcW+0= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/jedib0t/go-pretty/v6 v6.4.9 h1:vZ6bjGg2eBSrJn365qlxGcaWu09Id+LHtrfDWlB2Usc= -github.com/jedib0t/go-pretty/v6 v6.4.9/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs= +github.com/jedib0t/go-pretty/v6 v6.5.3 h1:GIXn6Er/anHTkVUoufs7ptEvxdD6KIhR7Axa2wYCPF0= +github.com/jedib0t/go-pretty/v6 v6.5.3/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jeremija/gosubmit v0.2.7 h1:At0OhGCFGPXyjPYAsCchoBUhE099pcBXmsb4iZqROIc= +github.com/jeremija/gosubmit v0.2.7/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI= 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.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= @@ -462,7 +435,6 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -492,9 +464,6 @@ github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marten-seemann/qpack v0.2.0/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= @@ -526,7 +495,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= @@ -558,7 +526,6 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -569,6 +536,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= +github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY= +github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= @@ -596,30 +565,30 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openziti/agent v1.0.16 h1:9Saji+8hFE1NpzP2XzDhsVJbCrDlhixoLHfOpFt5Z+U= github.com/openziti/agent v1.0.16/go.mod h1:zfm53+PVWoGFzjGGgQdKby5749G6VRYHe+eQJmoVKy4= -github.com/openziti/channel/v2 v2.0.111 h1:ZZDyUUFcyshitXjUqAMjdAKbaDMpgV7oX1Jp1I35Rc4= -github.com/openziti/channel/v2 v2.0.111/go.mod h1:abw0qwT0MzWvh1eI2P6D6CD17PRHL8EEo1d3DHCyCdM= +github.com/openziti/channel/v2 v2.0.116 h1:VUxJ3rICTQz9fmSz6tbssC2tzXafL1MAY6yvgHfSUHI= +github.com/openziti/channel/v2 v2.0.116/go.mod h1:RADBBOkbwpFMmbznU3bZmUsBB646seqZnQ7GPI6Chjg= 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-api v0.26.6 h1:qM5XRaYYZxRIkb3xDkAU1D2EkQx8a+oHvCWbd+v0fbA= -github.com/openziti/edge-api v0.26.6/go.mod h1:DX+fKivCRgnl5oxuLLoEx044arhjlgI7peGlqxN+Iks= -github.com/openziti/foundation/v2 v2.0.35 h1:4VaMwZ2kAy6jwBYeQIBN2m8rcGroTDX4A2Jp7NAKb6M= -github.com/openziti/foundation/v2 v2.0.35/go.mod h1:Xnb3IxP1e1UcgLggqSunEpCjH3iHozkPi9Bd9GESbwo= -github.com/openziti/identity v1.0.68 h1:SaFr7BeFQBoWQDiT28vUb8D9w7v6lIAK6/9RkwmV0OU= -github.com/openziti/identity v1.0.68/go.mod h1:HbOu3TQ032v8xE6xZWjO51azF4fUxRLjO/l/oGqJwUI= +github.com/openziti/edge-api v0.26.8 h1:W1iHwVrb4hVKXWhfN8g/dl1d0RGdus6nOYbhM5ixOEg= +github.com/openziti/edge-api v0.26.8/go.mod h1:Tm2Qn1BC0zF+F261Y8FTyPtS/UkeUtUBYoT6ueCjVbA= +github.com/openziti/foundation/v2 v2.0.36 h1:ogEIvsWur8/9mUzf9NOB4hRUyx372Uy6AmnHRcurIkY= +github.com/openziti/foundation/v2 v2.0.36/go.mod h1:MdK2oAJSwo7iCfvVdG16ZGz47qP7nG97ovnqEdXW2kQ= +github.com/openziti/identity v1.0.69 h1:wNgQomnv8ar2S1wge9jQK1jpqE2virOKKG8GyfTiHMQ= +github.com/openziti/identity v1.0.69/go.mod h1:+7hQNAG5nUUdz0165OubWpMHkP/ZVJB3nv9HUXXi9H8= github.com/openziti/jwks v1.0.3 h1:hf8wkb+Cg4nH/HM0KROFd7u+C3DkRVcFZJ7tDV+4icc= github.com/openziti/jwks v1.0.3/go.mod h1:t4xxq8vlXGsPn29kiQVnZBBDDnEoOFqtJoHibkJunQQ= -github.com/openziti/metrics v1.2.41 h1:JShcFb6qJPA2cMiWQLtcSXiJjsrhEWpH+aVcjT/Mcbs= -github.com/openziti/metrics v1.2.41/go.mod h1:L9h0NrliMA3+p7+ascKgvx28qoKHymN9l+CMA+Q+sZc= -github.com/openziti/runzmd v1.0.36 h1:HOqTZFzTTFu52qmCAQfFvKDmCSl8ZqP1PQQ0UnJIA4E= -github.com/openziti/runzmd v1.0.36/go.mod h1:jYqummjskmFh63htJFF2SrUuvxNQifqd5REUhYVaY/A= -github.com/openziti/sdk-golang v0.22.0 h1:kOXziZTNvMyJc0DIPoQ9izAukkJTL8nqdrlwWfU/Ul0= -github.com/openziti/sdk-golang v0.22.0/go.mod h1:QdoqZHmiajDHywYCh25SGMMA3NipCvO5Iykf8fHi+sI= -github.com/openziti/secretstream v0.1.14 h1:Ta+nB5Prcct+L5LIKUA1nE56QhWS6lMPQYTlpxUltU0= -github.com/openziti/secretstream v0.1.14/go.mod h1:/hhuLfu+GIv0+cnapfsu/VOnXEvmTt3GKtCu+lQ0RIw= -github.com/openziti/storage v0.2.27 h1:WdFD0KxXZxSoWOaojdi5r1LO0BTvn4x/7wwdwhRPssc= -github.com/openziti/storage v0.2.27/go.mod h1:p/04So5E3NT2jsGew0AS4hYTfP5srti3VytOjlVcx0M= -github.com/openziti/transport/v2 v2.0.119 h1:KOgHU+9EZUVPvv8ncifqHmNEcFUHbJHigo3jyPvWnOc= -github.com/openziti/transport/v2 v2.0.119/go.mod h1:H2IIBP6ed9isE/eJHGXtAZL0d73ApYOpLG9sSvutNNI= +github.com/openziti/metrics v1.2.43 h1:DSrmpLhoA45DlLVNdKOn2lBfCM0/r6wKz+3SDXe8X7Y= +github.com/openziti/metrics v1.2.43/go.mod h1:+RY4avT60Vbxb9wyfvRD0msrARyYCB5+heb8VIZzCm8= +github.com/openziti/runzmd v1.0.37 h1:qj2r9z4t7OAdmIXMdGbP9Su6TqA0bLdD2RMjJ71LRS0= +github.com/openziti/runzmd v1.0.37/go.mod h1:eKhqJsGoLeDHex/o5Mw6TcNJxlVljafSVm7ZU+bX5G8= +github.com/openziti/sdk-golang v0.22.17 h1:taywYpWpWBtZUj6KewMScYXgPe8TWz2nWNl96/y/IZ4= +github.com/openziti/sdk-golang v0.22.17/go.mod h1:t0sT5N1Q/LdAd54Dxz274sQ9vJo8/B5Q0jn+VZ9vFuw= +github.com/openziti/secretstream v0.1.16 h1:tVanF7OpJL1MJ1gvWaRlR2i+kAbrGsxr3q6EXFOS08U= +github.com/openziti/secretstream v0.1.16/go.mod h1:bvjGBUW/0e5MzD5S3FW3rhGASRNWAi+kTkTENZ9qRDE= +github.com/openziti/storage v0.2.28 h1:qHnsSF4RgQpT23hOXlwkAvJ0gO5PLmvTqyBy13dm3Rc= +github.com/openziti/storage v0.2.28/go.mod h1:ahdvsmmdQWFsZXeExvXeA8MHUXPLrwuDFBJDTztLY5E= +github.com/openziti/transport/v2 v2.0.121 h1:9WB1/9YMFed2UuefqZq+odUYYkoFOr+8aBIAZEC1MNE= +github.com/openziti/transport/v2 v2.0.121/go.mod h1:hS7TzoyTIwm4lVEsGyjQkoEg+vA+6dAOR8S4FZmWIj4= 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.1.0 h1:Xhh3C2pZkq/Prr65V+SfFSibLDYteoc4f62KQCcTZF4= @@ -642,7 +611,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= -github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw= github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= @@ -691,8 +659,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= @@ -705,8 +673,8 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ= -github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -771,8 +739,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.18.1 h1:rmuU42rScKWlhhJDyXZRKJQHXFX02chSVW1IvkPGiVM= -github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= 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= @@ -788,9 +756,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -799,7 +765,6 @@ github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSW github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -815,9 +780,7 @@ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ 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/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -835,15 +798,14 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zitadel/oidc/v2 v2.7.0 h1:IGX4EDk6tegTjUSsZDWeTfLseFU0BdJ/Glf1tgys2lU= -github.com/zitadel/oidc/v2 v2.7.0/go.mod h1:zkUkVJS0sDVy9m0UA9RgO3f8i/C0rtjvXU36UJj7T+0= +github.com/zitadel/oidc/v2 v2.12.0 h1:4aMTAy99/4pqNwrawEyJqhRb3yY3PtcDxnoDSryhpn4= +github.com/zitadel/oidc/v2 v2.12.0/go.mod h1:LrRav74IiThHGapQgCHZOUNtnqJG0tcZKHro/91rtLw= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak= @@ -901,8 +863,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= 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= @@ -947,8 +909,8 @@ 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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= @@ -1002,8 +964,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= 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= @@ -1018,8 +980,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1116,16 +1078,17 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= 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= @@ -1206,8 +1169,8 @@ 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.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= 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= @@ -1245,8 +1208,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1327,8 +1291,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/AlecAivazis/survey.v1 v1.8.7 h1:oBJqtgsyBLg9K5FK9twNUbcPnbCPoh+R9a+7nag3qJM= gopkg.in/AlecAivazis/survey.v1 v1.8.7/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1365,7 +1329,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/quickstart/docker/.gitignore b/quickstart/docker/.gitignore index 31e10f210..2c291eaa5 100644 --- a/quickstart/docker/.gitignore +++ b/quickstart/docker/.gitignore @@ -1 +1,2 @@ -ziti-bin +*/ziti-bin/** +*/persistent/** diff --git a/quickstart/docker/all-in-one/.env b/quickstart/docker/all-in-one/.env new file mode 100644 index 000000000..19cd77223 --- /dev/null +++ b/quickstart/docker/all-in-one/.env @@ -0,0 +1,2 @@ +# required until ziti 0.32.0 +ZITI_QUICK_TAG=release-next \ No newline at end of file diff --git a/quickstart/docker/all-in-one/Dockerfile b/quickstart/docker/all-in-one/Dockerfile new file mode 100644 index 000000000..423015b44 --- /dev/null +++ b/quickstart/docker/all-in-one/Dockerfile @@ -0,0 +1,5 @@ +FROM debian:bookworm-slim + +COPY ./build/ziti /usr/local/bin/ + +CMD ["ziti"] diff --git a/quickstart/docker/all-in-one/README.md b/quickstart/docker/all-in-one/README.md new file mode 100644 index 000000000..fabf528d6 --- /dev/null +++ b/quickstart/docker/all-in-one/README.md @@ -0,0 +1,122 @@ +# minimal Ziti Docker quickstart + +This Docker Compose project runs `ziti edge quickstart` in a container while persisting configs, PKI, database, etc. in the same directory `./persistent/`. + +## Run Ziti + +This is the primary use case for this project: running the `ziti edge quickstart` command in the official +`openziti/ziti-cli` container image. + +1. In this "minimal" sub-directory, pull the container images. + + ```bash + docker compose pull + ``` + +2. Run the project. + + ```bash + docker compose up --detach + ``` + +3. Modify the state in `./persistent/`, and bounce the container. + + ```bash + docker compose up --force-recreate --detach + ``` + +4. Observe the logs + + ```bash + docker compose logs quickstart --follow + ``` + +5. Run the CLI inside the quickstart environment. + + ```bash + docker compose exec quickstart ziti edge list identities + ``` + + ```buttonless title="Output" + ╭────────────┬───────────────────┬─────────┬────────────┬─────────────╮ + │ ID │ NAME │ TYPE │ ATTRIBUTES │ AUTH-POLICY │ + ├────────────┼───────────────────┼─────────┼────────────┼─────────────┤ + │ ZS1YAo4Gnj │ quickstart-router │ Router │ │ Default │ + │ cOmDAo4Gb │ Default Admin │ Default │ │ Default │ + ╰────────────┴───────────────────┴─────────┴────────────┴─────────────╯ + results: 1-2 of 2 + ``` + +## Develop Ziti + +This is a secondary use case for this Docker Compose project that replaces the `ziti` binary in the container image with +the one you build locally with `go build` before running the `ziti edge quickstart` command. + +1. In the top-level directory of the `ziti` project, build the binary. + + ```bash + go build -o ./build ./... + ``` + + The build command can also be run from this "minimal" sub-directory. + + ```bash + go build -o ../../../build ../../../... + ``` + +2. In the "minimal" sub-directory, with `Dockerfile` present: + + ```bash + docker compose up --detach --build + ``` + + By adding this `--build` option to the `up` command, the container image is built from the Dockerfile with your + locally built `ziti` binary instead of pulling the default `openziti/ziti-cli` container image from Docker Hub. In + the `compose.yml`, the Docker build context is defined with environment variable `ZITI_SRC_ROOT` which defaults to + `../../../` (three levels up from this directory at the top level of a Git working copy of the source repo). + +### Troubleshooting + +#### Changing File Locations + +The Compose project file `compose.yml` and `Dockerfile` have file paths that represent the assumption they're placed in +a sub-directory three levels deep in a checked-out copy of the `openziti/ziti` source repository. This allows the Dockerfile +to copy the built binary from the top-level directory `./build`. You can move these files outside the source tree if you +adjust the paths in both files. + +#### Building `ziti` in the Dockerfile + +If the binary you build on your host doesn't run in the container due to an environment issue, such as a GLIBC version +mismatch, you have the option to build `ziti` in the container every time you run `up --build`. + +Change `Dockerfile` like this, and run `docker compose up --detach --build` to build the checked-out source tree and run +the quickstart with the build. + +```dockerfile +FROM golang:1.20-bookworm AS builder +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN go build -o ./build/ ./... + +FROM debian:bookworm-slim +COPY --from=builder /app/build/ziti /usr/local/bin/ + +CMD ["ziti"] +``` + +#### Gotcha - Clobbering the Container Image + +With `docker compose up --build`, the container image specified in `image` is replaced with the one built from the Dockerfile. +This clobbers any image you may have pulled from the registry unless you change the value of `image` or comment the line. + +```yaml + # commenting "image" avoids clobbering the image pulled from the registry + # image: ${ZITI_QUICK_IMAGE:-docker.io/openziti/ziti-cli}:${ZITI_QUICK_TAG:-latest} + build: + context: ${ZITI_SRC_ROOT:-../../../} + dockerfile: ./quickstart/docker/minimal/Dockerfile +``` + +Next time you run `docker compose pull` the image from the registry will be refreshed in the local cache. diff --git a/quickstart/docker/all-in-one/compose.yml b/quickstart/docker/all-in-one/compose.yml new file mode 100644 index 000000000..81b67186b --- /dev/null +++ b/quickstart/docker/all-in-one/compose.yml @@ -0,0 +1,66 @@ +services: + quickstart: + image: ${ZITI_QUICK_IMAGE:-docker.io/openziti/ziti-cli}:${ZITI_QUICK_TAG:-latest} + restart: unless-stopped + build: + context: ${ZITI_SRC_ROOT:-../../../} + dockerfile: ./quickstart/docker/all-in-one/Dockerfile + args: {} + networks: + quickstart: + # this allows other containers to use the same external DNS name to reach the quickstart container from within the + # Docker network that clients outside the Docker network use to reach the quickstart container via port forwarding + aliases: + - ${EXTERNAL_DNS:-null} + entrypoint: + - bash + - -euc + - | + ZITI_CMD+=" --ctrl-address ${EXTERNAL_DNS:-127.0.0.1}"\ + " --ctrl-port ${ZITI_CTRL_EDGE_ADVERTISED_PORT:-1280}"\ + " --router-address ${EXTERNAL_DNS:-127.0.0.1}"\ + " --router-port ${ZITI_ROUTER_PORT:-3022}"\ + " --password ${ZITI_PWD:-admin}" + echo "DEBUG: run command is: ziti $${@} $${ZITI_CMD}" + exec ziti "$${@}" $${ZITI_CMD} + command: -- edge quickstart --home /persistent + user: ${ZIGGY_UID:-1000} + environment: + HOME: /persistent + PFXLOG_NO_JSON: "${PFXLOG_NO_JSON:-true}" + volumes: + # store the quickstart state in a named volume; "initialize" service's mount must remain aligned to set the owner on + # "up" + - persistent:/persistent + # store the quickstart state on the Docker host in the same directory as this compose.yml file + # - ./persistent:/persistent + ports: + - ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_CTRL_EDGE_ADVERTISED_PORT:-1280}:${ZITI_CTRL_EDGE_ADVERTISED_PORT:-1280} + - ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_ROUTER_PORT:-3022}:${ZITI_ROUTER_PORT:-3022} + depends_on: + initialize: + condition: service_completed_successfully + # this service is used to initialize the persistent volume by setting the owner to the UID of the user running the + # quickstart container + initialize: + image: busybox + command: chown -Rc ${ZIGGY_UID:-1000} /persistent + user: root + environment: + HOME: /persistent + # PFXLOG_NO_JSON: "true" + volumes: + # store the quickstart state in a named volume; this mount must align with the "quickstart" service's mount + - persistent:/persistent + # store the quickstart state on the Docker host in the same directory as this compose.yml file + # - ./persistent:/persistent + +# define a custom network so that we can also define a DNS alias for the quickstart container +networks: + quickstart: + driver: bridge + +volumes: + # this will not be used if you switch from named volume to bind mount volume + persistent: + driver: local \ No newline at end of file diff --git a/quickstart/docker/image/getZiti.ps1 b/quickstart/docker/image/getZiti.ps1 index 12f49b922..5927da8cd 100644 --- a/quickstart/docker/image/getZiti.ps1 +++ b/quickstart/docker/image/getZiti.ps1 @@ -4,8 +4,8 @@ Gets the latest ziti from github and adds it to your path .DESCRIPTION This script will: - - detect the lastest version of ziti - - download the latest versio of ziti into the folder of your choice, defaulting to $env:userprofile.ziti\bin) + - detect the latest version of ziti + - download the latest version of ziti into the folder of your choice, defaulting to $env:userprofile.ziti\bin) - unzip the downloaded file - optionally add the extracted path to your path if executed with a "dot" as in: . getLatestZiti.ps1 diff --git a/quickstart/docker/image/run-router-external.sh b/quickstart/docker/image/run-router-external.sh index fcb226e2a..120e38f82 100755 --- a/quickstart/docker/image/run-router-external.sh +++ b/quickstart/docker/image/run-router-external.sh @@ -35,7 +35,7 @@ if [ ! -f ${ZITI_ROUTER_ADVERTISED_ADDRESS}.jwt ]; then # If we have override variables then override the base variable - # This is required as the .bashrc loads the env file which clobbers passed in varibles + # This is required as the .bashrc loads the env file which clobbers passed in variables if [[ "${ZITI_ROUTER_RAWNAME_OVERRIDE}" == "" ]]; then echo "ERROR: Missing ZITI_ROUTER_RAWNAME_OVERRIDE definition" >&2; exit; fi # May have been a bad attempt before, so lets clean up rm -f ${ZITI_HOME}/${ZITI_ROUTER_NAME}* diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh index c71d0e896..3e9e68815 100644 --- a/quickstart/docker/image/ziti-cli-functions.sh +++ b/quickstart/docker/image/ziti-cli-functions.sh @@ -75,7 +75,7 @@ function _setup_ziti_env_path { function _setup_ziti_network { if [[ "ran" != "${_setup_ziti_network_run}" ]]; then - if [[ "${ZITI_NETWORK-}" == "" ]]; then ZITI_NETWORK="$(hostname -s)"; export ZITI_NETWORK; else echo "ZITI_NETWORK overridden: ${ZITI_NETWORK}"; fi + if [[ "${ZITI_NETWORK-}" == "" ]]; then ZITI_NETWORK="$(hostname)"; export ZITI_NETWORK; else echo "ZITI_NETWORK overridden: ${ZITI_NETWORK}"; fi _setup_ziti_network_run="ran" fi } diff --git a/quickstart/kubernetes/miniziti.bash b/quickstart/kubernetes/miniziti.bash index 97d7e9b7c..b7db23a32 100644 --- a/quickstart/kubernetes/miniziti.bash +++ b/quickstart/kubernetes/miniziti.bash @@ -283,7 +283,7 @@ minizitiLogin() { --password logInfo "Setting default ziti identity to: $MINIKUBE_PROFILE" - zitiWrapper edge use "$MINIKUBE_PROFILE" >&3 + ziti edge use "$MINIKUBE_PROFILE" >&3 } minizitiConsole() { diff --git a/quickstart/test/README.md b/quickstart/test/README.md new file mode 100644 index 000000000..8d45da2d4 --- /dev/null +++ b/quickstart/test/README.md @@ -0,0 +1,43 @@ +# Running Quickstart Tests +The quickstart test ensures a network is minimally functional by creating a service that intercepts the controller's +edge HTTP/API plane, then obtains a valid http response by dialing that service. + +## Automated +The automated test starts up an ephemeral OpenZiti network and runs `performQuickstartTest`. + +To run the automated edge test, execute the following from the project root (environment variables are auto populated) +``` +# From project root +go test -v -tags "quickstart automated" ./ziti/cmd/edge/... -run TestEdgeQuickstartAutomated + +# From relative README path +go test -v -tags "quickstart automated" ../../ziti/cmd/edge/... -run TestEdgeQuickstartAutomated +``` + +## Manual +The manual test utilizes an existing network and runs `performQuickstartTest`. Use the manual method to test +any network, anywhere, by adjusting the environment variables as necessary. + +The following environment variables are referenced for network information. + +* `ZITI_USER` - defaults to `admin` +* `ZITI_PWD` - defaults to `admin` +* `ZITI_CTRL_EDGE_ADVERTISED_ADDRESS` - defaults to `ziti-edge-controller` +* `ZITI_CTRL_EDGE_ADVERTISED_PORT` - defaults to `1280` +* `ZITI_ROUTER_NAME` - defaults to `ziti-edge-router` + +To run the manual test, edit the environment variables as necessary and execute the following from the project root +``` +# Optionally adjust environment variable values as needed +ZITI_USER="admin" +ZITI_PWD="admin" +ZITI_CTRL_EDGE_ADVERTISED_ADDRESS="ziti-edge-controller" +ZITI_CTRL_EDGE_ADVERTISED_PORT="1280" +ZITI_ROUTER_NAME="ziti-edge-router" + +# From project root +go test -v -tags "quickstart manual" ./ziti/cmd/edge/... -run TestEdgeQuickstartManual + +# From relative README path +go test -v -tags "quickstart manual" ../../ziti/cmd/edge/... -run TestEdgeQuickstartManual +``` \ No newline at end of file diff --git a/router/accepter.go b/router/accepter.go index ffbc962ee..288f381d7 100644 --- a/router/accepter.go +++ b/router/accepter.go @@ -16,7 +16,10 @@ func (self *xlinkAccepter) Accept(xlink xlink.Xlink) error { if err := self.forwarder.RegisterLink(xlink); err != nil { return err } - logrus.Infof("accepted new link [l/%s]", xlink.Id()) + logrus.WithField("linkId", xlink.Id()). + WithField("destId", xlink.DestinationId()). + WithField("iteration", xlink.Iteration()). + Info("accepted new link") return nil } diff --git a/router/config.go b/router/config.go index 9e9f6b6d8..f338f130b 100644 --- a/router/config.go +++ b/router/config.go @@ -19,6 +19,7 @@ package router import ( "bytes" "fmt" + "github.com/openziti/transport/v2/tls" "github.com/openziti/ziti/router/env" "io" "os" @@ -27,13 +28,13 @@ import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" + "github.com/openziti/foundation/v2/concurrenz" + "github.com/openziti/identity" + "github.com/openziti/transport/v2" "github.com/openziti/ziti/common/config" "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/router/forwarder" "github.com/openziti/ziti/router/xgress" - "github.com/openziti/foundation/v2/concurrenz" - "github.com/openziti/identity" - "github.com/openziti/transport/v2" "github.com/pkg/errors" "github.com/spf13/pflag" "gopkg.in/yaml.v2" @@ -743,6 +744,18 @@ func LoadConfig(path string) (*Config, error) { } } + if value, found := cfgmap["tls"]; found { + if tlsMap, ok := value.(map[interface{}]interface{}); ok { + if value, found := tlsMap["handshakeTimeout"]; found { + if val, err := time.ParseDuration(fmt.Sprintf("%v", value)); err == nil { + tls.SetSharedListenerHandshakeTimeout(val) + } else { + return nil, errors.Wrapf(err, "failed to parse tls.handshakeTimeout value '%v", value) + } + } + } + } + return cfg, nil } diff --git a/router/enroll/enroll.go b/router/enroll/enroll.go index 77bb2d71e..601f62449 100644 --- a/router/enroll/enroll.go +++ b/router/enroll/enroll.go @@ -24,6 +24,11 @@ import ( "encoding/json" "errors" "fmt" + "net/http" + "net/url" + "os" + "strings" + "github.com/go-resty/resty/v2" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" @@ -32,10 +37,6 @@ import ( "github.com/openziti/sdk-golang/ziti/enroll" "github.com/openziti/ziti/router" "github.com/openziti/ziti/router/internal/edgerouter" - "net/http" - "net/url" - "os" - "strings" ) type apiPost struct { @@ -225,7 +226,7 @@ func (re *RestEnroller) Send(client *resty.Client, enrollUrl string, e *apiPost) return nil, err } if resp.StatusCode() != http.StatusOK { - return nil, fmt.Errorf("enrollment failed recieved HTTP status [%s]: %s", resp.Status(), resp.Body()) + return nil, fmt.Errorf("enrollment failed received HTTP status [%s]: %s", resp.Status(), resp.Body()) } return &envelope, nil diff --git a/router/fabric/manager.go b/router/fabric/manager.go index 06b41636e..5a6888e83 100644 --- a/router/fabric/manager.go +++ b/router/fabric/manager.go @@ -54,6 +54,7 @@ type StateManager interface { //"Network" Sessions RemoveEdgeSession(token string) AddEdgeSessionRemovedListener(token string, callBack func(token string)) RemoveListener + WasSessionRecentlyRemoved(token string) bool //ApiSessions GetApiSession(token string) *ApiSession @@ -284,6 +285,10 @@ func (sm *StateManagerImpl) GetApiSession(token string) *ApiSession { return nil } +func (sm *StateManagerImpl) WasSessionRecentlyRemoved(token string) bool { + return sm.recentlyRemovedSessions.Has(token) +} + func (sm *StateManagerImpl) AddEdgeSessionRemovedListener(token string, callBack func(token string)) RemoveListener { if sm.recentlyRemovedSessions.Has(token) { go callBack(token) // callback can be long process with network traffic. Don't block event processing diff --git a/router/forwarder/options.go b/router/forwarder/options.go index f0011169c..05521b1cb 100644 --- a/router/forwarder/options.go +++ b/router/forwarder/options.go @@ -44,7 +44,7 @@ const ( DefaultRateLimiterQueueLength = 5000 MinRateLimiterWorkerQueueLength = 1 MaxRateLimiterWorkerQueueLength = 50000 - DefaultRateLimiterWorkerCount = 5 + DefaultRateLimiterWorkerCount = 15 MinRateLimiterWorkerCount = 1 MaxRateLimiterWorkerCount = 10000 diff --git a/router/handler_ctrl/fault.go b/router/handler_ctrl/fault.go index f124b181d..16315b1b1 100644 --- a/router/handler_ctrl/fault.go +++ b/router/handler_ctrl/fault.go @@ -56,6 +56,12 @@ func (self *faultHandler) handleFault(_ *channel.Message, ch channel.Channel, fa linkId := fault.Id log = log.WithField("linkId", linkId) if link, _ := self.xlinkRegistry.GetLinkById(linkId); link != nil { + if fault.Iteration > 0 && fault.Iteration < link.Iteration() { + log.WithField("fault.iteration", fault.Iteration). + WithField("link.iteration", link.Iteration()). + Info("link fault reported, but fault iteration < link iteration, ignoring") + return + } log.Info("link fault reported, closing") if err := link.CloseNotified(); err != nil { log.WithError(err).Error("failure closing link") diff --git a/router/handler_ctrl/route.go b/router/handler_ctrl/route.go index ba90d5172..ce43feee3 100644 --- a/router/handler_ctrl/route.go +++ b/router/handler_ctrl/route.go @@ -23,15 +23,15 @@ import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" - "github.com/openziti/ziti/controller/xt" + "github.com/openziti/foundation/v2/goroutines" + "github.com/openziti/identity" "github.com/openziti/ziti/common/ctrl_msg" "github.com/openziti/ziti/common/logcontext" "github.com/openziti/ziti/common/pb/ctrl_pb" + "github.com/openziti/ziti/controller/xt" "github.com/openziti/ziti/router/forwarder" "github.com/openziti/ziti/router/handler_xgress" "github.com/openziti/ziti/router/xgress" - "github.com/openziti/foundation/v2/goroutines" - "github.com/openziti/identity" "github.com/pkg/errors" "github.com/sirupsen/logrus" "google.golang.org/protobuf/proto" @@ -53,6 +53,7 @@ func newRouteHandler(ch channel.Channel, env env.RouterEnv, forwarder *forwarder env: env, forwarder: forwarder, pool: pool, + dialerCfg: env.GetDialerCfg(), } return handler diff --git a/router/handler_edge_ctrl/apiSessionAdded.go b/router/handler_edge_ctrl/apiSessionAdded.go index 027c0a6cf..54866c2d6 100644 --- a/router/handler_edge_ctrl/apiSessionAdded.go +++ b/router/handler_edge_ctrl/apiSessionAdded.go @@ -20,6 +20,10 @@ import ( "encoding/json" "errors" "fmt" + "sync" + "sync/atomic" + "time" + "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" "github.com/openziti/channel/v2/protobufs" @@ -29,9 +33,6 @@ import ( "github.com/openziti/ziti/router/fabric" "github.com/sirupsen/logrus" "google.golang.org/protobuf/proto" - "sync" - "sync/atomic" - "time" ) type apiSessionAddedHandler struct { @@ -121,7 +122,7 @@ func (h *apiSessionAddedHandler) applySync(tracker *apiSessionSyncTracker) { tracker.isDone.Store(true) duration := tracker.endTime.Sub(tracker.startTime) - logrus.Infof("finished sychronizing api sessions [count: %d, syncId: %s, duration: %v]", len(apiSessions), tracker.syncId, duration) + logrus.Infof("finished synchronizing api sessions [count: %d, syncId: %s, duration: %v]", len(apiSessions), tracker.syncId, duration) } func (h *apiSessionAddedHandler) syncFailed(err error) { diff --git a/router/handler_edge_ctrl/hello.go b/router/handler_edge_ctrl/hello.go index 4d1550f95..fcbec9d34 100644 --- a/router/handler_edge_ctrl/hello.go +++ b/router/handler_edge_ctrl/hello.go @@ -17,15 +17,16 @@ package handler_edge_ctrl import ( + "strconv" + "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" "github.com/openziti/channel/v2/protobufs" + "github.com/openziti/ziti/common/build" "github.com/openziti/ziti/common/pb/edge_ctrl_pb" "github.com/openziti/ziti/controller/env" "github.com/openziti/ziti/router/fabric" - "github.com/openziti/ziti/common/build" "google.golang.org/protobuf/proto" - "strconv" ) type helloHandler struct { @@ -39,7 +40,7 @@ type helloHandler struct { } func NewHelloHandler(stateManager fabric.StateManager, listeners []*edge_ctrl_pb.Listener) *helloHandler { - //supportedProtocols, protocolPorts, and hostname is for backwards compatability with v0.26.3 and older controllers + //supportedProtocols, protocolPorts, and hostname is for backwards compatibility with v0.26.3 and older controllers var supportedProtocols []string var protocolPorts []string hostname := "" @@ -51,7 +52,7 @@ func NewHelloHandler(stateManager fabric.StateManager, listeners []*edge_ctrl_pb protocolPorts = append(protocolPorts, strconv.Itoa(int(listener.Advertise.Port))) if hostname != "" && hostname != listener.Advertise.Hostname { - pfxlog.Logger().Warnf("this router is configured to use different hostnames for different edge listeners. If the controller is v0.26.3 or earlier this is not supported. Advertise %s will be used for all protocls", listeners[0].Advertise.Value) + pfxlog.Logger().Warnf("this router is configured to use different hostnames for different edge listeners. If the controller is v0.26.3 or earlier this is not supported. Advertise %s will be used for all protocols", listeners[0].Advertise.Value) } hostname = listener.Advertise.Hostname diff --git a/router/handler_link/bind.go b/router/handler_link/bind.go index 236a5dfa0..be5937291 100644 --- a/router/handler_link/bind.go +++ b/router/handler_link/bind.go @@ -67,11 +67,9 @@ func (self *bindHandler) BindChannel(binding channel.Binding) error { "routerVersion": self.xlink.DestVersion(), }) - closeNotify := make(chan struct{}) - binding.GetChannel().SetLogicalName("l/" + self.xlink.Id()) binding.SetUserData(self.xlink.Id()) - binding.AddCloseHandler(newCloseHandler(self.xlink, self.ctrl, self.forwarder, closeNotify, self.xlinkRegistry)) + binding.AddCloseHandler(newCloseHandler(self.xlink, self.forwarder, self.xlinkRegistry)) binding.AddErrorHandler(newErrorHandler(self.xlink, self.ctrl)) binding.AddTypedReceiveHandler(newPayloadHandler(self.xlink, self.forwarder)) binding.AddTypedReceiveHandler(newAckHandler(self.xlink, self.forwarder)) diff --git a/router/handler_link/close.go b/router/handler_link/close.go index 8803fed9d..66ce5e443 100644 --- a/router/handler_link/close.go +++ b/router/handler_link/close.go @@ -19,38 +19,30 @@ package handler_link import ( "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" - "github.com/openziti/channel/v2/protobufs" - "github.com/openziti/ziti/common/pb/ctrl_pb" - "github.com/openziti/ziti/router/env" "github.com/openziti/ziti/router/forwarder" "github.com/openziti/ziti/router/xlink" - "sync/atomic" ) type closeHandler struct { link xlink.Xlink - ctrl env.NetworkControllers forwarder *forwarder.Forwarder - closeNotify chan struct{} - closed atomic.Bool xlinkRegistry xlink.Registry } -func newCloseHandler(link xlink.Xlink, ctrl env.NetworkControllers, forwarder *forwarder.Forwarder, closeNotify chan struct{}, registry xlink.Registry) *closeHandler { +func newCloseHandler(link xlink.Xlink, forwarder *forwarder.Forwarder, registry xlink.Registry) *closeHandler { return &closeHandler{ link: link, - ctrl: ctrl, forwarder: forwarder, - closeNotify: closeNotify, xlinkRegistry: registry, } } func (self *closeHandler) HandleClose(ch channel.Channel) { - if self.closed.CompareAndSwap(false, true) { + self.link.CloseOnce(func() { log := pfxlog.ContextLogger(ch.Label()). WithField("linkId", self.link.Id()). - WithField("routerId", self.link.DestinationId()) + WithField("routerId", self.link.DestinationId()). + WithField("iteration", self.link.Iteration()) self.forwarder.UnregisterLink(self.link) @@ -62,18 +54,5 @@ func (self *closeHandler) HandleClose(ch channel.Channel) { }() log.Info("link closed") - - self.link.HandleCloseNotification(func() { - self.ctrl.ForEach(func(controllerId string, ch channel.Channel) { - fault := &ctrl_pb.Fault{Subject: ctrl_pb.FaultSubject_LinkFault, Id: self.link.Id()} - if err := protobufs.MarshalTyped(fault).Send(ch); err == nil { - log.WithField("ctrlId", controllerId).Debug("transmitted link fault") - } else { - log.WithField("ctrlId", controllerId).WithError(err).Error("unexpected error transmitting link fault") - } - }) - }) - - close(self.closeNotify) - } + }) } diff --git a/router/internal/edgerouter/config.go b/router/internal/edgerouter/config.go index 3d759f303..b35095184 100644 --- a/router/internal/edgerouter/config.go +++ b/router/internal/edgerouter/config.go @@ -18,20 +18,21 @@ package edgerouter import ( "fmt" + "net" + "net/url" + "strconv" + "strings" + "time" + "github.com/michaelquigley/pfxlog" "github.com/mitchellh/mapstructure" + "github.com/openziti/identity" + "github.com/openziti/transport/v2" "github.com/openziti/ziti/common" "github.com/openziti/ziti/common/pb/edge_ctrl_pb" "github.com/openziti/ziti/router" - "github.com/openziti/identity" - "github.com/openziti/transport/v2" "github.com/pkg/errors" "github.com/spf13/pflag" - "net" - "net/url" - "strconv" - "strings" - "time" ) const ( @@ -256,7 +257,7 @@ func (config *Config) loadListener(rootConfigMap map[interface{}]interface{}) er edgeListener, err := parseEdgeListenerOptions(i, address, submap) if err != nil { - return fmt.Errorf("error parsing edge listner[%d]: %v", i, err) + return fmt.Errorf("error parsing edge listener[%d]: %v", i, err) } config.EdgeListeners = append(config.EdgeListeners, edgeListener) @@ -310,7 +311,7 @@ func parseEdgeListenerOptions(index int, address string, edgeListenerMap map[int } if advertisePort != addressPort { - pfxlog.Logger().Warnf("port in [listeners[%d].options.advertise] must equal port in [listeners[%d].address] for edge binding but did not. Got [%d] [%d]", index, index, advertisePort, addressPort) + pfxlog.Logger().Infof("advertised port [%d] in [listeners[%d].options.advertise] does not match the listening port [%d] in [listeners[%d].address].", index, advertisePort, index, addressPort) } return &edge_ctrl_pb.Listener{ @@ -365,7 +366,7 @@ func (config *Config) loadCsr(configMap map[interface{}]interface{}, pathPrefix for _, uristr := range config.Csr.Sans.UriAddresses { parsedUrl, err := url.Parse(uristr) if err != nil { - return fmt.Errorf("invalid SAN URI ecountered in configuration file: %s", uristr) + return fmt.Errorf("invalid SAN URI encountered in configuration file: %s", uristr) } config.Csr.Sans.UriAddressesParsed = append(config.Csr.Sans.UriAddressesParsed, parsedUrl) } @@ -373,7 +374,7 @@ func (config *Config) loadCsr(configMap map[interface{}]interface{}, pathPrefix for _, ipstr := range config.Csr.Sans.IpAddresses { ip := net.ParseIP(ipstr) if ip == nil { - return fmt.Errorf("invalid SAN IP address ecountered in configuration file: %s", ipstr) + return fmt.Errorf("invalid SAN IP address encountered in configuration file: %s", ipstr) } config.Csr.Sans.IpAddressesParsed = append(config.Csr.Sans.IpAddressesParsed, ip) } diff --git a/router/link/link_events.go b/router/link/link_events.go index 9392d7a44..1f12006a8 100644 --- a/router/link/link_events.go +++ b/router/link/link_events.go @@ -46,7 +46,7 @@ func (self *removeLinkDest) Handle(registry *linkRegistryImpl) { delete(registry.destinations, self.id) if dest != nil { for _, state := range dest.linkMap { - state.status = StatusDestRemoved + state.updateStatus(StatusDestRemoved) if link, _ := registry.GetLink(state.linkId); link != nil { if err := link.Close(); err != nil { pfxlog.Logger(). @@ -171,7 +171,7 @@ func (self *dialRequest) Handle(registry *linkRegistryImpl) { WithField("address", self.dial.Address). WithField("linkKey", linkKey) - if link, found := registry.linkMap[linkKey]; found { + if link, found := registry.GetLink(linkKey); found { registry.SendRouterLinkMessage(link, self.ctrlCh) continue } @@ -214,7 +214,9 @@ func (self *updateLinkStatusForLink) Handle(registry *linkRegistryImpl) { log := pfxlog.Logger().WithField("linkKey", link.Key()).WithField("linkId", link.Id()) dest, found := registry.destinations[link.DestinationId()] if !found { - log.WithField("linkDest", link.DestinationId()).Warnf("unable to mark link as %s, link destination not present in registry", self.status) + if link.IsDialed() { // if link was created by listener, rather than dialer we may not have an entry for it + log.WithField("linkDest", link.DestinationId()).Warnf("unable to mark link as %s, link destination not present in registry", self.status) + } return } @@ -230,33 +232,56 @@ func (self *updateLinkStatusForLink) Handle(registry *linkRegistryImpl) { return } - state.status = self.status + state.updateStatus(self.status) if state.status == StatusEstablished { state.connectedCount++ state.retryDelay = time.Duration(0) + state.ctrlsNotified = false + registry.triggerNotify() } if state.status == StatusLinkFailed { state.retryDelay = time.Duration(0) state.nextDial = time.Now() registry.evaluateLinkState(state) + state.addPendingLinkFault(link.Id(), link.Iteration()) } } -type updateLinkState struct { - linkState *linkState - status linkStatus +type addLinkFaultForReplacedLink struct { + link xlink.Xlink } -func (self *updateLinkState) Handle(registry *linkRegistryImpl) { - state := self.linkState - if state.status == StatusDestRemoved { +func (self *addLinkFaultForReplacedLink) Handle(registry *linkRegistryImpl) { + link := self.link + log := pfxlog.Logger().WithField("linkKey", link.Key()).WithField("linkId", link.Id()) + dest, found := registry.destinations[link.DestinationId()] + if !found { + if link.IsDialed() { // if link was created by listener, rather than dialer we may not have an entry for it + log.WithField("linkDest", link.DestinationId()).Info("link destination not present in registry") + } + return + } + + state, found := dest.linkMap[link.Key()] + if !found { + if link.IsDialed() { // if link was created by listener, rather than dialer we may not have an entry for it + log.WithField("linkDest", link.DestinationId()).Info("link state not present in registry") + } return } - state.status = self.status - if state.status == StatusDialFailed { - state.dialFailed(registry) + state.addPendingLinkFault(link.Id(), link.Iteration()) +} + +type updateLinkStatusToDialFailed struct { + linkState *linkState +} + +func (self *updateLinkStatusToDialFailed) Handle(registry *linkRegistryImpl) { + if self.linkState.status == StatusDialing { + self.linkState.updateStatus(StatusDialFailed) + self.linkState.dialFailed(registry) } } @@ -283,7 +308,7 @@ func (self *inspectLinkStatesEvent) Handle(registry *linkRegistryImpl) { Id: state.linkId, Key: state.linkKey, Status: state.status.String(), - DialAttempts: state.dialAttempts, + DialAttempts: state.dialAttempts.Load(), ConnectedCount: state.connectedCount, RetryDelay: state.retryDelay.String(), NextDial: state.nextDial.Format(time.RFC3339), @@ -292,6 +317,7 @@ func (self *inspectLinkStatesEvent) Handle(registry *linkRegistryImpl) { TargetBinding: state.listener.LocalBinding, DialerGroups: state.dialer.GetGroups(), DialerBinding: state.dialer.GetBinding(), + CtrlsNotified: state.ctrlsNotified, } if inspectLinkState.TargetBinding == "" { inspectLinkState.TargetBinding = "default" @@ -316,3 +342,28 @@ func (self *inspectLinkStatesEvent) GetResults(timeout time.Duration) ([]*inspec return nil, errors.New("timed out waiting for result") } } + +type markNewLinksNotified struct { + links []stateAndLink +} + +func (self *markNewLinksNotified) Handle(*linkRegistryImpl) { + for _, pair := range self.links { + if pair.state.status == StatusEstablished { + pair.state.ctrlsNotified = true + } + } +} + +type markFaultedLinksNotified struct { + successfullySent []stateAndFaults +} + +func (self *markFaultedLinksNotified) Handle(*linkRegistryImpl) { + for _, pair := range self.successfullySent { + state := pair.state + for _, fault := range pair.faults { + state.clearFault(fault) + } + } +} diff --git a/router/link/link_registry.go b/router/link/link_registry.go index fe4d1ecc5..e1a4fafa3 100644 --- a/router/link/link_registry.go +++ b/router/link/link_registry.go @@ -24,6 +24,7 @@ import ( "github.com/openziti/channel/v2/protobufs" "github.com/openziti/foundation/v2/goroutines" "github.com/openziti/identity" + "github.com/openziti/ziti/common/capabilities" "github.com/openziti/ziti/common/inspect" "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/router/env" @@ -40,6 +41,7 @@ type Env interface { GetXlinkDialers() []xlink.Dialer GetCloseNotify() <-chan struct{} GetLinkDialerPool() goroutines.Pool + GetRateLimiterPool() goroutines.Pool } func NewLinkRegistry(routerEnv Env) xlink.Registry { @@ -51,6 +53,7 @@ func NewLinkRegistry(routerEnv Env) xlink.Registry { env: routerEnv, destinations: map[string]*linkDest{}, linkStateQueue: &linkStateHeap{}, + triggerNotifyC: make(chan struct{}, 1), } go result.run() @@ -59,36 +62,39 @@ func NewLinkRegistry(routerEnv Env) xlink.Registry { } type linkRegistryImpl struct { - linkMap map[string]xlink.Xlink - linkByIdMap map[string]xlink.Xlink + linkMapLocks sync.RWMutex + linkMap map[string]xlink.Xlink + linkByIdMap map[string]xlink.Xlink sync.Mutex ctrls env.NetworkControllers - env Env - destinations map[string]*linkDest - linkStateQueue *linkStateHeap - events chan event + env Env + destinations map[string]*linkDest + linkStateQueue *linkStateHeap + events chan event + triggerNotifyC chan struct{} + notifyInProgress atomic.Bool } func (self *linkRegistryImpl) GetLink(linkKey string) (xlink.Xlink, bool) { - self.Lock() - defer self.Unlock() + self.linkMapLocks.RLock() + defer self.linkMapLocks.RUnlock() val, found := self.linkMap[linkKey] return val, found } func (self *linkRegistryImpl) GetLinkById(linkId string) (xlink.Xlink, bool) { - self.Lock() - defer self.Unlock() + self.linkMapLocks.RLock() + defer self.linkMapLocks.RUnlock() link, found := self.linkByIdMap[linkId] return link, found } func (self *linkRegistryImpl) DebugForgetLink(linkId string) bool { - self.Lock() - defer self.Unlock() + self.linkMapLocks.Lock() + defer self.linkMapLocks.Unlock() if link := self.linkByIdMap[linkId]; link != nil { delete(self.linkByIdMap, linkId) delete(self.linkMap, link.Key()) @@ -112,17 +118,19 @@ func (self *linkRegistryImpl) DialSucceeded(link xlink.Xlink) (xlink.Xlink, bool func (self *linkRegistryImpl) applyLink(link xlink.Xlink) (xlink.Xlink, bool) { log := logrus.WithField("dest", link.DestinationId()). WithField("linkProtocol", link.LinkProtocol()). - WithField("newLinkId", link.Id()) + WithField("newLinkId", link.Id()). + WithField("newLinkIteration", link.Iteration()) if link.IsClosed() { log.Info("link being registered, but is already closed, skipping registration") return nil, false } - if existing := self.linkMap[link.Key()]; existing != nil { + if existing, _ := self.GetLink(link.Key()); existing != nil { log = log.WithField("currentLinkId", existing.Id()) - // once we have an established link, we'll store the same id on both sides. Once that happens we can't use - // the link id to decide which duplicate to throw away, so we'll use the router ids instead - if existing.Id() < link.Id() || (existing.Id() == link.Id() && self.env.GetRouterId().Token < link.DestinationId()) { + log = log.WithField("currentLinkIteration", existing.Iteration()) + + // if the id is the same we want to throw away the older one, since the new one is a replacement + if existing.Id() < link.Id() { // give the other side a chance to close the link first and report it as a duplicate time.AfterFunc(30*time.Second, func() { if err := link.Close(); err != nil { @@ -131,47 +139,65 @@ func (self *linkRegistryImpl) applyLink(link xlink.Xlink) (xlink.Xlink, bool) { }) return existing, false } - log.Info("duplicate link detected. closing current link (current link id is > than new link id)") - legacyCtl := self.useLegacyLinkMgmtForOldCtrl() + // make sure we don't block the registry loop + go func() { + log.Info("duplicate link detected. closing current link (current link id is >= than new link id)") - self.ctrls.ForEach(func(ctrlId string, ch channel.Channel) { - // report link fault, then close link after allowing some time for circuits to be re-routed - fault := &ctrl_pb.Fault{ - Id: existing.Id(), - Subject: ctrl_pb.FaultSubject_LinkDuplicate, - } + legacyCtl := self.useLegacyLinkMgmtForOldCtrl() - if legacyCtl { - fault.Subject = ctrl_pb.FaultSubject_LinkFault - } + self.ctrls.ForEach(func(ctrlId string, ch channel.Channel) { + // report link fault, then close link after allowing some time for circuits to be re-routed + fault := &ctrl_pb.Fault{ + Id: existing.Id(), + Subject: ctrl_pb.FaultSubject_LinkDuplicate, + Iteration: existing.Iteration(), + } - if err := protobufs.MarshalTyped(fault).Send(ch); err != nil { - log.WithField("ctrlId", ctrlId). - WithError(err). - Error("failed to send router fault when duplicate link detected") - } - }) + if legacyCtl { + fault.Subject = ctrl_pb.FaultSubject_LinkFault + } - time.AfterFunc(5*time.Minute, func() { - _ = existing.Close() - }) + if err := protobufs.MarshalTyped(fault).WithTimeout(time.Second).SendAndWaitForWire(ch); err != nil { + log.WithField("ctrlId", ctrlId). + WithError(err). + Error("failed to send router fault when duplicate link detected") + } + }) + + time.AfterFunc(5*time.Minute, func() { + _ = existing.Close() + }) + }() } + + self.linkMapLocks.Lock() self.linkMap[link.Key()] = link self.linkByIdMap[link.Id()] = link + self.linkMapLocks.Unlock() + self.updateLinkStateEstablished(link) - self.SendRouterLinkMessage(link, self.ctrls.AllResponsiveCtrlChannels()...) return nil, true } func (self *linkRegistryImpl) LinkClosed(link xlink.Xlink) { - self.Lock() - defer self.Unlock() + markLinkStateClosed := false + self.linkMapLocks.Lock() if val := self.linkMap[link.Key()]; val == link { delete(self.linkMap, link.Key()) - self.updateLinkStateClosed(link) // only update link state to closed if this was the current link + markLinkStateClosed = true // only update link state to closed if this was the current link + } + + if val := self.linkByIdMap[link.Id()]; val == link { + delete(self.linkByIdMap, link.Id()) + } + self.linkMapLocks.Unlock() + + if markLinkStateClosed { + self.updateLinkStateClosed(link) + } else { + self.addLinkFaultForReplacedLink(link) } - delete(self.linkByIdMap, link.Id()) } func (self *linkRegistryImpl) Shutdown() { @@ -193,6 +219,7 @@ func (self *linkRegistryImpl) SendRouterLinkMessage(link xlink.Xlink, channels . DestRouterId: link.DestinationId(), LinkProtocol: link.LinkProtocol(), DialAddress: link.DialAddress(), + Iteration: link.Iteration(), }, }, } @@ -202,9 +229,17 @@ func (self *linkRegistryImpl) SendRouterLinkMessage(link xlink.Xlink, channels . WithField("dest", link.DestinationId()). WithField("linkProtocol", link.LinkProtocol()) + if len(channels) == 0 { + log.Info("no controllers available to notify of link") + } + for _, ch := range channels { - if err := protobufs.MarshalTyped(linkMsg).Send(ch); err != nil { - log.WithError(err).Error("error sending router link message") + if !capabilities.IsCapable(ch, capabilities.ControllerSingleRouterLinkSource) || link.IsDialed() { + if err := protobufs.MarshalTyped(linkMsg).Send(ch); err != nil { + log.WithError(err).Error("error sending router link message") + } + log.WithField("ctrlId", ch.Id()).Info("notified controller of new link") + } } } @@ -230,8 +265,8 @@ func (self *linkRegistryImpl) Run(env.RouterEnv) error { func (self *linkRegistryImpl) Iter() <-chan xlink.Xlink { result := make(chan xlink.Xlink, len(self.linkMap)) go func() { - self.Lock() - defer self.Unlock() + self.linkMapLocks.RLock() + defer self.linkMapLocks.RUnlock() for _, link := range self.linkMap { select { @@ -245,14 +280,22 @@ func (self *linkRegistryImpl) Iter() <-chan xlink.Xlink { } func (self *linkRegistryImpl) NotifyOfReconnect(ch channel.Channel) { + self.Lock() + defer self.Unlock() + + alwaysSend := !capabilities.IsCapable(ch, capabilities.ControllerSingleRouterLinkSource) + routerLinks := &ctrl_pb.RouterLinks{} for link := range self.Iter() { - routerLinks.Links = append(routerLinks.Links, &ctrl_pb.RouterLinks_RouterLink{ - Id: link.Id(), - DestRouterId: link.DestinationId(), - LinkProtocol: link.LinkProtocol(), - DialAddress: link.DialAddress(), - }) + if alwaysSend || link.IsDialed() { + routerLinks.Links = append(routerLinks.Links, &ctrl_pb.RouterLinks_RouterLink{ + Id: link.Id(), + DestRouterId: link.DestinationId(), + LinkProtocol: link.LinkProtocol(), + DialAddress: link.DialAddress(), + Iteration: link.Iteration(), + }) + } } if err := protobufs.MarshalTyped(routerLinks).Send(ch); err != nil { @@ -288,6 +331,24 @@ func (self *linkRegistryImpl) DialRequested(ctrlCh channel.Channel, dial *ctrl_p }) } +func (self *linkRegistryImpl) markNewLinksNotified(links []stateAndLink) { + self.queueEvent(&markNewLinksNotified{ + links: links, + }) +} + +func (self *linkRegistryImpl) markFaultedLinksNotified(successfullySent []stateAndFaults) { + self.queueEvent(&markFaultedLinksNotified{ + successfullySent: successfullySent, + }) +} + +func (self *linkRegistryImpl) dialFailed(state *linkState) { + self.queueEvent(&updateLinkStatusToDialFailed{ + linkState: state, + }) +} + func (self *linkRegistryImpl) queueEvent(evt event) { select { case <-self.env.GetCloseNotify(): @@ -306,8 +367,11 @@ func (self *linkRegistryImpl) run() { select { case evt := <-self.events: evt.Handle(self) + case <-self.triggerNotifyC: + self.notifyControllersOfLinks() case <-queueCheckTicker.C: self.evaluateLinkStateQueue() + self.notifyControllersOfLinks() case <-fullScanTicker.C: self.evaluateDestinations() case <-self.env.GetCloseNotify(): @@ -316,6 +380,13 @@ func (self *linkRegistryImpl) run() { } } +func (self *linkRegistryImpl) triggerNotify() { + select { + case self.triggerNotifyC <- struct{}{}: + default: + } +} + func (self *linkRegistryImpl) evaluateLinkStateQueue() { now := time.Now() for len(*self.linkStateQueue) > 0 { @@ -341,7 +412,7 @@ func (self *linkRegistryImpl) evaluateDestinations() { // If the link is not valid, allow it to be re-dialed state.retryDelay = time.Duration(0) state.nextDial = time.Now() - state.status = StatusLinkFailed + state.updateStatus(StatusLinkFailed) } else { hasEstablishedLinks = true } @@ -365,8 +436,9 @@ func (self *linkRegistryImpl) evaluateLinkState(state *linkState) { couldDial := state.status != StatusEstablished && state.status != StatusDialing && state.nextDial.Before(time.Now()) if couldDial { - state.status = StatusDialing - state.dialAttempts++ + state.updateStatus(StatusDialing) + iteration := state.dialAttempts.Add(1) + log = log.WithField("linkId", state.linkId).WithField("iteration", iteration) log.Info("queuing link to dial") err := self.env.GetLinkDialerPool().QueueOrError(func() { @@ -381,10 +453,7 @@ func (self *linkRegistryImpl) evaluateLinkState(state *linkState) { link, err := state.dialer.Dial(state) if err != nil { log.WithError(err).Error("error dialing link") - self.queueEvent(&updateLinkState{ - linkState: state, - status: StatusDialFailed, - }) + self.dialFailed(state) return } @@ -393,16 +462,13 @@ func (self *linkRegistryImpl) evaluateLinkState(state *linkState) { if existing != nil { self.updateLinkStateEstablished(link) } else { - self.queueEvent(&updateLinkState{ - linkState: state, - status: StatusDialFailed, - }) + self.dialFailed(state) } } }) if err != nil { log.WithError(err).Error("unable to queue link dial, see pool error") - state.status = StatusQueueFailed + state.updateStatus(StatusQueueFailed) state.dialFailed(self) } } @@ -422,6 +488,12 @@ func (self *linkRegistryImpl) updateLinkStateClosed(link xlink.Xlink) { }) } +func (self *linkRegistryImpl) addLinkFaultForReplacedLink(link xlink.Xlink) { + self.queueEvent(&addLinkFaultForReplacedLink{ + link: link, + }) +} + func (self *linkRegistryImpl) Inspect(timeout time.Duration) *inspect.LinksInspectResult { evt := &inspectLinkStatesEvent{ result: atomic.Pointer[[]*inspect.LinkDest]{}, @@ -465,3 +537,180 @@ func (self *linkRegistryImpl) GetLinkKey(dialerBinding, protocol, dest, listener return fmt.Sprintf("%s->%s:%s->%s", dialerBinding, protocol, dest, listenerBinding) } + +func (self *linkRegistryImpl) notifyControllersOfLinks() { + if self.notifyInProgress.Load() { + pfxlog.Logger().WithField("op", "link-notify").Info("new link notification already in progress, exiting") + return + } + + var links []stateAndLink + var faults []stateAndFaults + + for _, dest := range self.destinations { + for _, state := range dest.linkMap { + if !state.ctrlsNotified { + if state.status == StatusEstablished { + link, _ := self.GetLink(state.linkKey) + if link == nil { + pfxlog.Logger(). + WithField("op", "link-notify"). + WithField("linkId", state.linkId). + Info("link not found for link key on established link, marking failed") + state.updateStatus(StatusDialFailed) + state.dialFailed(self) + } else if link.IsDialed() { + links = append(links, stateAndLink{ + state: state, + link: link, + }) + } + + // if we have an established link, don't send faults for it + if link != nil { + state.clearFaultsForLinkId(link.Id()) + } + } + } + + if len(state.linkFaults) > 0 { + var linkFaults []linkFault + linkFaults = append(linkFaults, state.linkFaults...) + faults = append(faults, stateAndFaults{ + state: state, + faults: linkFaults, + }) + } + } + } + + if len(links) == 0 && len(faults) == 0 { + return + } + + pfxlog.Logger().WithField("op", "link-notify").Info("attempting to queue link notifications") + self.notifyInProgress.Store(true) + err := self.env.GetRateLimiterPool().QueueOrError(func() { + pfxlog.Logger().WithField("op", "link-notify").Info("link notifications starting") + + defer func() { + self.notifyInProgress.Store(false) + pfxlog.Logger().WithField("op", "link-notify").Info("link notifications exiting") + }() + + if len(links) > 0 { + self.sendNewLinks(links) + } + + if len(faults) > 0 { + self.sendLinkFaults(faults) + } + }) + + if err != nil { + pfxlog.Logger().WithField("op", "link-notify").Info("unable to queue link notifications") + self.notifyInProgress.Store(false) + } +} + +func (self *linkRegistryImpl) sendNewLinks(links []stateAndLink) { + routerLinks := &ctrl_pb.RouterLinks{} + for _, pair := range links { + link := pair.link + routerLinks.Links = append(routerLinks.Links, &ctrl_pb.RouterLinks_RouterLink{ + Id: link.Id(), + DestRouterId: link.DestinationId(), + LinkProtocol: link.LinkProtocol(), + DialAddress: link.DialAddress(), + Iteration: link.Iteration(), + }) + } + + allSent := true + for ctrlId, ctrl := range self.ctrls.GetAll() { + connectedChecker := ctrl.Channel().Underlay().(interface{ IsConnected() bool }) + log := pfxlog.Logger().WithField("ctrlId", ctrlId).WithField("op", "link-notify") + if connectedChecker.IsConnected() { + msgEnv := protobufs.MarshalTyped(routerLinks).WithTimeout(10 * time.Second) + if err := msgEnv.SendAndWaitForWire(ctrl.Channel()); err != nil { + log.WithError(err).Error("timeout sending new router links") + allSent = false + + for _, pair := range links { + log.WithField("linkId", pair.link.Id()). + WithField("iteration", pair.link.Iteration()). + Info("failed to notify controller of new link") + } + } else { + for _, pair := range links { + log.WithField("linkId", pair.link.Id()). + WithField("iteration", pair.link.Iteration()). + Info("notified controller of new link") + } + } + } + } + + if allSent { + self.markNewLinksNotified(links) + } +} + +func (self *linkRegistryImpl) sendLinkFaults(list []stateAndFaults) { + var successfullySent []stateAndFaults + for _, item := range list { + var sent []linkFault + + for _, fault := range item.faults { + allSent := true + for ctrlId, ctrl := range self.ctrls.GetAll() { + faultMsg := &ctrl_pb.Fault{ + Subject: ctrl_pb.FaultSubject_LinkFault, + Id: fault.linkId, + Iteration: fault.iteration, + } + + log := pfxlog.Logger().WithField("ctrlId", ctrlId). + WithField("op", "link-notify"). + WithField("linkId", fault.linkId). + WithField("iteration", fault.iteration) + + connectedChecker := ctrl.Channel().Underlay().(interface{ IsConnected() bool }) + + if connectedChecker.IsConnected() { + msgEnv := protobufs.MarshalTyped(faultMsg).WithTimeout(10 * time.Second) + if err := msgEnv.SendAndWaitForWire(ctrl.Channel()); err != nil { + log.WithError(err).Error("timeout sending link fault") + allSent = false + log.Info("failed to notify controller of link fault") + } else { + log.Info("notified controller of link fault") + } + } + } + if allSent { + sent = append(sent, fault) + } + } + if len(sent) > 0 { + successfullySent = append(successfullySent, stateAndFaults{ + state: item.state, + faults: sent, + }) + } + } + + if len(successfullySent) > 0 { + self.markFaultedLinksNotified(successfullySent) + } +} + +type stateAndLink struct { + state *linkState + link xlink.Xlink +} + +type stateAndFaults struct { + state *linkState + faults []linkFault +} diff --git a/router/link/link_state.go b/router/link/link_state.go index b42fd76f4..c90452f20 100644 --- a/router/link/link_state.go +++ b/router/link/link_state.go @@ -18,8 +18,10 @@ package link import ( "container/heap" + "github.com/michaelquigley/pfxlog" "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/router/xlink" + "sync/atomic" "time" ) @@ -59,18 +61,36 @@ func (self *linkDest) update(update *linkDestUpdate) { } } +type linkFault struct { + linkId string + iteration uint32 +} + type linkState struct { linkKey string linkId string status linkStatus - dialAttempts uint - connectedCount uint + dialAttempts atomic.Uint64 + connectedCount uint64 retryDelay time.Duration nextDial time.Time dest *linkDest listener *ctrl_pb.Listener dialer xlink.Dialer - allowedDials int + allowedDials int64 + ctrlsNotified bool + linkFaults []linkFault +} + +func (self *linkState) updateStatus(status linkStatus) { + log := pfxlog.Logger(). + WithField("key", self.linkKey). + WithField("oldState", self.status). + WithField("newState", status). + WithField("linkId", self.linkId). + WithField("iteration", self.dialAttempts.Load()) + self.status = status + log.Info("status updated") } func (self *linkState) GetLinkKey() string { @@ -97,6 +117,47 @@ func (self *linkState) GetRouterVersion() string { return self.dest.version } +func (self *linkState) GetIteration() uint32 { + return uint32(self.dialAttempts.Load()) +} + +func (self *linkState) addPendingLinkFault(linkId string, iteration uint32) { + for _, fault := range self.linkFaults { + if fault.linkId == linkId { + if fault.iteration < iteration { + fault.iteration = iteration + } + return + } + } + self.linkFaults = append(self.linkFaults, linkFault{ + linkId: linkId, + iteration: iteration, + }) +} + +func (self *linkState) clearFaultsForLinkId(linkId string) { + faults := self.linkFaults + self.linkFaults = nil + + for _, fault := range faults { + if fault.linkId != linkId { + self.linkFaults = append(self.linkFaults, fault) + } + } +} + +func (self *linkState) clearFault(toClear linkFault) { + faults := self.linkFaults + self.linkFaults = nil + + for _, fault := range faults { + if fault.linkId != toClear.linkId || fault.iteration > toClear.iteration { + self.linkFaults = append(self.linkFaults, fault) + } + } +} + func (self *linkState) dialFailed(registry *linkRegistryImpl) { if self.allowedDials > 0 { self.allowedDials-- diff --git a/router/router.go b/router/router.go index f82c035f4..59cfb2a3c 100644 --- a/router/router.go +++ b/router/router.go @@ -21,12 +21,6 @@ import ( "context" "encoding/json" "fmt" - "github.com/openziti/foundation/v2/debugz" - "github.com/openziti/foundation/v2/goroutines" - "github.com/openziti/xweb/v2" - "github.com/openziti/ziti/common/config" - "github.com/openziti/ziti/router/link" - metrics2 "github.com/rcrowley/go-metrics" "io/fs" "os" "path" @@ -35,6 +29,13 @@ import ( "sync/atomic" "time" + "github.com/openziti/foundation/v2/debugz" + "github.com/openziti/foundation/v2/goroutines" + "github.com/openziti/xweb/v2" + "github.com/openziti/ziti/common/config" + "github.com/openziti/ziti/router/link" + metrics2 "github.com/rcrowley/go-metrics" + gosundheit "github.com/AppsFlyer/go-sundheit" "github.com/AppsFlyer/go-sundheit/checks" "github.com/michaelquigley/pfxlog" @@ -348,10 +349,10 @@ func (self *Router) startProfiling() { } func (self *Router) initRateLimiterPool() error { - linkDialerPoolConfig := goroutines.PoolConfig{ + rateLimiterPoolConfig := goroutines.PoolConfig{ QueueSize: uint32(self.forwarder.Options.RateLimiter.QueueLength), MinWorkers: 0, - MaxWorkers: uint32(self.forwarder.Options.LinkDial.WorkerCount), + MaxWorkers: uint32(self.forwarder.Options.RateLimiter.WorkerCount), IdleTime: 30 * time.Second, CloseNotify: self.GetCloseNotify(), PanicHandler: func(err interface{}) { @@ -359,11 +360,11 @@ func (self *Router) initRateLimiterPool() error { }, } - fabricMetrics.ConfigureGoroutinesPoolMetrics(&linkDialerPoolConfig, self.GetMetricsRegistry(), "pool.link.dialer") + fabricMetrics.ConfigureGoroutinesPoolMetrics(&rateLimiterPoolConfig, self.GetMetricsRegistry(), "pool.rate_limiter") - rateLimiterPool, err := goroutines.NewPool(linkDialerPoolConfig) + rateLimiterPool, err := goroutines.NewPool(rateLimiterPoolConfig) if err != nil { - return errors.Wrap(err, "error creating rate limted pool") + return errors.Wrap(err, "error creating rate limited pool") } self.rateLimiterPool = rateLimiterPool @@ -578,7 +579,7 @@ func (self *Router) connectToController(addr transport.Address, bindHandler chan if buf, err := proto.Marshal(listeners); err != nil { return errors.Wrap(err, "unable to marshal Listeners") } else { - attributes[int32(ctrl_pb.ContentType_ListenersHeader)] = buf + attributes[int32(ctrl_pb.ControlHeaders_ListenersHeader)] = buf } } @@ -591,7 +592,7 @@ func (self *Router) connectToController(addr transport.Address, bindHandler chan if buf, err := proto.Marshal(routerMeta); err != nil { return errors.Wrap(err, "unable to router metadata") } else { - attributes[int32(ctrl_pb.ContentType_RouterMetadataHeader)] = buf + attributes[int32(ctrl_pb.ControlHeaders_RouterMetadataHeader)] = buf } var channelRef concurrenz.AtomicValue[channel.Channel] @@ -619,6 +620,11 @@ func (self *Router) connectToController(addr transport.Address, bindHandler chan } channelRef.Store(ch) + // If there are multiple controllers we may have to catch up the controllers that connected later + // with things that have already happened because we had state from other controllers, such as + // links + reconnectHandler() + return nil } diff --git a/router/xgress_edge/dialer.go b/router/xgress_edge/dialer.go index 4967ac050..27bdb094f 100644 --- a/router/xgress_edge/dialer.go +++ b/router/xgress_edge/dialer.go @@ -99,6 +99,10 @@ func (dialer *dialer) Dial(params xgress.DialParams) (xt.PeerData, error) { dialRequest.Headers[edge.PublicKeyHeader] = pk } + if marker, ok := circuitId.Data[edge.ConnectionMarkerHeader]; ok { + dialRequest.Headers[edge.ConnectionMarkerHeader] = marker + } + appData, hasAppData := circuitId.Data[edge.AppDataHeader] if hasAppData { dialRequest.Headers[edge.AppDataHeader] = appData diff --git a/router/xgress_edge/fabric.go b/router/xgress_edge/fabric.go index 43e2e115b..4d5c7c006 100644 --- a/router/xgress_edge/fabric.go +++ b/router/xgress_edge/fabric.go @@ -125,9 +125,10 @@ func (self *edgeTerminator) close(notify bool, reason string) { if terminatorId := self.terminatorId.Load(); terminatorId != "" { if self.terminatorId.CompareAndSwap(terminatorId, "") { logger.Debug("removing terminator on router") - self.edgeClientConn.listener.factory.hostedServices.Delete(terminatorId) self.state.Store(TerminatorStateDeleting) + self.edgeClientConn.listener.factory.hostedServices.Delete(terminatorId) + logger.Info("removing terminator on controller") ctrlCh := self.edgeClientConn.listener.factory.ctrls.AnyCtrlChannel() if ctrlCh == nil { diff --git a/router/xgress_edge/hosted.go b/router/xgress_edge/hosted.go index 15e88d554..09faf7bdf 100644 --- a/router/xgress_edge/hosted.go +++ b/router/xgress_edge/hosted.go @@ -112,13 +112,20 @@ func (self *hostedServiceRegistry) scanForRetries() { } func (self *hostedServiceRegistry) tryEstablish(terminator *edgeTerminator) { - terminator.state.Store(TerminatorStateEstablishing) + log := pfxlog.Logger().WithField("terminatorId", terminator.Id()). + WithField("token", terminator.token). + WithField("state", terminator.state.Load().String()) + + if !terminator.state.CompareAndSwap(TerminatorStatePendingEstablishment, TerminatorStateEstablishing) { + log.Info("terminator not pending, not going to try to establish") + return + } + err := self.env.GetRateLimiterPool().QueueOrError(func() { self.establishTerminatorWithRetry(terminator) }) if err != nil { - terminator.state.Store(TerminatorStatePendingEstablishment) - pfxlog.Logger().WithField("terminatorId", terminator.Id()).Info("rate limited: unable to queue to establish") + log.Info("rate limited: unable to queue to establish") self.retriesPending = true } } @@ -171,7 +178,7 @@ func (self *hostedServiceRegistry) cleanupDuplicates(newest *edgeTerminator) { terminator.close(false, "duplicate terminator") // don't notify, channel is already closed, we can't send messages self.services.Delete(key) pfxlog.Logger().WithField("routerId", terminator.edgeClientConn.listener.id.Token). - WithField("sessionToken", terminator.token). + WithField("token", terminator.token). WithField("instance", terminator.instance). WithField("terminatorId", terminator.terminatorId.Load()). WithField("duplicateOf", newest.terminatorId.Load()). @@ -189,7 +196,7 @@ func (self *hostedServiceRegistry) unbindSession(connId uint32, sessionToken str terminator.close(false, "unbind successful") // don't notify, sdk asked us to unbind self.services.Delete(key) pfxlog.Logger().WithField("routerId", terminator.edgeClientConn.listener.id.Token). - WithField("sessionToken", sessionToken). + WithField("token", sessionToken). WithField("terminatorId", terminator.terminatorId.Load()). Info("terminator removed") atLeastOneRemoved = true @@ -212,7 +219,9 @@ func (self *hostedServiceRegistry) getRelatedTerminators(sessionToken string, pr } func (self *hostedServiceRegistry) establishTerminatorWithRetry(terminator *edgeTerminator) { - log := logrus.WithField("terminatorId", terminator.terminatorId.Load()) + log := logrus. + WithField("terminatorId", terminator.terminatorId.Load()). + WithField("token", terminator.token) if state := terminator.state.Load(); state != TerminatorStateEstablishing { log.WithField("state", state.String()).Info("not attempting to establish terminator, not in establishing state") @@ -228,10 +237,11 @@ func (self *hostedServiceRegistry) establishTerminatorWithRetry(terminator *edge return backoff.Permanent(fmt.Errorf("terminator state is %v, stopping terminator creation for terminator %s", state.String(), terminator.terminatorId.Load())) } + if terminator.terminatorId.Load() == "" { + return backoff.Permanent(fmt.Errorf("terminator has been closed, stopping terminator creation")) + } - var err error - log.Info("attempting to establish terminator") - err = self.establishTerminator(terminator) + err := self.establishTerminator(terminator) if err != nil && terminator.state.Load() != TerminatorStateEstablishing { return backoff.Permanent(err) } @@ -260,10 +270,16 @@ func (self *hostedServiceRegistry) establishTerminator(terminator *edgeTerminato log := pfxlog.Logger(). WithField("routerId", factory.env.GetRouterId().Token). - WithField("terminatorId", terminator.terminatorId.Load()) + WithField("terminatorId", terminator.terminatorId.Load()). + WithField("token", terminator.token) + + terminatorId := terminator.terminatorId.Load() + if terminatorId == "" { + return fmt.Errorf("edge link is closed, stopping terminator creation for terminator %s", terminatorId) + } request := &edge_ctrl_pb.CreateTerminatorV2Request{ - Address: terminator.terminatorId.Load(), + Address: terminatorId, SessionToken: terminator.token, Fingerprints: terminator.edgeClientConn.fingerprints.Prints(), PeerData: terminator.hostData, @@ -281,12 +297,14 @@ func (self *hostedServiceRegistry) establishTerminator(terminator *edgeTerminato return errors.New(errStr) } + log.Info("sending create terminator v2 request") + err := protobufs.MarshalTyped(request).WithTimeout(timeout).SendAndWaitForWire(ctrlCh) if err != nil { return err } - if self.waitForTerminatorCreated(terminator.terminatorId.Load(), 10*time.Second) { + if self.waitForTerminatorCreated(terminatorId, 10*time.Second) { return nil } @@ -295,7 +313,7 @@ func (self *hostedServiceRegistry) establishTerminator(terminator *edgeTerminato return errors.Errorf("timeout waiting for response to create terminator request for terminator %v", terminator.terminatorId.Load()) } -func (self *hostedServiceRegistry) HandleCreateTerminatorResponse(msg *channel.Message, ctrlCh channel.Channel) { +func (self *hostedServiceRegistry) HandleCreateTerminatorResponse(msg *channel.Message, _ channel.Channel) { log := pfxlog.Logger().WithField("routerId", self.env.GetRouterId().Token) response := &edge_ctrl_pb.CreateTerminatorV2Response{} @@ -313,6 +331,11 @@ func (self *hostedServiceRegistry) HandleCreateTerminatorResponse(msg *channel.M return } + if response.Result != edge_ctrl_pb.CreateTerminatorResult_Success { + terminator.close(true, response.Msg) + return + } + if terminator.state.CompareAndSwap(TerminatorStateEstablishing, TerminatorStateEstablished) { self.notifyTerminatorCreated(response.TerminatorId) log.Info("received terminator created notification") diff --git a/router/xgress_edge/listener.go b/router/xgress_edge/listener.go index c3a215e33..ae3e8c515 100644 --- a/router/xgress_edge/listener.go +++ b/router/xgress_edge/listener.go @@ -19,16 +19,15 @@ package xgress_edge import ( "encoding/binary" "fmt" + "time" + "github.com/openziti/ziti/common/capabilities" "github.com/openziti/ziti/common/cert" fabricMetrics "github.com/openziti/ziti/common/metrics" - "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/common/pb/edge_ctrl_pb" "github.com/openziti/ziti/controller/idgen" "github.com/pkg/errors" "google.golang.org/protobuf/proto" - "math/big" - "time" "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" @@ -40,6 +39,13 @@ import ( "github.com/openziti/ziti/router/xgress_common" ) +var peerHeaders = []uint32{ + edge.PublicKeyHeader, + edge.CallerIdHeader, + edge.AppDataHeader, + edge.ConnectionMarkerHeader, +} + type listener struct { id *identity.TokenId factory *Factory @@ -152,7 +158,7 @@ func (self *edgeClientConn) processConnect(req *channel.Message, ch channel.Chan log.Debug("dialing fabric") peerData := make(map[uint32][]byte) - for _, key := range []uint32{edge.PublicKeyHeader, edge.CallerIdHeader, edge.AppDataHeader} { + for _, key := range peerHeaders { if pk, found := req.Headers[int32(key)]; found { peerData[key] = pk } @@ -191,7 +197,7 @@ func (self *edgeClientConn) processBind(req *channel.Message, ch channel.Channel if ctrlCh == nil { errStr := "no controller available, cannot create terminator" pfxlog.ContextLogger(ch.Label()). - WithField("sessionToken", string(req.Body)). + WithField("token", string(req.Body)). WithFields(edge.GetLoggerFields(req)). WithField("routerId", self.listener.id.Token). Error(errStr) @@ -199,14 +205,7 @@ func (self *edgeClientConn) processBind(req *channel.Message, ch channel.Channel return } - supportsCreateTerminatorV2 := false - headers := ctrlCh.Underlay().Headers() - if val, found := headers[int32(ctrl_pb.ContentType_CapabilitiesHeader)]; found { - capabilitiesMask := &big.Int{} - capabilitiesMask.SetBytes(val) - supportsCreateTerminatorV2 = capabilitiesMask.Bit(capabilities.ControllerCreateTerminatorV2) == 1 - } - + supportsCreateTerminatorV2 := capabilities.IsCapable(ctrlCh, capabilities.ControllerCreateTerminatorV2) if supportsCreateTerminatorV2 { self.processBindV2(req, ch) } else { @@ -218,7 +217,7 @@ func (self *edgeClientConn) processBindV1(req *channel.Message, ch channel.Chann token := string(req.Body) log := pfxlog.ContextLogger(ch.Label()). - WithField("sessionToken", token). + WithField("token", token). WithFields(edge.GetLoggerFields(req)). WithField("routerId", self.listener.id.Token) @@ -316,7 +315,7 @@ func (self *edgeClientConn) processBindV2(req *channel.Message, ch channel.Chann token := string(req.Body) log := pfxlog.ContextLogger(ch.Label()). - WithField("sessionToken", token). + WithField("token", token). WithFields(edge.GetLoggerFields(req)). WithField("routerId", self.listener.id.Token) @@ -335,7 +334,7 @@ func (self *edgeClientConn) processBindV2(req *channel.Message, ch channel.Chann terminatorId = terminator.terminatorId.Load() log = log.WithField("terminatorId", terminatorId) - // everything is the same, we can re-use the terminator + // everything is the same, we can reuse the terminator if terminator.edgeClientConn == self && terminator.token == token { log.Info("duplicate create terminator request") self.sendStateConnectedReply(req, nil) @@ -405,20 +404,27 @@ func (self *edgeClientConn) processBindV2(req *channel.Message, ch channel.Chann notifyEstablished: notifyEstablished, } terminator.terminatorId.Store(terminatorId) - - log.Info("establishing terminator") + terminator.state.Store(TerminatorStatePendingEstablishment) // need to remove session remove listener on close terminator.onClose = self.listener.factory.stateManager.AddEdgeSessionRemovedListener(token, func(token string) { terminator.close(true, "session ended") }) - self.sendStateConnectedReply(req, nil) + // If the session was recently removed, the call to AddEdgeSessionRemovedListener will have asynchronously closed + // the terminator + if self.listener.factory.stateManager.WasSessionRecentlyRemoved(token) { + log.Info("invalid session, not establishing terminator") + } else { + log.Info("establishing terminator") - self.listener.factory.hostedServices.EstablishTerminator(terminator) - if listenerId == "" { - // only removed dupes with a scan if we don't have an sdk provided key - self.listener.factory.hostedServices.cleanupDuplicates(terminator) + self.sendStateConnectedReply(req, nil) + + self.listener.factory.hostedServices.EstablishTerminator(terminator) + if listenerId == "" { + // only removed dupes with a scan if we don't have an sdk provided key + self.listener.factory.hostedServices.cleanupDuplicates(terminator) + } } } @@ -430,7 +436,7 @@ func (self *edgeClientConn) processUnbind(req *channel.Message, _ channel.Channe if !atLeastOneTerminatorRemoved { pfxlog.Logger(). WithField("connId", connId). - WithField("sessionToken", token). + WithField("token", token). Info("no terminator found to unbind for token") } } @@ -450,7 +456,7 @@ func (self *edgeClientConn) removeTerminator(ctrlCh channel.Channel, token, term func (self *edgeClientConn) processUpdateBind(req *channel.Message, ch channel.Channel) { token := string(req.Body) - log := pfxlog.ContextLogger(ch.Label()).WithField("sessionToken", token).WithFields(edge.GetLoggerFields(req)) + log := pfxlog.ContextLogger(ch.Label()).WithField("token", token).WithFields(edge.GetLoggerFields(req)) terminators := self.listener.factory.hostedServices.getRelatedTerminators(token, self) if len(terminators) == 0 { diff --git a/router/xgress_edge_tunnel/servicepoll.go b/router/xgress_edge_tunnel/servicepoll.go index 02fc7c80d..7da287874 100644 --- a/router/xgress_edge_tunnel/servicepoll.go +++ b/router/xgress_edge_tunnel/servicepoll.go @@ -17,16 +17,17 @@ limitations under the License. */ import ( + "reflect" + "sync" + "time" + "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" "github.com/openziti/edge-api/rest_model" - "github.com/openziti/ziti/tunnel/intercept" "github.com/openziti/sdk-golang/ziti" + "github.com/openziti/ziti/tunnel/intercept" cmap "github.com/orcaman/concurrent-map/v2" "github.com/sirupsen/logrus" - "reflect" - "sync" - "time" ) func newServicePoller(fabricProvider *fabricProvider) *servicePoller { @@ -57,7 +58,7 @@ func (self *servicePoller) handleServiceListUpdate(ch channel.Channel, lastUpdat return } - logrus.Debugf("procesing service updates with %v services", len(services)) + logrus.Debugf("processing service updates with %v services", len(services)) self.servicesLastUpdateToken.Set(ch.Id(), lastUpdateToken) diff --git a/router/xlink/xlink.go b/router/xlink/xlink.go index 87e423f4b..9bbbb237d 100644 --- a/router/xlink/xlink.go +++ b/router/xlink/xlink.go @@ -18,12 +18,12 @@ package xlink import ( "github.com/openziti/channel/v2" - "github.com/openziti/ziti/common/inspect" - "github.com/openziti/ziti/common/pb/ctrl_pb" - "github.com/openziti/ziti/router/xgress" "github.com/openziti/identity" "github.com/openziti/metrics" "github.com/openziti/transport/v2" + "github.com/openziti/ziti/common/inspect" + "github.com/openziti/ziti/common/pb/ctrl_pb" + "github.com/openziti/ziti/router/xgress" "time" ) @@ -94,6 +94,7 @@ type Dial interface { GetAddress() string GetLinkProtocol() string GetRouterVersion() string + GetIteration() uint32 } type BackoffConfig interface { @@ -129,11 +130,13 @@ type Xlink interface { DestVersion() string LinkProtocol() string DialAddress() string - HandleCloseNotification(f func()) + CloseOnce(f func()) IsClosed() bool InspectLink() *inspect.LinkInspectDetail GetAddresses() []*ctrl_pb.LinkConn IsDialed() bool + Iteration() uint32 + AreFaultsSent() bool } type Forwarder interface { diff --git a/router/xlink_transport/dialer.go b/router/xlink_transport/dialer.go index 4f5d2ed33..21cb4e6de 100644 --- a/router/xlink_transport/dialer.go +++ b/router/xlink_transport/dialer.go @@ -77,14 +77,14 @@ func (self *dialer) Dial(dial xlink.Dial) (xlink.Xlink, error) { xli, err = self.dialSingle(linkId, address, connId, dial) } if err != nil { - return nil, errors.Wrapf(err, "error dialing outgoing link [l/%s]", linkId.Token) + return nil, errors.Wrapf(err, "error dialing outgoing link [l/%s@%v]", linkId.Token, dial.GetIteration()) } if err = self.acceptor.Accept(xli); err != nil { if closeErr := xli.Close(); closeErr != nil { pfxlog.Logger().WithError(closeErr).WithField("acceptErr", err).Error("error closing link after accept error") } - return nil, errors.Wrapf(err, "error accepting link [l/%s]", linkId.Token) + return nil, errors.Wrapf(err, "error accepting link [l/%s@%v]", linkId.Token, dial.GetIteration()) } return xli, nil @@ -94,13 +94,16 @@ func (self *dialer) Dial(dial xlink.Dial) (xlink.Xlink, error) { func (self *dialer) dialSplit(linkId *identity.TokenId, address transport.Address, connId string, dial xlink.Dial) (xlink.Xlink, error) { logrus.Debugf("dialing link with split payload/ack channels [l/%s]", linkId.Token) - payloadDialer := channel.NewClassicDialerWithBindAddress(linkId, address, self.config.localBinding, map[int32][]byte{ + headers := channel.Headers{ LinkHeaderRouterId: []byte(self.id.Token), LinkHeaderConnId: []byte(connId), LinkHeaderType: {byte(PayloadChannel)}, LinkHeaderRouterVersion: []byte(dial.GetRouterVersion()), LinkHeaderBinding: []byte(self.GetBinding()), - }) + } + headers.PutUint32Header(LinkHeaderIteration, dial.GetIteration()) + + payloadDialer := channel.NewClassicDialerWithBindAddress(linkId, address, self.config.localBinding, headers) logrus.Debugf("dialing payload channel for [l/%s]", linkId.Token) @@ -113,6 +116,7 @@ func (self *dialer) dialSplit(linkId *identity.TokenId, address transport.Addres routerVersion: dial.GetRouterVersion(), linkProtocol: dial.GetLinkProtocol(), dialAddress: dial.GetAddress(), + iteration: dial.GetIteration(), dialed: true, }, } @@ -124,13 +128,16 @@ func (self *dialer) dialSplit(linkId *identity.TokenId, address transport.Addres logrus.Debugf("dialing ack channel for [l/%s]", linkId.Token) - ackDialer := channel.NewClassicDialerWithBindAddress(linkId, address, self.config.localBinding, map[int32][]byte{ + headers = channel.Headers{ LinkHeaderRouterId: []byte(self.id.Token), LinkHeaderConnId: []byte(connId), LinkHeaderType: {byte(AckChannel)}, LinkHeaderRouterVersion: []byte(dial.GetRouterVersion()), LinkHeaderBinding: []byte(self.GetBinding()), - }) + } + headers.PutUint32Header(LinkHeaderIteration, dial.GetIteration()) + + ackDialer := channel.NewClassicDialerWithBindAddress(linkId, address, self.config.localBinding, headers) _, err = channel.NewChannelWithTransportConfiguration("l/"+linkId.Token, ackDialer, channel.BindHandlerF(bindHandler.bindAckChannel), self.config.options, self.transportConfig) if err != nil { @@ -144,12 +151,15 @@ func (self *dialer) dialSplit(linkId *identity.TokenId, address transport.Addres func (self *dialer) dialSingle(linkId *identity.TokenId, address transport.Address, connId string, dial xlink.Dial) (xlink.Xlink, error) { logrus.Debugf("dialing link with single channel [l/%s]", linkId.Token) - payloadDialer := channel.NewClassicDialerWithBindAddress(linkId, address, self.config.localBinding, map[int32][]byte{ + headers := channel.Headers{ LinkHeaderRouterId: []byte(self.id.Token), LinkHeaderConnId: []byte(connId), LinkHeaderRouterVersion: []byte(dial.GetRouterVersion()), LinkHeaderBinding: []byte(self.GetBinding()), - }) + } + headers.PutUint32Header(LinkHeaderIteration, dial.GetIteration()) + + payloadDialer := channel.NewClassicDialerWithBindAddress(linkId, address, self.config.localBinding, headers) bindHandler := &dialBindHandler{ dialer: self, @@ -160,6 +170,7 @@ func (self *dialer) dialSingle(linkId *identity.TokenId, address transport.Addre linkProtocol: dial.GetLinkProtocol(), routerVersion: dial.GetRouterVersion(), dialAddress: dial.GetAddress(), + iteration: dial.GetIteration(), dialed: true, }, } diff --git a/router/xlink_transport/factory.go b/router/xlink_transport/factory.go index 2aa2bff47..4a8c56618 100644 --- a/router/xlink_transport/factory.go +++ b/router/xlink_transport/factory.go @@ -19,10 +19,10 @@ package xlink_transport import ( "fmt" "github.com/openziti/channel/v2" - "github.com/openziti/ziti/router/xlink" "github.com/openziti/identity" "github.com/openziti/metrics" "github.com/openziti/transport/v2" + "github.com/openziti/ziti/router/xlink" ) type channelType byte @@ -33,6 +33,7 @@ const ( LinkHeaderRouterId = 2 LinkHeaderRouterVersion = 3 LinkHeaderBinding = 4 + LinkHeaderIteration = 5 PayloadChannel channelType = 1 AckChannel channelType = 2 diff --git a/router/xlink_transport/listener.go b/router/xlink_transport/listener.go index 7f2f41970..2815dbf32 100644 --- a/router/xlink_transport/listener.go +++ b/router/xlink_transport/listener.go @@ -20,13 +20,14 @@ import ( "fmt" "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v2" - fabricMetrics "github.com/openziti/ziti/common/metrics" - "github.com/openziti/ziti/router/xlink" "github.com/openziti/identity" "github.com/openziti/metrics" "github.com/openziti/transport/v2" + fabricMetrics "github.com/openziti/ziti/common/metrics" + "github.com/openziti/ziti/router/xlink" "github.com/pkg/errors" "github.com/sirupsen/logrus" + "io" "sync" "time" ) @@ -34,7 +35,7 @@ import ( type listener struct { id *identity.TokenId config *listenerConfig - listener channel.UnderlayListener + listener io.Closer accepter xlink.Acceptor bindHandlerFactory BindHandlerFactory tcfg transport.Configuration @@ -46,18 +47,17 @@ type listener struct { func (self *listener) Listen() error { config := channel.ListenerConfig{ - ConnectOptions: self.config.options.ConnectOptions, - TransportConfig: self.tcfg, - PoolConfigurator: fabricMetrics.GoroutinesPoolMetricsConfigF(self.metricsRegistry, "pool.listener.link"), + ConnectOptions: self.config.options.ConnectOptions, + TransportConfig: self.tcfg, + PoolConfigurator: fabricMetrics.GoroutinesPoolMetricsConfigF(self.metricsRegistry, "pool.listener.link"), + ConnectionHandlers: []channel.ConnectionHandler{&ConnectionHandler{self.id}}, } - listener := channel.NewClassicListener(self.id, self.config.bind, config) - self.listener = listener - connectionHandler := &ConnectionHandler{self.id} - if err := self.listener.Listen(connectionHandler); err != nil { + var err error + if self.listener, err = channel.NewClassicListenerF(self.id, self.config.bind, config, self.acceptNewUnderlay); err != nil { return fmt.Errorf("error listening (%w)", err) } - go self.acceptLoop() + go self.cleanupExpiredPartialLinks() return nil } @@ -86,16 +86,9 @@ func (self *listener) GetLocalBinding() string { return self.config.bindInterface } -func (self *listener) acceptLoop() { - for { - _, err := channel.NewChannelWithTransportConfiguration("link", self.listener, self, self.config.options, self.tcfg) - if err != nil && errors.Is(err, channel.ListenerClosedError) { - logrus.Errorf("link underlay acceptor closed") - return - } else if err != nil { - logrus.Errorf("error creating link underlay (%v)", err) - continue - } +func (self *listener) acceptNewUnderlay(underlay channel.Underlay) { + if _, err := channel.NewChannelWithUnderlay("link", underlay, self, self.config.options); err != nil { + logrus.WithError(err).Error("error creating link channel") } } @@ -104,12 +97,13 @@ func (self *listener) BindChannel(binding channel.Binding) error { WithField("linkProtocol", self.GetLinkProtocol()). WithField("linkId", binding.GetChannel().Id()) - headers := binding.GetChannel().Underlay().Headers() + headers := channel.Headers(binding.GetChannel().Underlay().Headers()) var chanType channelType routerId := "" routerVersion := "" dialerBinding := "" + var iteration uint32 if headers != nil { if v, ok := headers[LinkHeaderRouterId]; ok { @@ -128,12 +122,17 @@ func (self *listener) BindChannel(binding channel.Binding) error { dialerBinding = string(val) log = log.WithField("dialerBinding", dialerBinding) } + if val, ok := headers.GetUint32Header(LinkHeaderIteration); ok { + iteration = val + log = log.WithField("iteration", iteration) + } } linkMeta := &linkMetadata{ routerId: routerId, routerVersion: routerVersion, dialerBinding: dialerBinding, + iteration: iteration, } if chanType != 0 { @@ -203,6 +202,7 @@ func (self *listener) getOrCreateSplitLink(id string, linkMeta *linkMetadata, bi routerVersion: linkMeta.routerVersion, linkProtocol: self.GetLinkProtocol(), dialAddress: self.GetAdvertisement(), + iteration: linkMeta.iteration, dialed: false, }, eventTime: time.Now(), @@ -239,6 +239,7 @@ func (self *listener) bindNonSplitChannel(binding channel.Binding, linkMeta *lin routerVersion: linkMeta.routerVersion, linkProtocol: self.GetLinkProtocol(), dialAddress: self.GetAdvertisement(), + iteration: linkMeta.iteration, dialed: false, } @@ -295,4 +296,5 @@ type linkMetadata struct { routerId string routerVersion string dialerBinding string + iteration uint32 } diff --git a/router/xlink_transport/xlink.go b/router/xlink_transport/xlink.go index 2737cc56c..928c02782 100644 --- a/router/xlink_transport/xlink.go +++ b/router/xlink_transport/xlink.go @@ -18,10 +18,10 @@ package xlink_transport import ( "github.com/openziti/channel/v2" + "github.com/openziti/metrics" "github.com/openziti/ziti/common/inspect" "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/router/xgress" - "github.com/openziti/metrics" "sync/atomic" ) @@ -33,9 +33,11 @@ type impl struct { routerVersion string linkProtocol string dialAddress string - closeNotified atomic.Bool + closed atomic.Bool + faultsSent atomic.Bool droppedMsgMeter metrics.Meter dialed bool + iteration uint32 } func (self *impl) Id() string { @@ -46,6 +48,10 @@ func (self *impl) Key() string { return self.key } +func (self *impl) Iteration() uint32 { + return self.iteration +} + func (self *impl) Init(metricsRegistry metrics.Registry) error { if self.droppedMsgMeter == nil { self.droppedMsgMeter = metricsRegistry.Meter("link.dropped_msgs:" + self.id) @@ -83,10 +89,14 @@ func (self *impl) Close() error { } func (self *impl) CloseNotified() error { - self.closeNotified.Store(true) + self.faultsSent.Store(true) return self.Close() } +func (self *impl) AreFaultsSent() bool { + return self.faultsSent.Load() +} + func (self *impl) DestinationId() string { return self.routerId } @@ -107,8 +117,8 @@ func (self *impl) IsDialed() bool { return self.dialed } -func (self *impl) HandleCloseNotification(f func()) { - if self.closeNotified.CompareAndSwap(false, true) { +func (self *impl) CloseOnce(f func()) { + if self.closed.CompareAndSwap(false, true) { f() } } @@ -124,6 +134,7 @@ func (self *impl) InspectCircuit(detail *inspect.CircuitInspectDetail) { func (self *impl) InspectLink() *inspect.LinkInspectDetail { return &inspect.LinkInspectDetail{ Id: self.Id(), + Iteration: self.Iteration(), Key: self.key, Split: false, Protocol: self.LinkProtocol(), diff --git a/router/xlink_transport/xlink_split.go b/router/xlink_transport/xlink_split.go index bb7bed055..ca118d156 100644 --- a/router/xlink_transport/xlink_split.go +++ b/router/xlink_transport/xlink_split.go @@ -18,10 +18,10 @@ package xlink_transport import ( "github.com/openziti/channel/v2" + "github.com/openziti/metrics" "github.com/openziti/ziti/common/inspect" "github.com/openziti/ziti/common/pb/ctrl_pb" "github.com/openziti/ziti/router/xgress" - "github.com/openziti/metrics" "github.com/pkg/errors" "sync/atomic" ) @@ -35,9 +35,11 @@ type splitImpl struct { routerVersion string linkProtocol string dialAddress string - closeNotified atomic.Bool + closed atomic.Bool + faultsSent atomic.Bool droppedMsgMeter metrics.Meter dialed bool + iteration uint32 } func (self *splitImpl) Id() string { @@ -48,6 +50,10 @@ func (self *splitImpl) Key() string { return self.key } +func (self *splitImpl) Iteration() uint32 { + return self.iteration +} + func (self *splitImpl) Init(metricsRegistry metrics.Registry) error { if self.droppedMsgMeter == nil { self.droppedMsgMeter = metricsRegistry.Meter("link.dropped_msgs:" + self.id) @@ -80,10 +86,14 @@ func (self *splitImpl) SendControl(msg *xgress.Control) error { } func (self *splitImpl) CloseNotified() error { - self.closeNotified.Store(true) + self.faultsSent.Store(true) return self.Close() } +func (self *splitImpl) AreFaultsSent() bool { + return self.faultsSent.Load() +} + func (self *splitImpl) Close() error { if self.droppedMsgMeter != nil { self.droppedMsgMeter.Dispose() @@ -121,8 +131,8 @@ func (self *splitImpl) DialAddress() string { return self.dialAddress } -func (self *splitImpl) HandleCloseNotification(f func()) { - if self.closeNotified.CompareAndSwap(false, true) { +func (self *splitImpl) CloseOnce(f func()) { + if self.closed.CompareAndSwap(false, true) { f() } } @@ -142,6 +152,7 @@ func (self *splitImpl) InspectCircuit(detail *inspect.CircuitInspectDetail) { func (self *splitImpl) InspectLink() *inspect.LinkInspectDetail { return &inspect.LinkInspectDetail{ Id: self.Id(), + Iteration: self.Iteration(), Key: self.key, Split: true, Protocol: self.LinkProtocol(), diff --git a/tests/api_error_test.go b/tests/api_error_test.go index 500602fb2..b274d02fc 100644 --- a/tests/api_error_test.go +++ b/tests/api_error_test.go @@ -20,9 +20,10 @@ package tests import ( - "github.com/google/uuid" "net/http" "testing" + + "github.com/google/uuid" ) func Test_Api_Errors(t *testing.T) { @@ -89,7 +90,7 @@ func Test_Api_Errors(t *testing.T) { madeUpToken := uuid.New().String() resp, err := ctx.newAnonymousClientApiRequest(). - SetHeader("accept", "appliaction/x-pem-file, application/json"). + SetHeader("accept", "application/x-pem-file, application/json"). Post("enroll?token=" + madeUpToken) ctx.Req.NoError(err) diff --git a/tests/auth_oidc_refresh_test.go b/tests/auth_oidc_refresh_test.go new file mode 100644 index 000000000..0e42e3718 --- /dev/null +++ b/tests/auth_oidc_refresh_test.go @@ -0,0 +1,116 @@ +package tests + +// +//import ( +// "bytes" +// "encoding/json" +// "github.com/go-resty/resty/v2" +// "github.com/openziti/ziti/common" +// "github.com/openziti/ziti/controller/oidc_auth" +// "github.com/zitadel/oidc/v2/pkg/oidc" +// "io" +// "net/http" +// "testing" +// "time" +//) +// +//func Test_Authenticate_OIDC_Refresh(t *testing.T) { +// ctx := NewTestContext(t) +// defer ctx.Teardown() +// ctx.StartServer() +// +// rpServer, err := newOidcTestRp(ctx.ApiHost) +// ctx.Req.NoError(err) +// +// rpServer.Start() +// defer rpServer.Stop() +// +// //clientApiUrl, err := url.Parse("https://" + ctx.ApiHost + EdgeClientApiPath) +// //ctx.Req.NoError(err) +// // +// //managementApiUrl, err := url.Parse("https://" + ctx.ApiHost + EdgeManagementApiPath) +// //ctx.Req.NoError(err) +// +// t.Run("authenticate", func(t *testing.T) { +// ctx.testContextChanged(t) +// +// client := resty.NewWithClient(ctx.NewHttpClient(ctx.NewTransport())) +// client.SetRedirectPolicy(resty.DomainCheckRedirectPolicy("127.0.0.1", "localhost")) +// resp, err := client.R().Get(rpServer.LoginUri) +// +// ctx.Req.NoError(err) +// ctx.Req.Equal(http.StatusOK, resp.StatusCode()) +// +// authRequestId := resp.Header().Get(oidc_auth.AuthRequestIdHeader) +// ctx.Req.NotEmpty(authRequestId) +// +// opLoginUri := "https://" + resp.RawResponse.Request.URL.Host + "/oidc/login/username" +// +// resp, err = client.R().SetFormData(map[string]string{"id": authRequestId, "username": ctx.AdminAuthenticator.Username, "password": ctx.AdminAuthenticator.Password}).Post(opLoginUri) +// +// ctx.Req.NoError(err) +// ctx.Req.Equal(http.StatusOK, resp.StatusCode()) +// +// var outTokens *oidc.Tokens[*common.IdTokenClaims] +// +// select { +// case tokens := <-rpServer.TokenChan: +// outTokens = tokens +// case <-time.After(5 * time.Second): +// ctx.Fail("no tokens received, hit timeout") +// } +// +// ctx.Req.NotNil(outTokens) +// ctx.Req.NotEmpty(outTokens.IDToken) +// ctx.Req.NotEmpty(outTokens.IDTokenClaims) +// ctx.Req.NotEmpty(outTokens.AccessToken) +// ctx.Req.NotEmpty(outTokens.RefreshToken) +// +// t.Run("attempt to exchange tokens", func(t *testing.T) { +// refreshToken := outTokens.RefreshToken +// clientID := "native" +// +// // OIDC token endpoint for your provider +// tokenEndpoint := "https://" + resp.RawResponse.Request.URL.Host + "/oidc/token" +// +// // Prepare the request body +// requestBody, _ := json.Marshal(map[string]string{ +// "grant_type": "refresh_token", +// "refresh_token": refreshToken, +// "client_id": clientID, +// }) +// +// // Create a new HTTP request +// req, err := http.NewRequest("POST", tokenEndpoint, bytes.NewBuffer(requestBody)) +// if err != nil { +// panic(err) +// } +// +// // Set appropriate headers +// req.Header.Set("Content-Type", "application/json") +// +// // Make the HTTP request +// client := &http.Client{} +// resp, err := client.Do(req) +// if err != nil { +// panic(err) +// } +// defer resp.Body.Close() +// +// // Read and unmarshal the response body +// body, err := io.ReadAll(resp.Body) +// if err != nil { +// panic(err) +// } +// +// var tokenResponse oidc.TokenExchangeResponse +// err = json.Unmarshal(body, &tokenResponse) +// if err != nil { +// panic(err) +// } +// +// println(tokenResponse) +// +// }) +// }) +//} diff --git a/tests/context.go b/tests/context.go index 11394d7ce..049e4ea4e 100644 --- a/tests/context.go +++ b/tests/context.go @@ -350,7 +350,14 @@ func (ctx *TestContext) StartServerFor(testDb string, clean bool) { if clean { err := os.Remove(testDb) if !os.IsNotExist(err) { - ctx.Req.NoError(err) + + //try again after a small wait + time.Sleep(100 * time.Millisecond) + + err := os.Remove(testDb) + if !os.IsNotExist(err) { + ctx.Req.NoError(err) + } } } diff --git a/tests/control.go b/tests/control.go index 511721889..9ba51b3e4 100644 --- a/tests/control.go +++ b/tests/control.go @@ -2,19 +2,28 @@ package tests import ( "github.com/openziti/channel/v2" - "github.com/openziti/ziti/controller" "github.com/openziti/foundation/v2/versions" "github.com/openziti/transport/v2" + "github.com/openziti/ziti/common/capabilities" + "github.com/openziti/ziti/common/pb/ctrl_pb" + "github.com/openziti/ziti/controller" + "math/big" ) func (ctx *FabricTestContext) NewControlChannelListener() channel.UnderlayListener { config, err := controller.LoadConfig(FabricControllerConfFile) ctx.Req.NoError(err) + ctx.Req.NoError(config.Db.Close()) versionHeader, err := versions.StdVersionEncDec.Encode(versions.NewDefaultVersionProvider().AsVersionInfo()) ctx.Req.NoError(err) + + capabilityMask := &big.Int{} + capabilityMask.SetBit(capabilityMask, capabilities.ControllerCreateTerminatorV2, 1) + capabilityMask.SetBit(capabilityMask, capabilities.ControllerSingleRouterLinkSource, 1) headers := map[int32][]byte{ - channel.HelloVersionHeader: versionHeader, + channel.HelloVersionHeader: versionHeader, + int32(ctrl_pb.ControlHeaders_CapabilitiesHeader): capabilityMask.Bytes(), } ctrlChannelListenerConfig := channel.ListenerConfig{ diff --git a/tests/identity_api_session_activity_test.go b/tests/identity_api_session_activity_test.go index 4119a264f..025d0c93f 100644 --- a/tests/identity_api_session_activity_test.go +++ b/tests/identity_api_session_activity_test.go @@ -3,9 +3,9 @@ package tests import ( rest_identity "github.com/openziti/edge-api/rest_management_api_client/identity" "github.com/openziti/edge-api/rest_model" - "github.com/openziti/ziti/controller" edge_apis "github.com/openziti/sdk-golang/edge-apis" "github.com/openziti/sdk-golang/ziti" + "github.com/openziti/ziti/controller" "net/url" "testing" "time" @@ -42,7 +42,7 @@ func Test_Identity_HasErConnection(t *testing.T) { caPool, err := ziti.GetControllerWellKnownCaPool("https://" + ctx.ApiHost) ctx.Req.NoError(err) - managementClient := edge_apis.NewManagementApiClient(managementUrl, caPool) + managementClient := edge_apis.NewManagementApiClient(managementUrl, caPool, nil) curSession, err := managementClient.Authenticate(creds, nil) ctx.Req.NoError(err) diff --git a/tests/link_test.go b/tests/link_test.go index 7565e76a4..fecbc96a4 100644 --- a/tests/link_test.go +++ b/tests/link_test.go @@ -75,6 +75,10 @@ func (self *testRegistryEnv) GetLinkDialerPool() goroutines.Pool { panic("implement me") } +func (self *testRegistryEnv) GetRateLimiterPool() goroutines.Pool { + panic("implement me") +} + type testDial struct { Key string LinkId string @@ -108,6 +112,10 @@ func (self *testDial) GetRouterVersion() string { return self.RouterVersion } +func (self *testDial) GetIteration() uint32 { + return 1 +} + func setupEnv() link.Env { ctrls := env.NewNetworkControllers(time.Second, nil, env.NewDefaultHeartbeatOptions()) @@ -215,18 +223,19 @@ func Test_DuplicateLinkWithLinkCloseDialer(t *testing.T) { ctrlListener := ctx.NewControlChannelListener() router1 := ctx.startRouter(1) - router1cc, linkCheck1 := testutil.StartLinkTest("router-1", ctrlListener, ctx.Req) + linkChecker := testutil.NewLinkChecker(ctx.Req) + router1cc := testutil.StartLinkTest(linkChecker, "router-1", ctrlListener, ctx.Req) router1Listeners := &ctrl_pb.Listeners{} - if val, found := router1cc.Underlay().Headers()[int32(ctrl_pb.ContentType_ListenersHeader)]; found { + if val, found := router1cc.Underlay().Headers()[int32(ctrl_pb.ControlHeaders_ListenersHeader)]; found { ctx.Req.NoError(proto.Unmarshal(val, router1Listeners)) } router2 := ctx.startRouter(2) - router2cc, linkCheck2 := testutil.StartLinkTest("router-2", ctrlListener, ctx.Req) + router2cc := testutil.StartLinkTest(linkChecker, "router-2", ctrlListener, ctx.Req) router2Listeners := &ctrl_pb.Listeners{} - if val, found := router1cc.Underlay().Headers()[int32(ctrl_pb.ContentType_ListenersHeader)]; found { + if val, found := router1cc.Underlay().Headers()[int32(ctrl_pb.ControlHeaders_ListenersHeader)]; found { ctx.Req.NoError(proto.Unmarshal(val, router1Listeners)) } @@ -258,32 +267,31 @@ func Test_DuplicateLinkWithLinkCloseDialer(t *testing.T) { time.Sleep(time.Second) - linkCheck1.RequireNoErrors() - link1 := linkCheck1.RequireOneActiveLink() + linkChecker.RequireNoErrors() + link1 := linkChecker.RequireOneActiveLink() - linkCheck2.RequireNoErrors() - link2 := linkCheck1.RequireOneActiveLink() + linkChecker.RequireNoErrors() + link2 := linkChecker.RequireOneActiveLink() ctx.Req.Equal(link1.Id, link2.Id) // Test closing control ch to router 1. On reconnect the existing link should get reported ctx.Req.NoError(router1cc.Close()) - _, linkCheck1 = testutil.StartLinkTest("router-1", ctrlListener, ctx.Req) + _ = testutil.StartLinkTest(linkChecker, "router-1", ctrlListener, ctx.Req) time.Sleep(time.Second) - - linkCheck1.RequireNoErrors() - link1 = linkCheck1.RequireOneActiveLink() + linkChecker.RequireNoErrors() + link1 = linkChecker.RequireOneActiveLink() ctx.Req.Equal(link1.Id, link2.Id) // Test closing control ch to router 2. On reconnect the existing link should get reported ctx.Req.NoError(router2cc.Close()) - _, linkCheck2 = testutil.StartLinkTest("router-2", ctrlListener, ctx.Req) + _ = testutil.StartLinkTest(linkChecker, "router-2", ctrlListener, ctx.Req) time.Sleep(time.Second) - linkCheck2.RequireNoErrors() - link2 = linkCheck2.RequireOneActiveLink() + linkChecker.RequireNoErrors() + link2 = linkChecker.RequireOneActiveLink() ctx.Req.Equal(link1.Id, link2.Id) // restart router 1 @@ -294,10 +302,10 @@ func Test_DuplicateLinkWithLinkCloseDialer(t *testing.T) { ctx.Req.NoError(router1.Shutdown()) }() - router1cc, linkCheck1 = testutil.StartLinkTest("router-1", ctrlListener, ctx.Req) + router1cc = testutil.StartLinkTest(linkChecker, "router-1", ctrlListener, ctx.Req) ctx.Req.NoError(protobufs.MarshalTyped(peerUpdates2).WithTimeout(time.Second).SendAndWaitForWire(router1cc)) - linkCheck1.RequireNoErrors() + linkChecker.RequireNoErrors() //time.Sleep(time.Minute) // diff --git a/tests/posture_check_process_multi_test.go b/tests/posture_check_process_multi_test.go index 531e56c67..de8d441fd 100644 --- a/tests/posture_check_process_multi_test.go +++ b/tests/posture_check_process_multi_test.go @@ -19,12 +19,13 @@ package tests import ( + "net/http" + "testing" + "github.com/Jeffail/gabs" "github.com/google/uuid" "github.com/openziti/edge-api/rest_model" "github.com/openziti/ziti/common/eid" - "net/http" - "testing" ) func Test_PostureChecks_ProcessMulti(t *testing.T) { @@ -435,7 +436,7 @@ func Test_PostureChecks_ProcessMulti(t *testing.T) { IsRunning: true, Path: process03Path, SignerFingerprints: []string{ - signerFingerprints[3], //no signers on 03's check shoudln't matter + signerFingerprints[3], //no signers on 03's check shouldn't matter }, } @@ -640,7 +641,7 @@ func Test_PostureChecks_ProcessMulti(t *testing.T) { IsRunning: true, Path: process03Path, SignerFingerprints: []string{ - signerFingerprints[3], //no signers on 03's check shoudln't matter + signerFingerprints[3], //no signers on 03's check shouldn't matter }, } diff --git a/tests/sdk_auth_test.go b/tests/sdk_auth_test.go index 43c3cef7e..fddb62a85 100644 --- a/tests/sdk_auth_test.go +++ b/tests/sdk_auth_test.go @@ -8,6 +8,7 @@ import ( "github.com/openziti/edge-api/rest_management_api_client/external_jwt_signer" identity2 "github.com/openziti/edge-api/rest_management_api_client/identity" "github.com/openziti/edge-api/rest_model" + "github.com/openziti/edge-api/rest_util" nfpem "github.com/openziti/foundation/v2/pem" edge_apis "github.com/openziti/sdk-golang/edge-apis" "net/url" @@ -31,7 +32,7 @@ func TestSdkAuth(t *testing.T) { ctx.Req.NoError(err) adminCreds := edge_apis.NewUpdbCredentials(ctx.AdminAuthenticator.Username, ctx.AdminAuthenticator.Password) - adminClient := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA()) + adminClient := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA(), nil) apiSession, err := adminClient.Authenticate(adminCreds, nil) t.Run("management updb", func(t *testing.T) { @@ -40,20 +41,20 @@ func TestSdkAuth(t *testing.T) { ctx.Req.NoError(err) ctx.Req.NotNil(adminClient) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("client updb, ca pool on client", func(t *testing.T) { ctx.testContextChanged(t) creds := edge_apis.NewUpdbCredentials(ctx.AdminAuthenticator.Username, ctx.AdminAuthenticator.Password) - client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA()) + client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA(), nil) apiSession, err := client.Authenticate(creds, nil) ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("client updb, ca pool on cert", func(t *testing.T) { @@ -62,26 +63,26 @@ func TestSdkAuth(t *testing.T) { creds := edge_apis.NewUpdbCredentials(ctx.AdminAuthenticator.Username, ctx.AdminAuthenticator.Password) creds.CaPool = ctx.ControllerConfig.Id.CA() - client := edge_apis.NewClientApiClient(clientApiUrl, nil) + client := edge_apis.NewClientApiClient(clientApiUrl, nil, nil) apiSession, err := client.Authenticate(creds, nil) ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("management cert, ca pool on client", func(t *testing.T) { ctx.testContextChanged(t) creds := edge_apis.NewCertCredentials([]*x509.Certificate{testIdCerts.cert}, testIdCerts.key) - client := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA()) + client := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA(), nil) apiSession, err := client.Authenticate(creds, nil) - ctx.Req.NoError(err) + ctx.Req.NoError(rest_util.WrapErr(err)) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("management cert, ca pool on cert", func(t *testing.T) { @@ -90,13 +91,15 @@ func TestSdkAuth(t *testing.T) { creds := edge_apis.NewCertCredentials([]*x509.Certificate{testIdCerts.cert}, testIdCerts.key) creds.CaPool = ctx.ControllerConfig.Id.CA() - client := edge_apis.NewManagementApiClient(managementApiUrl, nil) + client := edge_apis.NewManagementApiClient(managementApiUrl, nil, nil) apiSession, err := client.Authenticate(creds, nil) + err = rest_util.WrapErr(err) + ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("client cert, ca pool on client", func(t *testing.T) { @@ -104,13 +107,15 @@ func TestSdkAuth(t *testing.T) { creds := edge_apis.NewCertCredentials([]*x509.Certificate{testIdCerts.cert}, testIdCerts.key) - client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA()) + client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA(), nil) apiSession, err := client.Authenticate(creds, nil) + err = rest_util.WrapErr(err) + ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("client cert, ca pool on creds", func(t *testing.T) { @@ -119,13 +124,15 @@ func TestSdkAuth(t *testing.T) { creds := edge_apis.NewCertCredentials([]*x509.Certificate{testIdCerts.cert}, testIdCerts.key) creds.CaPool = ctx.ControllerConfig.Id.CA() - client := edge_apis.NewClientApiClient(clientApiUrl, nil) + client := edge_apis.NewClientApiClient(clientApiUrl, nil, nil) apiSession, err := client.Authenticate(creds, nil) + err = rest_util.WrapErr(err) + ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("ext jwt signer", func(t *testing.T) { @@ -225,13 +232,13 @@ func TestSdkAuth(t *testing.T) { t.Run("client jwt, ca pool on client", func(t *testing.T) { ctx.testContextChanged(t) creds := edge_apis.NewJwtCredentials(jwtStrSigned) - client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA()) + client := edge_apis.NewClientApiClient(clientApiUrl, ctx.ControllerConfig.Id.CA(), nil) apiSession, err := client.Authenticate(creds, nil) ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("client jwt, ca pool on creds", func(t *testing.T) { @@ -239,25 +246,25 @@ func TestSdkAuth(t *testing.T) { creds := edge_apis.NewJwtCredentials(jwtStrSigned) creds.CaPool = ctx.ControllerConfig.Id.CA() - client := edge_apis.NewClientApiClient(clientApiUrl, nil) + client := edge_apis.NewClientApiClient(clientApiUrl, nil, nil) apiSession, err := client.Authenticate(creds, nil) ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("management jwt, ca pool on client", func(t *testing.T) { ctx.testContextChanged(t) creds := edge_apis.NewJwtCredentials(jwtStrSigned) - client := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA()) + client := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA(), nil) apiSession, err := client.Authenticate(creds, nil) ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) t.Run("management jwt, ca pool on creds", func(t *testing.T) { @@ -265,13 +272,13 @@ func TestSdkAuth(t *testing.T) { creds := edge_apis.NewJwtCredentials(jwtStrSigned) creds.CaPool = ctx.ControllerConfig.Id.CA() - client := edge_apis.NewManagementApiClient(managementApiUrl, nil) + client := edge_apis.NewManagementApiClient(managementApiUrl, nil, nil) apiSession, err := client.Authenticate(creds, nil) ctx.Req.NoError(err) ctx.Req.NotNil(client) ctx.Req.NotNil(apiSession) - ctx.Req.NotNil(apiSession.Token) + ctx.Req.NotNil(apiSession.GetToken()) }) }) diff --git a/tests/sdk_event_test.go b/tests/sdk_event_test.go index 899cf5f9a..cb9ae69b1 100644 --- a/tests/sdk_event_test.go +++ b/tests/sdk_event_test.go @@ -31,7 +31,7 @@ func Test_SDK_Events(t *testing.T) { ctx.Req.NoError(err) adminCreds := edge_apis.NewUpdbCredentials(ctx.AdminAuthenticator.Username, ctx.AdminAuthenticator.Password) - adminClient := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA()) + adminClient := edge_apis.NewManagementApiClient(managementApiUrl, ctx.ControllerConfig.Id.CA(), nil) apiSession, err := adminClient.Authenticate(adminCreds, nil) ctx.NoError(err) ctx.NotNil(apiSession) @@ -60,9 +60,9 @@ func Test_SDK_Events(t *testing.T) { ctx.Req.NoError(err) ctx.Req.NotNil(ztx) - called := make(chan *rest_model.CurrentAPISessionDetail, 1) + called := make(chan *edge_apis.ApiSession, 1) - removeFullListener := ztx.Events().AddAuthenticationStateFullListener(func(ztx ziti.Context, detail *rest_model.CurrentAPISessionDetail) { + removeFullListener := ztx.Events().AddAuthenticationStateFullListener(func(ztx ziti.Context, detail *edge_apis.ApiSession) { ctx.Req.NotNil(ztx) called <- detail }) @@ -76,7 +76,7 @@ func Test_SDK_Events(t *testing.T) { select { case newApiSession := <-called: ctx.Req.NotNil(newApiSession) - ctx.Req.NotEmpty(newApiSession.Token) + ctx.Req.NotEmpty(newApiSession.GetToken()) ctx.Req.Empty(newApiSession.AuthQueries, "expected 0 auth queries") case <-time.After(time.Second * 5): ctx.Req.Fail("time out, full auth event never encountered") @@ -128,9 +128,9 @@ func Test_SDK_Events(t *testing.T) { ztxPostMfa.Close() }() - partialChan := make(chan *rest_model.CurrentAPISessionDetail, 1) + partialChan := make(chan *edge_apis.ApiSession, 1) - removePartialListener := ztxPostMfa.Events().AddAuthenticationStatePartialListener(func(ztx ziti.Context, detail *rest_model.CurrentAPISessionDetail) { + removePartialListener := ztxPostMfa.Events().AddAuthenticationStatePartialListener(func(ztx ziti.Context, detail *edge_apis.ApiSession) { ctx.Req.NotNil(ztx) partialChan <- detail }) @@ -159,9 +159,9 @@ func Test_SDK_Events(t *testing.T) { t.Run("EventAuthenticationStateFull emitted after providing MFA TOTP Code", func(t *testing.T) { ctx.testContextChanged(t) - fullChan := make(chan *rest_model.CurrentAPISessionDetail, 1) + fullChan := make(chan *edge_apis.ApiSession, 1) - fullListenerRemover := ztxPostMfa.Events().AddAuthenticationStateFullListener(func(ztx ziti.Context, detail *rest_model.CurrentAPISessionDetail) { + fullListenerRemover := ztxPostMfa.Events().AddAuthenticationStateFullListener(func(ztx ziti.Context, detail *edge_apis.ApiSession) { ctx.Req.NotNil(ztx) fullChan <- detail }) @@ -184,7 +184,7 @@ func Test_SDK_Events(t *testing.T) { select { case newApiSession := <-fullChan: ctx.Req.NotNil(newApiSession) - ctx.Req.NotEmpty(newApiSession.Token) + ctx.Req.NotEmpty(newApiSession.GetToken()) ctx.Req.Empty(newApiSession.AuthQueries, "expected 0 auth queries") case <-time.After(time.Second * 5): ctx.Req.Fail("time out") @@ -193,9 +193,9 @@ func Test_SDK_Events(t *testing.T) { t.Run("EventAuthenticationStateUnauthenticated emitted if the current API Session is deleted", func(t *testing.T) { ctx.testContextChanged(t) - unauthCalled := make(chan *rest_model.CurrentAPISessionDetail, 1) + unauthCalled := make(chan *edge_apis.ApiSession, 1) - removeUnauthedListener := ztxPostMfa.Events().AddAuthenticationStateUnauthenticatedListener(func(ztx ziti.Context, detail *rest_model.CurrentAPISessionDetail) { + removeUnauthedListener := ztxPostMfa.Events().AddAuthenticationStateUnauthenticatedListener(func(ztx ziti.Context, detail *edge_apis.ApiSession) { ctx.Req.NotNil(ztx) ctx.Req.NotNil(detail) @@ -205,7 +205,7 @@ func Test_SDK_Events(t *testing.T) { defer removeUnauthedListener() implZtx := ztxPostMfa.(*ziti.ContextImpl) - apiSessionId := *implZtx.CtrlClt.CurrentAPISessionDetail.Load().ID + apiSessionId := *implZtx.CtrlClt.ApiSession.Load().ID deleteParams := api_session.NewDeleteAPISessionsParams() deleteParams.ID = apiSessionId @@ -220,7 +220,7 @@ func Test_SDK_Events(t *testing.T) { select { case apiSession := <-unauthCalled: ctx.Req.NotNil(apiSession) - ctx.Req.NotEmpty(apiSession.Token) + ctx.Req.NotEmpty(apiSession.GetToken()) case <-time.After(time.Second * 5): ctx.Req.Fail("time out") } diff --git a/tests/testutil/linkschecker.go b/tests/testutil/linkschecker.go index 2616a24a8..574fed6ad 100644 --- a/tests/testutil/linkschecker.go +++ b/tests/testutil/linkschecker.go @@ -1,22 +1,26 @@ package testutil import ( + "fmt" + "sync" + "time" + "github.com/openziti/channel/v2" + "github.com/openziti/foundation/v2/errorz" "github.com/openziti/ziti/common/handler_common" "github.com/openziti/ziti/common/pb/ctrl_pb" - "github.com/openziti/foundation/v2/errorz" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" - "sync" - "time" ) type TestLink struct { - Id string - Dest string - Failed bool + Id string + Src string + Dest string + FaultCount int + Valid bool } type LinkStateChecker struct { @@ -33,7 +37,7 @@ func (self *LinkStateChecker) reportError(err error) { } } -func (self *LinkStateChecker) HandleLink(msg *channel.Message, _ channel.Channel) { +func (self *LinkStateChecker) HandleLink(msg *channel.Message, ch channel.Channel) { self.Lock() defer self.Unlock() @@ -43,8 +47,22 @@ func (self *LinkStateChecker) HandleLink(msg *channel.Message, _ channel.Channel } for _, link := range routerLinks.Links { - self.links[link.Id] = &TestLink{ - Id: link.Id, + testLink, ok := self.links[link.Id] + if !ok { + self.links[link.Id] = &TestLink{ + Id: link.Id, + Src: ch.Id(), + Dest: link.DestRouterId, + Valid: true, + } + } else { + if testLink.Src != ch.Id() { + self.reportError(fmt.Errorf("source router change for link %v => %v", testLink.Src, ch.Id())) + } + if testLink.Dest != link.DestRouterId { + self.reportError(fmt.Errorf("dest router change for link %v => %v", testLink.Dest, link.DestRouterId)) + } + testLink.Valid = true } } } @@ -63,7 +81,8 @@ func (self *LinkStateChecker) HandleFault(msg *channel.Message, _ channel.Channe if fault.Subject == ctrl_pb.FaultSubject_LinkFault || fault.Subject == ctrl_pb.FaultSubject_LinkDuplicate { if link, found := self.links[fault.Id]; found { - link.Failed = true + link.FaultCount++ + link.Valid = false } else { self.reportError(errors.Errorf("no link with Id %s found", fault.Id)) } @@ -71,7 +90,7 @@ func (self *LinkStateChecker) HandleFault(msg *channel.Message, _ channel.Channe } func (self *LinkStateChecker) HandleOther(msg *channel.Message, _ channel.Channel) { - // -33 = reconenct ping + // -33 = reconnect ping // 5 = heartbeat // 1007 = metrics message if msg.ContentType == -33 || msg.ContentType == 5 || msg.ContentType == 1007 { @@ -107,7 +126,7 @@ func (self *LinkStateChecker) RequireOneActiveLink() *TestLink { var activeLink *TestLink for _, link := range self.links { - if !link.Failed { + if link.Valid { self.req.Nil(activeLink, "more than one active link found") activeLink = link } @@ -116,13 +135,16 @@ func (self *LinkStateChecker) RequireOneActiveLink() *TestLink { return activeLink } -func StartLinkTest(id string, uf channel.UnderlayFactory, assertions *require.Assertions) (channel.Channel, *LinkStateChecker) { +func NewLinkChecker(assertions *require.Assertions) *LinkStateChecker { checker := &LinkStateChecker{ errorC: make(chan error, 4), links: map[string]*TestLink{}, req: assertions, } + return checker +} +func StartLinkTest(checker *LinkStateChecker, id string, uf channel.UnderlayFactory, assertions *require.Assertions) channel.Channel { bindHandler := func(binding channel.Binding) error { binding.AddReceiveHandlerF(channel.AnyContentType, checker.HandleOther) binding.AddReceiveHandlerF(int32(ctrl_pb.ContentType_VerifyRouterType), func(msg *channel.Message, ch channel.Channel) { @@ -136,5 +158,5 @@ func StartLinkTest(id string, uf channel.UnderlayFactory, assertions *require.As timeoutUF := NewTimeoutUnderlayFactory(uf, 2*time.Second) ch, err := channel.NewChannel(id, timeoutUF, channel.BindHandlerF(bindHandler), channel.DefaultOptions()) assertions.NoError(err) - return ch, checker + return ch } diff --git a/tunnel/health/health.go b/tunnel/health/health.go index e542fbf7c..bb35c111b 100644 --- a/tunnel/health/health.go +++ b/tunnel/health/health.go @@ -3,15 +3,16 @@ package health import ( "context" "fmt" + "reflect" + "sync" + "sync/atomic" + "time" + health "github.com/AppsFlyer/go-sundheit" "github.com/michaelquigley/pfxlog" "github.com/openziti/sdk-golang/ziti" "github.com/openziti/sdk-golang/ziti/edge" "github.com/sirupsen/logrus" - "reflect" - "sync" - "sync/atomic" - "time" ) const ( @@ -268,7 +269,7 @@ func (self *manager) OnCheckCompleted(name string, r health.Result) { } // If result processing is slow, let it drop on the floor. In general results should be coming in - // slowly enough that we shouln't have any trouble keeping up + // slowly enough that we shouldn't have any trouble keeping up select { case self.results <- wrapped: default: diff --git a/tunnel/intercept/tproxy/tproxy_linux.go b/tunnel/intercept/tproxy/tproxy_linux.go index 7d6654b7a..61c3f5540 100644 --- a/tunnel/intercept/tproxy/tproxy_linux.go +++ b/tunnel/intercept/tproxy/tproxy_linux.go @@ -19,27 +19,28 @@ package tproxy import ( "context" "fmt" + "net" + "os/exec" + "strings" + "syscall" + "time" + "github.com/coreos/go-iptables/iptables" "github.com/michaelquigley/pfxlog" + "github.com/openziti/foundation/v2/info" + "github.com/openziti/foundation/v2/mempool" + "github.com/openziti/foundation/v2/stringz" + "github.com/openziti/sdk-golang/ziti/edge/network" "github.com/openziti/ziti/tunnel" "github.com/openziti/ziti/tunnel/dns" "github.com/openziti/ziti/tunnel/entities" "github.com/openziti/ziti/tunnel/intercept" "github.com/openziti/ziti/tunnel/router" "github.com/openziti/ziti/tunnel/udp_vconn" - "github.com/openziti/foundation/v2/info" - "github.com/openziti/foundation/v2/mempool" - "github.com/openziti/foundation/v2/stringz" - "github.com/openziti/sdk-golang/ziti/edge/network" cmap "github.com/orcaman/concurrent-map/v2" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" - "net" - "os/exec" - "strings" - "syscall" - "time" ) const ( @@ -231,7 +232,7 @@ func (self *interceptor) newTproxy(service *entities.Service, resolver dns.Resol } if t.tcpLn == nil && t.udpLn == nil { - return nil, errors.Errorf("service %v has no supported protocols (tcp, udp). Serivce protocols: %+v", *service.Name, config.Protocols) + return nil, errors.Errorf("service %v has no supported protocols (tcp, udp). Service protocols: %+v", *service.Name, config.Protocols) } if t.tcpLn != nil { @@ -483,7 +484,7 @@ func (self *tProxy) Apply(addr *intercept.InterceptAddress) { if err := self.addInterceptAddr(addr, self.service, port, self.tracker); err != nil { logrus.Debugf("failed for service %v, intercepting proto: %v, cidr: %v, ports: %v:%v", *self.service.Name, addr.Proto(), addr.IpNet(), addr.LowPort(), addr.HighPort()) - // do we undo the previous succesful ones? + // do we undo the previous successful ones? // only fail at end and return all that failed? } } diff --git a/version b/version index 48b9990e0..00d0c14da 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.31 +0.32 diff --git a/ziti-tunnel/README.md b/ziti-tunnel/README.md index c77402913..277ca555d 100644 --- a/ziti-tunnel/README.md +++ b/ziti-tunnel/README.md @@ -239,8 +239,8 @@ Linux distributions typically manage the contents of /etc/resolv.conf, so simply will only work for a short time until /etc/resolv.conf is overwritten by the managing process. Resolver configuration changes must survive restarts of the Linux name resolution manager. Linux -distrubutions use one of several name resolution managers. The simplest way to determine which name -resolution manager is being used by your Linux distrubtion is to look at /etc/resolv.conf: +distributions use one of several name resolution managers. The simplest way to determine which name +resolution manager is being used by your Linux distribution is to look at /etc/resolv.conf: $ ls -l /etc/resolv.conf @@ -256,7 +256,7 @@ ziti-tunnel's internal DNS server first by adding the following to /etc/dhcp/dhc prepend domain-name-servers 127.0.0.1; Then restart network manager. Unless you know the name of the NetworkManager systemd -service on your Linux distrubtion, it's probably easiest to reboot the host. +service on your Linux distribution, it's probably easiest to reboot the host. #### systemd-resolved @@ -280,4 +280,4 @@ If the service hostname does not resolve, ziti-tunnel will find an unused link-l the route for the service: [0012] INFO adding bogushost.net -> 169.254.1.4 to resolver - [0012] INFO ziti/tunnel/protocols/tcp.Listen: Accepting on 169.254.1.4:25 service=telnet \ No newline at end of file + [0012] INFO ziti/tunnel/protocols/tcp.Listen: Accepting on 169.254.1.4:25 service=telnet diff --git a/ziti/cmd/api/list.go b/ziti/cmd/api/list.go index 2eef77647..071c80b21 100644 --- a/ziti/cmd/api/list.go +++ b/ziti/cmd/api/list.go @@ -18,16 +18,17 @@ package api import ( "fmt" - "github.com/Jeffail/gabs" - "github.com/jedib0t/go-pretty/v6/table" - "github.com/openziti/foundation/v2/errorz" - "github.com/openziti/ziti/ziti/util" - "github.com/pkg/errors" "io" "net/url" "os" "reflect" "strings" + + "github.com/Jeffail/gabs" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/openziti/foundation/v2/errorz" + "github.com/openziti/ziti/ziti/util" + "github.com/pkg/errors" ) // ListEntitiesOfType queries the Ziti Controller for entities of the given type @@ -137,7 +138,7 @@ func MapNamesToIDs(api util.API, entityType string, o *Options, list ...string) if len(list) > 1 { fmt.Printf("Found multiple %v matching %v. Please specify which you want by prefixing with id: or name:\n", entityType, val) - return nil, errors.Errorf("ambigous if %v is id or name", val) + return nil, errors.Errorf("ambiguous if %v is id or name", val) } for _, entity := range list { diff --git a/ziti/cmd/cmd.go b/ziti/cmd/cmd.go index 996f56ff7..733d373c7 100644 --- a/ziti/cmd/cmd.go +++ b/ziti/cmd/cmd.go @@ -19,6 +19,11 @@ package cmd import ( goflag "flag" "fmt" + "io" + "os" + "path/filepath" + "strings" + "github.com/openziti/ziti/ziti/cmd/agentcli" "github.com/openziti/ziti/ziti/cmd/common" "github.com/openziti/ziti/ziti/cmd/create" @@ -35,10 +40,6 @@ import ( "github.com/openziti/ziti/ziti/router" "github.com/openziti/ziti/ziti/tunnel" "github.com/openziti/ziti/ziti/util" - "io" - "os" - "path/filepath" - "strings" "github.com/openziti/ziti/common/version" "github.com/spf13/cobra" @@ -232,7 +233,7 @@ func initConfig() { } func NewRootCommand(in io.Reader, out, err io.Writer) *cobra.Command { - //need to make new CMD everytime because the flags are not thread safe... + //need to make new CMD every time because the flags are not thread safe... ret := &cobra.Command{ Use: "ziti", Short: "ziti is a CLI for working with Ziti", diff --git a/ziti/cmd/demo/echo_server_update_terminator.go b/ziti/cmd/demo/echo_server_update_terminator.go index 202b9a5ee..514bfd538 100644 --- a/ziti/cmd/demo/echo_server_update_terminator.go +++ b/ziti/cmd/demo/echo_server_update_terminator.go @@ -18,6 +18,8 @@ package demo import ( "fmt" + "time" + "github.com/openziti/agent" "github.com/openziti/channel/v2" "github.com/openziti/ziti/ziti/cmd/agentcli" @@ -25,7 +27,6 @@ import ( cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers" "github.com/pkg/errors" "github.com/spf13/cobra" - "time" ) type AgentEchoServerUpdateTerminatorAction struct { @@ -95,7 +96,7 @@ func (self *AgentEchoServerUpdateTerminatorAction) makeRequest(ch channel.Channe fmt.Printf("error: %v\n", result.Message) } } else { - return errors.Errorf("unexpected reponse type: %v", reply.ContentType) + return errors.Errorf("unexpected response type: %v", reply.ContentType) } return nil } diff --git a/ziti/cmd/demo/root.go b/ziti/cmd/demo/root.go index a0868d05c..f53bcc38f 100644 --- a/ziti/cmd/demo/root.go +++ b/ziti/cmd/demo/root.go @@ -72,6 +72,10 @@ func NewDemoCmd(p common.OptionsProvider) *cobra.Command { demoCmd.AddCommand(newEchoServerCmd()) demoCmd.AddCommand(newZcatCmd()) + + zcatCloseTestCmd := newZcatCloseTestCmd() + zcatCloseTestCmd.Hidden = true + demoCmd.AddCommand(zcatCloseTestCmd) demoCmd.AddCommand(agentCmd) demoCmd.AddCommand(setupCmd) diff --git a/ziti/cmd/demo/zcat_closetest.go b/ziti/cmd/demo/zcat_closetest.go new file mode 100644 index 000000000..e8e650969 --- /dev/null +++ b/ziti/cmd/demo/zcat_closetest.go @@ -0,0 +1,163 @@ +/* + 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 demo + +import ( + "bufio" + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/foundation/v2/debugz" + "github.com/openziti/sdk-golang/ziti" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "net" + "os" + "strings" + "time" +) + +type zcatCloseTestAction struct { + verbose bool + logFormatter string + configFile string +} + +func newZcatCloseTestCmd() *cobra.Command { + action := &zcatCloseTestAction{} + + cmd := &cobra.Command{ + Use: "zcatCloseTest ", + Example: "ziti demo zcatCloseTest tcp:localhost:1234 or ziti demo zcatCloseTest -i zcatCloseTest.json ziti:echo", + Short: "A simple network cat facility which can run over tcp or ziti", + Args: cobra.ExactArgs(1), + Run: action.run, + } + + // allow interspersing positional args and flags + cmd.Flags().SetInterspersed(true) + 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 *zcatCloseTestAction) initLogging() { + logLevel := logrus.InfoLevel + if self.verbose { + logLevel = logrus.DebugLevel + } + + options := pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").NoColor() + pfxlog.GlobalInit(logLevel, options) + + switch self.logFormatter { + case "pfxlog": + pfxlog.SetFormatter(pfxlog.NewFormatter(pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").StartingToday())) + case "json": + pfxlog.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02T15:04:05.000Z"}) + case "text": + pfxlog.SetFormatter(&logrus.TextFormatter{}) + default: + // let logrus do its own thing + } +} + +func (self *zcatCloseTestAction) run(_ *cobra.Command, args []string) { + self.initLogging() + + log := pfxlog.Logger() + + parts := strings.Split(args[0], ":") + if len(parts) < 2 { + log.Fatalf("destination %v is invalid. destination must be of the form network:address", args[0]) + } + network := parts[0] + addr := strings.Join(parts[1:], ":") + + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "stack") { + debugz.DumpStack() + fmt.Println("===============================================================") + } else { + if err := self.sendRecv(network, addr, scanner.Text()); err != nil { + panic(err) + } + } + } +} + +func (self *zcatCloseTestAction) sendRecv(network, addr, line string) error { + log := pfxlog.Logger() + + var conn net.Conn + var err error + + log.Debugf("dialing %v:%v", network, addr) + if network == "tcp" || network == "udp" { + conn, err = net.Dial(network, addr) + } else if network == "ziti" { + zitiConfig, cfgErr := ziti.NewConfigFromFile(self.configFile) + if cfgErr != nil { + log.WithError(cfgErr).Fatalf("unable to load ziti identity from [%v]", self.configFile) + } + + dialIdentifier := "" + if atIdx := strings.IndexByte(addr, '@'); atIdx > 0 { + dialIdentifier = addr[:atIdx] + addr = addr[atIdx+1:] + } + + zitiContext, ctxErr := ziti.NewContext(zitiConfig) + if ctxErr != nil { + pfxlog.Logger().WithError(err).Fatal("could not create sdk context from config") + } + + defer func() { + zitiContext.Close() + }() + + dialOptions := &ziti.DialOptions{ + ConnectTimeout: 5 * time.Second, + Identity: dialIdentifier, + } + conn, err = zitiContext.DialWithOptions(addr, dialOptions) + } else { + log.Fatalf("invalid network '%v'. valid values are ['ziti', 'tcp', 'udp']", network) + } + + if err != nil { + log.WithError(err).Fatalf("unable to dial %v:%v", network, addr) + } + + log.Debugf("connected to %v:%v", network, addr) + + n, err := conn.Write([]byte(line)) + if err != nil { + return err + } + + buf := make([]byte, n) + if _, err = conn.Read(buf); err != nil { + return err + } + fmt.Println(string(buf)) + return nil +} diff --git a/ziti/cmd/edge/common.go b/ziti/cmd/edge/common.go index ab6eeef3f..aea864ffb 100644 --- a/ziti/cmd/edge/common.go +++ b/ziti/cmd/edge/common.go @@ -18,10 +18,11 @@ package edge import ( "fmt" - "github.com/openziti/ziti/ziti/cmd/api" - "github.com/pkg/errors" "os" "strings" + + "github.com/openziti/ziti/ziti/cmd/api" + "github.com/pkg/errors" ) func mapNameToID(entityType string, val string, o api.Options) (string, error) { @@ -97,7 +98,7 @@ func mapNamesToIDs(entityType string, o api.Options, skipNotFound bool, list ... if len(list) > 1 { fmt.Printf("Found multiple %v matching %v. Please specify which you want by prefixing with id: or name:\n", entityType, val) - return nil, errors.Errorf("ambigous if %v is id or name", val) + return nil, errors.Errorf("ambiguous if %v is id or name", val) } entityId, _ := list[0].Path("id").Data().(string) diff --git a/ziti/cmd/edge/create_authenticator_updb.go b/ziti/cmd/edge/create_authenticator_updb.go index 223423414..3f760e611 100644 --- a/ziti/cmd/edge/create_authenticator_updb.go +++ b/ziti/cmd/edge/create_authenticator_updb.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "github.com/Jeffail/gabs" "github.com/openziti/edge-api/rest_management_api_client/authenticator" "github.com/openziti/foundation/v2/term" @@ -105,7 +106,7 @@ func runCreateIdentityPassword(idType string, options *createAuthenticatorUpdb) } if len(result.Payload.Data) != 0 { - return fmt.Errorf("updb authentictor already exists, update or remove it instead") + return fmt.Errorf("updb authenticator already exists, update or remove it instead") } if options.password == "" { diff --git a/ziti/cmd/edge/create_edge_router.go b/ziti/cmd/edge/create_edge_router.go index abc7d3779..fd1e33f57 100644 --- a/ziti/cmd/edge/create_edge_router.go +++ b/ziti/cmd/edge/create_edge_router.go @@ -59,7 +59,7 @@ func NewCreateEdgeRouterCmd(out io.Writer, errOut io.Writer) *cobra.Command { // allow interspersing positional args and flags cmd.Flags().SetInterspersed(true) - cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "Role attributes of the new edge router") + cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "comma-separated role attributes for the new router") cmd.Flags().BoolVarP(&options.isTunnelerEnabled, "tunneler-enabled", "t", false, "Can this edge router be used as a tunneler") cmd.Flags().StringVarP(&options.jwtOutputFile, "jwt-output-file", "o", "", "File to which to output the JWT used for enrolling the edge router") cmd.Flags().StringToStringVar(&options.appData, "app-Data", nil, "Custom application data") diff --git a/ziti/cmd/edge/create_identity.go b/ziti/cmd/edge/create_identity.go index fa110f62c..0ef48a5b8 100644 --- a/ziti/cmd/edge/create_identity.go +++ b/ziti/cmd/edge/create_identity.go @@ -89,7 +89,7 @@ func newCreateIdentityOfTypeCmd(name string, options *createIdentityOptions) *co cmd.Flags().BoolVarP(&options.isAdmin, "admin", "A", false, "Give the new identity admin privileges") cmd.Flags().StringVar(&options.username, "updb", "", "username to give the identity, will create a UPDB enrollment") cmd.Flags().StringVar(&options.externalId, "external-id", "", "an external id to give to the identity") - cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "Role attributes of the new identity") + cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "comma-separated role attributes for the new identity") cmd.Flags().StringVarP(&options.jwtOutputFile, "jwt-output-file", "o", "", "File to which to output the JWT used for enrolling the identity") cmd.Flags().StringVarP(&options.defaultHostingPrecedence, "default-hosting-precedence", "p", "", "Default precedence to use when hosting services using this identity [default,required,failed]") cmd.Flags().Uint16VarP(&options.defaultHostingCost, "default-hosting-cost", "c", 0, "Default cost to use when hosting services using this identity") diff --git a/ziti/cmd/edge/create_posture_check.go b/ziti/cmd/edge/create_posture_check.go index c1599f012..85c9b75b1 100644 --- a/ziti/cmd/edge/create_posture_check.go +++ b/ziti/cmd/edge/create_posture_check.go @@ -99,7 +99,7 @@ type createPostureCheckProcessMultiOptions struct { func (options *createPostureCheckOptions) addPostureFlags(cmd *cobra.Command) { // allow interspersing positional args and flags cmd.Flags().SetInterspersed(true) - cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "Role attributes of the new service") + cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "comma-separated role attributes for the new service") } func newCreatePostureCheckMacCmd(out io.Writer, errOut io.Writer) *cobra.Command { @@ -226,7 +226,7 @@ func newCreatePostureCheckProcessMultiCmd(out io.Writer, errOut io.Writer) *cobr cmd := &cobra.Command{ Use: fmt.Sprintf("process-multi ", OsLinux, OsMacOs, OsWindows, OsWindowsServer), - Short: "creates a posture check multi for an OS specific process. Provide os and paths as comma separated values", + Short: "Create a posture check requiring multiple executables and OSs. Provide CSVs of OS names and executable paths.", Args: func(cmd *cobra.Command, args []string) error { if err := cobra.ExactArgs(4)(cmd, args); err != nil { return err diff --git a/ziti/cmd/edge/create_service.go b/ziti/cmd/edge/create_service.go index 533b2b4b8..92c942d61 100644 --- a/ziti/cmd/edge/create_service.go +++ b/ziti/cmd/edge/create_service.go @@ -56,7 +56,7 @@ func newCreateServiceCmd(out io.Writer, errOut io.Writer) *cobra.Command { // allow interspersing positional args and flags cmd.Flags().SetInterspersed(true) - cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "Role attributes of the new service") + cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "comma-separated role attributes for the new service") cmd.Flags().StringSliceVarP(&options.configs, "configs", "c", nil, "Configuration id or names to be associated with the new service") cmd.Flags().StringVar(&options.terminatorStrategy, "terminator-strategy", "", "Specifies the terminator strategy for the service") cmd.Flags().DurationVar(&options.maxIdleTime, "max-idle-time", 0, "Time after which idle circuit will be terminated. Defaults to 0, which indicates no limit on idle circuits") diff --git a/ziti/cmd/edge/policy_advisor.go b/ziti/cmd/edge/policy_advisor.go index 892b4e945..7468c65df 100644 --- a/ziti/cmd/edge/policy_advisor.go +++ b/ziti/cmd/edge/policy_advisor.go @@ -18,13 +18,14 @@ package edge import ( "fmt" + "io" + "github.com/Jeffail/gabs" "github.com/openziti/ziti/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/util" "github.com/spf13/cobra" - "io" ) // newPolicyAdvisor creates a command object for the "controller policy-advisor" command @@ -176,7 +177,7 @@ func outputHeader(o *policyAdvisorOptions) error { "Policy General Guidelines\n"+ " In order for an identity to dial or bind a service, the following must be true:\n"+ " - The identity must have access to the service via a service policy of the correct type (dial or bind)\n"+ - " - The identity must have acces to at least one on-line edge router via an edge router policy\n"+ + " - The identity must have access to at least one on-line edge router via an edge router policy\n"+ " - The service must have access to at least one on-line edge router via a service edge router policy\n"+ " - There must be at least one on-line edge router that both the identity and service have access to.\n"+ "\n"+ diff --git a/ziti/cmd/edge/quickstart.go b/ziti/cmd/edge/quickstart.go index b77b3bb91..d861a4462 100644 --- a/ziti/cmd/edge/quickstart.go +++ b/ziti/cmd/edge/quickstart.go @@ -65,18 +65,17 @@ func NewQuickStartCmd(out io.Writer, errOut io.Writer, context context.Context) cmd := &cobra.Command{ Use: "quickstart", Short: "runs a Controller and Router in quickstart mode", - Long: `runs a Controller and Router in quickstart mode. By default, this will create a totally ephemeral network, only valid while running.`, + Long: "runs a Controller and Router in quickstart mode with a temporary directory; suitable for testing and development", Run: func(cmd *cobra.Command, args []string) { options.out = out options.errOut = errOut options.run(context) }, } - cmd.Flags().StringVarP(&options.Username, "username", "u", "", "Username to use when creating the Ziti Edge Controller. default: admin") - cmd.Flags().StringVarP(&options.Password, "password", "p", "", "Password to use for authenticating to the Ziti Edge Controller. default: admin") + cmd.Flags().StringVarP(&options.Username, "username", "u", "", "Admin username, default: admin") + cmd.Flags().StringVarP(&options.Password, "password", "p", "", "Admin password, default: admin") - cmd.Flags().BoolVar(&options.AlreadyInitialized, "already-initialized", false, "Specifies the PKI does not need to be created and the db does not need to be initialized. Recommended to be combined with --home. If --home is not specified the environment will be destroyed on shutdown! default: false") - cmd.Flags().StringVar(&options.Home, "home", "", "Sets the directory the environment should be installed into. Defaults to a temporary directory. If specified, the environment will not be removed on exit.") + cmd.Flags().StringVar(&options.Home, "home", "", "permanent directory") cmd.Flags().StringVar(&options.ControllerAddress, "ctrl-address", "", "Sets the advertised address for the control plane and API. current: "+currentCtrlAddy) cmd.Flags().Int16Var(&options.ControllerPort, "ctrl-port", int16(defautlCtrlPort), "Sets the port to use for the control plane and API. current: "+currentCtrlPort) @@ -100,6 +99,8 @@ func (o *QuickstartOpts) run(ctx context.Context) { tmpDir, _ := os.MkdirTemp("", "quickstart") o.Home = tmpDir o.cleanOnExit = true + } else { + logrus.Infof("permanent --home '%s' will not be removed on exit", o.Home) } if o.ControllerAddress != "" { _ = os.Setenv(constants.CtrlAdvertisedAddressVarName, o.ControllerAddress) @@ -141,12 +142,14 @@ func (o *QuickstartOpts) run(ctx context.Context) { } dbDir := o.Home + "/db" - _, _ = fmt.Fprintf(os.Stdout, "creating the tmp dir [%v] for the database.\n\n", dbDir) - _ = os.MkdirAll(dbDir, 0o777) + if _, err := os.Stat(dbDir); !os.IsNotExist(err) { + o.AlreadyInitialized = true + } else { + _ = os.MkdirAll(dbDir, 0o777) + logrus.Debugf("made directory '%s'", dbDir) - o.createMinimalPki() + o.createMinimalPki() - if !o.AlreadyInitialized { ctrl := create.NewCmdCreateConfigController() ctrl.SetArgs([]string{ fmt.Sprintf("--output=%s", ctrlYaml), @@ -303,69 +306,67 @@ func (o *QuickstartOpts) run(ctx context.Context) { } func (o *QuickstartOpts) createMinimalPki() { - if !o.AlreadyInitialized { - where := o.Home + "/pki" - fmt.Println("emitting a minimal PKI") - - //ziti pki create ca --pki-root="$pkiDir" --ca-file="root-ca" --ca-name="root-ca" - ca := pki.NewCmdPKICreateCA(o.out, o.errOut) - ca.SetArgs([]string{ - fmt.Sprintf("--pki-root=%s", where), - fmt.Sprintf("--ca-file=%s", "root-ca"), - fmt.Sprintf("--ca-name=%s", "root-ca"), - }) - pkiErr := ca.Execute() - if pkiErr != nil { - logrus.Fatal(pkiErr) - } + where := o.Home + "/pki" + fmt.Println("emitting a minimal PKI") + + //ziti pki create ca --pki-root="$pkiDir" --ca-file="root-ca" --ca-name="root-ca" + ca := pki.NewCmdPKICreateCA(o.out, o.errOut) + ca.SetArgs([]string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", "root-ca"), + fmt.Sprintf("--ca-name=%s", "root-ca"), + }) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Fatal(pkiErr) + } - //ziti pki create intermediate --pki-root "$pkiDir" --ca-name "root-ca" --intermediate-name "intermediate-ca" --intermediate-file "intermediate-ca" --max-path-len "1" - intermediate := pki.NewCmdPKICreateIntermediate(o.out, o.errOut) - intermediate.SetArgs([]string{ - fmt.Sprintf("--pki-root=%s", where), - fmt.Sprintf("--ca-name=%s", "root-ca"), - fmt.Sprintf("--intermediate-name=%s", "intermediate-ca"), - fmt.Sprintf("--intermediate-file=%s", "intermediate-ca"), - "--max-path-len=1", - }) - intErr := intermediate.Execute() - if intErr != nil { - logrus.Fatal(intErr) - } + //ziti pki create intermediate --pki-root "$pkiDir" --ca-name "root-ca" --intermediate-name "intermediate-ca" --intermediate-file "intermediate-ca" --max-path-len "1" + intermediate := pki.NewCmdPKICreateIntermediate(o.out, o.errOut) + intermediate.SetArgs([]string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", "root-ca"), + fmt.Sprintf("--intermediate-name=%s", "intermediate-ca"), + fmt.Sprintf("--intermediate-file=%s", "intermediate-ca"), + "--max-path-len=1", + }) + intErr := intermediate.Execute() + if intErr != nil { + logrus.Fatal(intErr) + } - //ziti pki create server --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --server-name "server" --server-file "server" --dns "localhost,${ZITI_HOSTNAME}" - svr := pki.NewCmdPKICreateServer(o.out, o.errOut) - var ips = "127.0.0.1,::1" - ip_override := os.Getenv("ZITI_CTRL_EDGE_IP_OVERRIDE") - if ip_override != "" { - ips = ips + "," + ip_override - } - svr.SetArgs([]string{ - fmt.Sprintf("--pki-root=%s", where), - fmt.Sprintf("--ca-name=%s", "intermediate-ca"), - fmt.Sprintf("--server-name=%s", "server"), - fmt.Sprintf("--server-file=%s", "server"), - fmt.Sprintf("--dns=%s,%s", "localhost", helpers.GetCtrlAdvertisedAddress()), - fmt.Sprintf("--ip=%s", ips), - }) - svrErr := svr.Execute() - if svrErr != nil { - logrus.Fatal(svrErr) - } + //ziti pki create server --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --server-name "server" --server-file "server" --dns "localhost,${ZITI_HOSTNAME}" + svr := pki.NewCmdPKICreateServer(o.out, o.errOut) + var ips = "127.0.0.1,::1" + ip_override := os.Getenv("ZITI_CTRL_EDGE_IP_OVERRIDE") + if ip_override != "" { + ips = ips + "," + ip_override + } + svr.SetArgs([]string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", "intermediate-ca"), + fmt.Sprintf("--server-name=%s", "server"), + fmt.Sprintf("--server-file=%s", "server"), + fmt.Sprintf("--dns=%s,%s", "localhost", helpers.GetCtrlAdvertisedAddress()), + fmt.Sprintf("--ip=%s", ips), + }) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } - //ziti pki create client --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --client-name "client" --client-file "client" --key-file "server" - client := pki.NewCmdPKICreateClient(o.out, o.errOut) - client.SetArgs([]string{ - fmt.Sprintf("--pki-root=%s", where), - fmt.Sprintf("--ca-name=%s", "intermediate-ca"), - fmt.Sprintf("--client-name=%s", "client"), - fmt.Sprintf("--client-file=%s", "client"), - fmt.Sprintf("--key-file=%s", "server"), - }) - clientErr := client.Execute() - if clientErr != nil { - logrus.Fatal(clientErr) - } + //ziti pki create client --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --client-name "client" --client-file "client" --key-file "server" + client := pki.NewCmdPKICreateClient(o.out, o.errOut) + client.SetArgs([]string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", "intermediate-ca"), + fmt.Sprintf("--client-name=%s", "client"), + fmt.Sprintf("--client-file=%s", "client"), + fmt.Sprintf("--key-file=%s", "server"), + }) + clientErr := client.Execute() + if clientErr != nil { + logrus.Fatal(clientErr) } } diff --git a/ziti/cmd/edge/quickstart_automated_test.go b/ziti/cmd/edge/quickstart_automated_test.go index c3db1559b..f41a770bf 100644 --- a/ziti/cmd/edge/quickstart_automated_test.go +++ b/ziti/cmd/edge/quickstart_automated_test.go @@ -12,7 +12,7 @@ import ( "time" ) -func TestEdgeQuickstart(t *testing.T) { +func TestEdgeQuickstartAutomated(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) _ = os.Setenv("ZITI_CTRL_EDGE_ADVERTISED_ADDRESS", "localhost") //force localhost _ = os.Setenv("ZITI_ROUTER_NAME", "quickstart-router") diff --git a/ziti/cmd/edge/quickstart_manual_test.go b/ziti/cmd/edge/quickstart_manual_test.go index 2435b8123..9a5af88c0 100644 --- a/ziti/cmd/edge/quickstart_manual_test.go +++ b/ziti/cmd/edge/quickstart_manual_test.go @@ -11,6 +11,6 @@ This is a manually run test that will, with the default values except the admin 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) { +func TestEdgeQuickstartManual(t *testing.T) { performQuickstartTest(t) } diff --git a/ziti/cmd/edge/update_edge_router.go b/ziti/cmd/edge/update_edge_router.go index e507921c6..3574882f2 100644 --- a/ziti/cmd/edge/update_edge_router.go +++ b/ziti/cmd/edge/update_edge_router.go @@ -65,7 +65,7 @@ func newUpdateEdgeRouterCmd(out io.Writer, errOut io.Writer) *cobra.Command { cmd.Flags().StringVarP(&options.name, "name", "n", "", "Set the name of the edge router") cmd.Flags().BoolVarP(&options.isTunnelerEnabled, "tunneler-enabled", "t", false, "Can this edge router be used as a tunneler") cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, - "Set role attributes of the edge router. Use --role-attributes '' to set an empty list") + "comma-separated role attributes for the router. Use '' to unset.") cmd.Flags().StringToStringVar(&options.appData, "app-data", nil, "Custom application data") cmd.Flags().BoolVar(&options.usePut, "use-put", false, "Use PUT to when making the request") cmd.Flags().Uint16Var(&options.cost, "cost", 0, "Specifies the router cost. Default 0.") diff --git a/ziti/cmd/edge/update_identity.go b/ziti/cmd/edge/update_identity.go index 8bfd1adaa..484e76d30 100644 --- a/ziti/cmd/edge/update_identity.go +++ b/ziti/cmd/edge/update_identity.go @@ -69,7 +69,7 @@ func newUpdateIdentityCmd(out io.Writer, errOut io.Writer) *cobra.Command { cmd.Flags().StringVarP(&options.name, "name", "n", "", "Set the name of the identity") cmd.Flags().StringVarP(&options.externalId, "external-id", "x", "", "an external id to give to the identity") cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, - "Set role attributes of the identity. Use --role-attributes '' to set an empty list") + "comma-separated role attributes for the identity. Use '' to unset.") cmd.Flags().StringVarP(&options.defaultHostingPrecedence, "default-hosting-precedence", "p", "", "Default precedence to use when hosting services using this identity [default,required,failed]") cmd.Flags().Uint16VarP(&options.defaultHostingCost, "default-hosting-cost", "c", 0, "Default cost to use when hosting services using this identity") cmd.Flags().StringToIntVar(&options.serviceCosts, "service-costs", map[string]int{}, "Per-service hosting costs") diff --git a/ziti/cmd/edge/update_identity_configs.go b/ziti/cmd/edge/update_identity_configs.go index 3007b7492..080c58abc 100644 --- a/ziti/cmd/edge/update_identity_configs.go +++ b/ziti/cmd/edge/update_identity_configs.go @@ -18,10 +18,11 @@ package edge import ( "fmt" + "io" + "github.com/openziti/ziti/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/common" cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers" - "io" "github.com/Jeffail/gabs" "github.com/spf13/cobra" @@ -56,7 +57,7 @@ func newUpdateIdentityConfigsCmd(out io.Writer, errOut io.Writer) *cobra.Command // allow interspersing positional args and flags cmd.Flags().SetInterspersed(true) - cmd.Flags().BoolVarP(&options.remove, "remove", "r", false, "Remove the sevice config override") + cmd.Flags().BoolVarP(&options.remove, "remove", "r", false, "Remove the service config override") return cmd } diff --git a/ziti/cmd/edge/update_posture_check.go b/ziti/cmd/edge/update_posture_check.go index 25f0e1b51..69dd9dc74 100644 --- a/ziti/cmd/edge/update_posture_check.go +++ b/ziti/cmd/edge/update_posture_check.go @@ -106,7 +106,7 @@ func newUpdatePostureCheckMacCmd(out io.Writer, errOut io.Writer) *cobra.Command cmd.Flags().SetInterspersed(true) cmd.Flags().StringVarP(&options.name, "name", "n", "", "Set the name") cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, - "Set role attributes of the posture check. Use --role-attributes '' to set an empty list") + "comma-separated role attributes for the posture check. Use '' to unset.") cmd.Flags().StringSliceVarP(&options.addresses, "mac-addresses", "m", nil, "Set MAC addresses of the posture check") @@ -178,7 +178,7 @@ func newUpdatePostureCheckDomainCmd(out io.Writer, errOut io.Writer) *cobra.Comm cmd.Flags().SetInterspersed(true) cmd.Flags().StringVarP(&options.name, "name", "n", "", "Set the name") cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, - "Set role attributes of the posture check. Use --role-attributes '' to set an empty list") + "comma-separated role attributes for the posture check. Use '' to unset.") cmd.Flags().StringSliceVarP(&options.domains, "domains", "d", nil, "Set the domains of the posture check") return cmd @@ -223,7 +223,7 @@ func newUpdatePostureCheckMfaCmd(out io.Writer, errOut io.Writer) *cobra.Command cmd.Flags().BoolVar(&options.ignoreLegacyEndpoints, "ignore-legacy", false, "Ignore prompts and timeout for endpoints that do not support MFA timeout/prompts") cmd.Flags().BoolVarP(&options.ignoreLegacyEndpoints, "no-ignore-legacy", "l", false, "Do not ignore prompts and timeout for endpoints that do not support MFA timeout/prompts") - cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "Set role attributes of the posture check. Use --role-attributes '' to set an empty list") + cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, "comma-separated role attributes for the posture check. Use '' to unset.") return cmd } @@ -316,7 +316,7 @@ func runUpdatePostureCheckDomain(o *updatePostureCheckDomainOptions) error { if o.Cmd.Flags().Changed("domains") { if len(o.domains) == 0 { - return fmt.Errorf("must specify at least one domain, multiple values may be separated by commas") + return fmt.Errorf("comma-separated domain names") } api.SetJSONValue(entityData, o.domains, "domains") @@ -369,7 +369,7 @@ func newUpdatePostureCheckProcessCmd(out io.Writer, errOut io.Writer) *cobra.Com cmd.Flags().SetInterspersed(true) cmd.Flags().StringVarP(&options.name, "name", "n", "", "Set the name") cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, - "Set role attributes of the posture check. Use --role-attributes '' to set an empty list") + "comma-separated role attributes for the posture check. Use '' to unset.") cmd.Flags().StringVarP(&options.path, "path", "p", "", "set the path of the posture check") cmd.Flags().StringSliceVarP(&options.hashes, "hash-sigs", "s", nil, "set the valid hashes of the posture check") cmd.Flags().StringVarP(&options.signer, "signer-fingerprint", "f", "", "set the signer fingerprint of the posture check") @@ -476,7 +476,7 @@ func newUpdatePostureCheckOsCmd(out io.Writer, errOut io.Writer) *cobra.Command cmd.Flags().SetInterspersed(true) cmd.Flags().StringVarP(&options.name, "name", "n", "", "Set the name") cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, - "Set role attributes of the posture check. Use --role-attributes '' to set an empty list") + "comma-separated role attributes for the posture check. Use '' to unset.") cmd.Flags().StringSliceVarP(&options.os, "os", "o", nil, "Set OS(es) of the posture check, should be in the format of ':::...', multiple may be specified via CSV or multiple flags") return cmd diff --git a/ziti/cmd/edge/update_service.go b/ziti/cmd/edge/update_service.go index aa116da1d..2722fdb75 100644 --- a/ziti/cmd/edge/update_service.go +++ b/ziti/cmd/edge/update_service.go @@ -63,9 +63,8 @@ func newUpdateServiceCmd(out io.Writer, errOut io.Writer) *cobra.Command { cmd.Flags().StringVarP(&options.name, "name", "n", "", "Set the name of the service") cmd.Flags().StringVar(&options.terminatorStrategy, "terminator-strategy", "", "Specifies the terminator strategy for the service") cmd.Flags().StringSliceVarP(&options.roleAttributes, "role-attributes", "a", nil, - "Set role attributes of the service. Use --role-attributes '' to set an empty list") + "comma-separated role attributes for the service. Use '' to unset.") cmd.Flags().DurationVar(&options.maxIdleTime, "max-idle-time", 0, "Time after which idle circuit will be terminated. Defaults to 0, which indicates no limit on idle circuits") - if err := options.encryption.Set("ON"); err != nil { panic(err) } diff --git a/ziti/cmd/fabric/root.go b/ziti/cmd/fabric/root.go index 51da34c6f..d4da670eb 100644 --- a/ziti/cmd/fabric/root.go +++ b/ziti/cmd/fabric/root.go @@ -110,6 +110,7 @@ func newValidateCommand(p common.OptionsProvider) *cobra.Command { } validateCmd.AddCommand(NewValidateTerminatorsCmd(p)) + validateCmd.AddCommand(NewValidateRouterLinksCmd(p)) return validateCmd } diff --git a/ziti/cmd/fabric/stream_toggle_pipe_traces.go b/ziti/cmd/fabric/stream_toggle_pipe_traces.go index c867af37b..d27dc36b6 100644 --- a/ziti/cmd/fabric/stream_toggle_pipe_traces.go +++ b/ziti/cmd/fabric/stream_toggle_pipe_traces.go @@ -18,14 +18,15 @@ package fabric import ( "fmt" + "time" + "github.com/openziti/channel/v2" - "github.com/openziti/channel/v2/trace/pb" + trace_pb "github.com/openziti/channel/v2/trace/pb" "github.com/openziti/ziti/common/pb/mgmt_pb" "github.com/openziti/ziti/ziti/cmd/api" "github.com/openziti/ziti/ziti/cmd/common" "github.com/spf13/cobra" "google.golang.org/protobuf/proto" - "time" ) type streamTogglePipeTracesAction struct { @@ -87,7 +88,7 @@ func (self *streamTogglePipeTracesAction) togglePipeTraces(_ *cobra.Command, arg fmt.Printf("\ntracing enabled successfully\n\n") fmt.Println(result.Message) } else { - fmt.Printf("\ntracing enable failured [%s]\n\n", result.Message) + fmt.Printf("\ntracing enable failed [%s]\n\n", result.Message) } } else { panic(fmt.Errorf("unexpected response type %v", responseMsg.ContentType)) diff --git a/ziti/cmd/fabric/validate_router_links.go b/ziti/cmd/fabric/validate_router_links.go new file mode 100644 index 000000000..719bc561a --- /dev/null +++ b/ziti/cmd/fabric/validate_router_links.go @@ -0,0 +1,144 @@ +/* + 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 fabric + +import ( + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/channel/v2" + "github.com/openziti/channel/v2/protobufs" + "github.com/openziti/ziti/common/pb/mgmt_pb" + "github.com/openziti/ziti/ziti/cmd/api" + "github.com/openziti/ziti/ziti/cmd/common" + "github.com/spf13/cobra" + "google.golang.org/protobuf/proto" + "os" + "time" +) + +type validateRouterLinksAction struct { + api.Options + includeValid bool + + eventNotify chan *mgmt_pb.RouterLinkDetails +} + +func NewValidateRouterLinksCmd(p common.OptionsProvider) *cobra.Command { + action := validateRouterLinksAction{ + Options: api.Options{ + CommonOptions: p(), + }, + } + + validateLinksCmd := &cobra.Command{ + Use: "router-links ", + Short: "Validate router links", + Example: "ziti fabric validate router-links --filter 'name=\"my-router\"' --include-valid", + Args: cobra.MaximumNArgs(1), + RunE: action.validateRouterLinks, + } + + action.AddCommonFlags(validateLinksCmd) + validateLinksCmd.Flags().BoolVar(&action.includeValid, "include-valid", false, "Don't hide results for valid links") + return validateLinksCmd +} + +func (self *validateRouterLinksAction) validateRouterLinks(_ *cobra.Command, args []string) error { + closeNotify := make(chan struct{}) + self.eventNotify = make(chan *mgmt_pb.RouterLinkDetails, 1) + + bindHandler := func(binding channel.Binding) error { + binding.AddReceiveHandler(int32(mgmt_pb.ContentType_ValidateRouterLinksResultType), self) + binding.AddCloseHandler(channel.CloseHandlerF(func(ch channel.Channel) { + close(closeNotify) + })) + return nil + } + + ch, err := api.NewWsMgmtChannel(channel.BindHandlerF(bindHandler)) + if err != nil { + return err + } + + filter := "" + if len(args) > 0 { + filter = args[0] + } + + request := &mgmt_pb.ValidateRouterLinksRequest{ + Filter: filter, + } + + responseMsg, err := protobufs.MarshalTyped(request).WithTimeout(time.Duration(self.Timeout) * time.Second).SendForReply(ch) + + response := &mgmt_pb.ValidateRouterLinksResponse{} + if err = protobufs.TypedResponse(response).Unmarshall(responseMsg, err); err != nil { + return err + } + + if !response.Success { + return fmt.Errorf("failed to start link validation: %s", response.Message) + } + + fmt.Printf("started validation of %v routers\n", response.RouterCount) + + expected := response.RouterCount + + errCount := 0 + for expected > 0 { + select { + case <-closeNotify: + fmt.Printf("channel closed, exiting") + return nil + case routerDetail := <-self.eventNotify: + result := "validation successful" + if !routerDetail.ValidateSuccess { + result = fmt.Sprintf("error: unable to validation (%s)", routerDetail.Message) + errCount++ + } + fmt.Printf("routerId: %s, routerName: %v, links: %v, %s\n", + routerDetail.RouterId, routerDetail.RouterName, len(routerDetail.LinkDetails), result) + + for _, linkDetail := range routerDetail.LinkDetails { + if self.includeValid || !linkDetail.IsValid { + fmt.Printf("\tlinkId: %s, destConnected: %v, ctrlState: %v, routerState: %v, dest: %v, dialed: %v \n", + linkDetail.LinkId, linkDetail.DestConnected, linkDetail.CtrlState, linkDetail.RouterState.String(), + linkDetail.DestRouterId, linkDetail.Dialed) + } + if !linkDetail.IsValid { + errCount++ + } + } + expected-- + } + } + fmt.Printf("%v errors found\n", errCount) + if errCount > 0 { + os.Exit(1) + } + return nil +} + +func (self *validateRouterLinksAction) HandleReceive(msg *channel.Message, _ channel.Channel) { + detail := &mgmt_pb.RouterLinkDetails{} + if err := proto.Unmarshal(msg.Body, detail); err != nil { + pfxlog.Logger().WithError(err).Error("unable to unmarshal router link details") + return + } + + self.eventNotify <- detail +} diff --git a/ziti/cmd/fabric/validate_terminators.go b/ziti/cmd/fabric/validate_terminators.go index a40b1677d..59c2c3d64 100644 --- a/ziti/cmd/fabric/validate_terminators.go +++ b/ziti/cmd/fabric/validate_terminators.go @@ -48,7 +48,7 @@ func NewValidateTerminatorsCmd(p common.OptionsProvider) *cobra.Command { validateTerminatorsCmd := &cobra.Command{ Use: "terminators", Short: "Validate terminators", - Example: "ziti fabric validate terminators --circuits --metrics --metrics-filter '.*'", + Example: "ziti fabric validate terminators --filter 'service.name=\"test\"' --show-only-invalid", Args: cobra.ExactArgs(0), RunE: action.validateTerminators, } diff --git a/ziti/controller/delete_sessions.go b/ziti/controller/delete_sessions.go index 8bb45a0db..0cb844eeb 100644 --- a/ziti/controller/delete_sessions.go +++ b/ziti/controller/delete_sessions.go @@ -18,10 +18,10 @@ package controller import ( "github.com/michaelquigley/pfxlog" - "github.com/openziti/ziti/controller" - fabricdb "github.com/openziti/ziti/controller/db" "github.com/openziti/storage/boltz" "github.com/openziti/ziti/common/version" + "github.com/openziti/ziti/controller" + fabricdb "github.com/openziti/ziti/controller/db" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -178,7 +178,7 @@ func deleteSessions(db boltz.Db) { }) if err != nil { - pfxlog.Logger().Errorf("could not read databse stats: %v", err) + pfxlog.Logger().Errorf("could not read database stats: %v", err) } err = db.Update(nil, func(ctx boltz.MutateContext) error { diff --git a/ziti/pki/store/local.go b/ziti/pki/store/local.go index d0dc98152..d7c54e227 100644 --- a/ziti/pki/store/local.go +++ b/ziti/pki/store/local.go @@ -21,7 +21,6 @@ import ( "crypto/x509/pkix" "encoding/pem" "fmt" - "github.com/openziti/ziti/ziti/pki/certificate" "io" "math/big" "os" @@ -30,10 +29,12 @@ import ( "strings" "time" + "github.com/openziti/ziti/ziti/pki/certificate" + "crypto/x509" ) -// Predifined directory names. +// Predefined directory names. const ( LocalCertsDir = "certs" LocalKeysDir = "keys" @@ -95,7 +96,7 @@ func (l *Local) Fetch(caName, name string) ([]byte, []byte, error) { return k, c, nil } -// FetchKeyBytes fetchs the private key and certificate for a given name signed by caName. +// FetchKeyBytes fetches the private key and certificate for a given name signed by caName. func (l *Local) FetchKeyBytes(caName, name string) ([]byte, error) { filepath.Join(l.Root, caName) @@ -379,7 +380,7 @@ func (l *Local) Update(caName string, sn *big.Int, st certificate.State) error { for scanner.Scan() { matches := indexRegexp.FindStringSubmatch(scanner.Text()) if len(matches) != 7 { - return fmt.Errorf("line [%v] is incorrectly formated", scanner.Text()) + return fmt.Errorf("line [%v] is incorrectly formatted", scanner.Text()) } matchedSerial := big.NewInt(0) @@ -434,7 +435,7 @@ func (l *Local) Revoked(caName string) ([]pkix.RevokedCertificate, error) { for scanner.Scan() { matches := indexRegexp.FindStringSubmatch(scanner.Text()) if len(matches) != 7 { - return nil, fmt.Errorf("line [%v] is incorrectly formated", scanner.Text()) + return nil, fmt.Errorf("line [%v] is incorrectly formatted", scanner.Text()) } if matches[1] != "R" { continue diff --git a/ziti/tunnel/proxy.go b/ziti/tunnel/proxy.go index a830d6654..c74f6a370 100644 --- a/ziti/tunnel/proxy.go +++ b/ziti/tunnel/proxy.go @@ -17,12 +17,13 @@ package tunnel import ( - "github.com/openziti/ziti/tunnel/intercept/proxy" - "github.com/pkg/errors" - "github.com/spf13/cobra" "math" "net" "strconv" + + "github.com/openziti/ziti/tunnel/intercept/proxy" + "github.com/pkg/errors" + "github.com/spf13/cobra" ) func NewProxyCmd() *cobra.Command { @@ -37,7 +38,7 @@ func NewProxyCmd() *cobra.Command { } func runProxy(cmd *cobra.Command, args []string) error { - // Fiddle with the poll rate and resolver settings if the user didn't wan't anything special. + // Fiddle with the poll rate and resolver settings if the user didn't want anything special. if flag := cmd.Flag(svcPollRateFlag); !flag.Changed { _ = flag.Value.Set(strconv.FormatUint(math.MaxUint32, 10)) } diff --git a/ziti/util/identities.go b/ziti/util/identities.go index 182b3087e..2e9878b21 100644 --- a/ziti/util/identities.go +++ b/ziti/util/identities.go @@ -5,14 +5,6 @@ import ( "crypto/x509" "encoding/json" "fmt" - httptransport "github.com/go-openapi/runtime/client" - "github.com/openziti/edge-api/rest_management_api_client" - "github.com/openziti/ziti/controller/env" - fabric_rest_client "github.com/openziti/ziti/controller/rest_client" - "github.com/openziti/identity" - "github.com/openziti/ziti/ziti/cmd/common" - "github.com/pkg/errors" - "gopkg.in/resty.v1" "io" "net" "net/http" @@ -21,6 +13,15 @@ import ( "path/filepath" "strings" "time" + + httptransport "github.com/go-openapi/runtime/client" + "github.com/openziti/edge-api/rest_management_api_client" + "github.com/openziti/identity" + "github.com/openziti/ziti/controller/env" + fabric_rest_client "github.com/openziti/ziti/controller/rest_client" + "github.com/openziti/ziti/ziti/cmd/common" + "github.com/pkg/errors" + "gopkg.in/resty.v1" ) type API string @@ -128,7 +129,7 @@ func (self *RestClientEdgeIdentity) GetBaseUrlForApi(api API) (string, error) { } return u.Scheme + "://" + u.Host + "/fabric/v1", nil } - return "", errors.Errorf("unsupport api %v", api) + return "", errors.Errorf("unsupported api %v", api) } func (self *RestClientEdgeIdentity) NewEdgeManagementClient(clientOpts ClientOpts) (*rest_management_api_client.ZitiEdgeManagement, error) { @@ -217,7 +218,7 @@ func (self *RestClientFabricIdentity) GetBaseUrlForApi(api API) (string, error) } return u.Scheme + "://" + u.Host + "/fabric/v1", nil } - return "", errors.Errorf("unsupport api %v", api) + return "", errors.Errorf("unsupported api %v", api) } func (self *RestClientFabricIdentity) IsReadOnly() bool { diff --git a/ziti/util/session.go b/ziti/util/session.go index 166f1fce6..3ff612507 100644 --- a/ziti/util/session.go +++ b/ziti/util/session.go @@ -56,7 +56,7 @@ func (session *Session) Load() error { return fmt.Errorf("unable to load Ziti CLI configuration. Exiting. Error: %v", err) } if session.Host == "" { - return fmt.Errorf("host not specififed in cli config file. Exiting") + return fmt.Errorf("host not specified in cli config file. Exiting") } return nil } diff --git a/zititest/go.mod b/zititest/go.mod index 0626f3fc4..8bb9d6a61 100644 --- a/zititest/go.mod +++ b/zititest/go.mod @@ -11,13 +11,13 @@ require ( github.com/google/uuid v1.5.0 github.com/michaelquigley/pfxlog v0.6.10 github.com/openziti/agent v1.0.16 - github.com/openziti/channel/v2 v2.0.111 - github.com/openziti/fablab v0.5.32 - github.com/openziti/foundation/v2 v2.0.35 - github.com/openziti/identity v1.0.68 - github.com/openziti/sdk-golang v0.22.0 - github.com/openziti/storage v0.2.27 - github.com/openziti/transport/v2 v2.0.119 + github.com/openziti/channel/v2 v2.0.116 + github.com/openziti/fablab v0.5.38 + github.com/openziti/foundation/v2 v2.0.36 + github.com/openziti/identity v1.0.69 + github.com/openziti/sdk-golang v0.22.17 + github.com/openziti/storage v0.2.28 + github.com/openziti/transport/v2 v2.0.121 github.com/openziti/ziti v0.28.3 github.com/pkg/errors v0.9.1 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 @@ -25,8 +25,8 @@ require ( github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.8.4 go.etcd.io/bbolt v1.3.8 - golang.org/x/net v0.19.0 - google.golang.org/protobuf v1.31.0 + golang.org/x/net v0.20.0 + google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -38,9 +38,10 @@ require ( github.com/alecthomas/chroma v0.10.0 // indirect github.com/andybalholm/brotli v1.0.6 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go v1.47.10 // indirect + github.com/aws/aws-sdk-go v1.49.2 // 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 @@ -62,21 +63,21 @@ require ( github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa // indirect github.com/go-acme/lego/v4 v4.14.2 // indirect github.com/go-jose/go-jose/v3 v3.0.1 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-openapi/analysis v0.21.5 // indirect + github.com/go-openapi/analysis v0.22.2 // indirect github.com/go-openapi/errors v0.21.0 // indirect - github.com/go-openapi/jsonpointer v0.20.1 // indirect - github.com/go-openapi/jsonreference v0.20.3 // indirect - github.com/go-openapi/loads v0.21.3 // indirect + github.com/go-openapi/jsonpointer v0.20.2 // indirect + github.com/go-openapi/jsonreference v0.20.4 // indirect + github.com/go-openapi/loads v0.21.5 // indirect github.com/go-openapi/runtime v0.26.2 // indirect - github.com/go-openapi/spec v0.20.12 // indirect - github.com/go-openapi/strfmt v0.21.10 // indirect - github.com/go-openapi/swag v0.22.5 // indirect - github.com/go-openapi/validate v0.22.3 // indirect - github.com/go-resty/resty/v2 v2.10.0 // indirect - github.com/golang-jwt/jwt/v5 v5.0.0 // indirect + github.com/go-openapi/spec v0.20.14 // indirect + github.com/go-openapi/strfmt v0.22.0 // indirect + github.com/go-openapi/swag v0.22.7 // indirect + github.com/go-openapi/validate v0.22.6 // indirect + github.com/go-resty/resty/v2 v2.11.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 // indirect github.com/gorilla/handlers v1.5.2 // indirect @@ -94,8 +95,10 @@ require ( github.com/hashicorp/raft v1.6.0 // indirect github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/influxdata/influxdb-client-go/v2 v2.13.0 // indirect github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d // indirect - github.com/jedib0t/go-pretty/v6 v6.4.9 // indirect + github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect + github.com/jedib0t/go-pretty/v6 v6.5.3 // indirect github.com/jessevdk/go-flags v1.5.0 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -123,17 +126,19 @@ require ( github.com/mitchellh/go-ps v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/muhlemmer/gu v0.3.1 // indirect + github.com/muhlemmer/httpforwarded v0.1.0 // indirect github.com/natefinch/lumberjack v2.0.0+incompatible // indirect github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce // indirect + github.com/oapi-codegen/runtime v1.0.0 // indirect 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/dilithium v0.3.3 // indirect - github.com/openziti/edge-api v0.26.6 // indirect + github.com/openziti/edge-api v0.26.8 // indirect github.com/openziti/jwks v1.0.3 // indirect - github.com/openziti/metrics v1.2.41 // indirect - github.com/openziti/runzmd v1.0.36 // indirect - github.com/openziti/secretstream v0.1.14 // indirect + github.com/openziti/metrics v1.2.43 // indirect + github.com/openziti/runzmd v1.0.37 // indirect + github.com/openziti/secretstream v0.1.16 // indirect github.com/openziti/x509-claims v1.0.3 // indirect github.com/openziti/xweb/v2 v2.1.0 // indirect github.com/openziti/ziti-db-explorer v1.1.3 // indirect @@ -147,11 +152,11 @@ require ( github.com/rabbitmq/amqp091-go v1.8.1 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rodaine/table v1.0.1 // indirect - github.com/rs/cors v1.9.0 // indirect + github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday v1.6.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/shirou/gopsutil/v3 v3.23.11 // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -159,7 +164,7 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.18.1 // indirect + github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect @@ -170,7 +175,7 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - github.com/zitadel/oidc/v2 v2.7.0 // indirect + github.com/zitadel/oidc/v2 v2.12.0 // indirect go.mongodb.org/mongo-driver v1.13.1 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect go.opentelemetry.io/otel v1.21.0 // indirect @@ -179,17 +184,17 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect go4.org v0.0.0-20180809161055-417644f6feb5 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.18.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/image v0.13.0 // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.14.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + golang.org/x/tools v0.16.0 // indirect + google.golang.org/appengine v1.6.8 // indirect gopkg.in/AlecAivazis/survey.v1 v1.8.7 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/resty.v1 v1.12.0 // indirect diff --git a/zititest/go.sum b/zititest/go.sum index d8d3911cf..77e7fc6ca 100644 --- a/zititest/go.sum +++ b/zititest/go.sum @@ -65,6 +65,7 @@ github.com/MichaelMure/go-term-text v0.3.1/go.mod h1:QgVjAEDUnRMlzpS6ky5CGblux7e github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= 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.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= @@ -82,6 +83,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= @@ -91,8 +94,8 @@ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.47.10 h1:cvufN7WkD1nlOgpRopsmxKQlFp5X1MfyAw4r7BBORQc= -github.com/aws/aws-sdk-go v1.47.10/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.49.2 h1:+4BEcm1nPCoDbVd+gg8cdxpa1qJfrvnddy12vpEVWjw= +github.com/aws/aws-sdk-go v1.49.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= 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= @@ -103,6 +106,7 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= @@ -210,42 +214,42 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-openapi/analysis v0.21.5 h1:3tHfEBh6Ia8eKc4M7khOGjPOAlWKJ10d877Cr9teujI= -github.com/go-openapi/analysis v0.21.5/go.mod h1:25YcZosX9Lwz2wBsrFrrsL8bmjjXdlyP6zsr2AMy29M= +github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0= +github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo= github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY= github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= -github.com/go-openapi/jsonpointer v0.20.1 h1:MkK4VEIEZMj4wT9PmjaUmGflVBr9nvud4Q4UVFbDoBE= -github.com/go-openapi/jsonpointer v0.20.1/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/jsonreference v0.20.3 h1:EjGcjTW8pD1mRis6+w/gmoBdqv5+RbE9B85D1NgDOVQ= -github.com/go-openapi/jsonreference v0.20.3/go.mod h1:FviDZ46i9ivh810gqzFLl5NttD5q3tSlMLqLr6okedM= -github.com/go-openapi/loads v0.21.3 h1:8sSH2FIm/SnbDUGv572md4YqVMFne/a9Eubvcd3anew= -github.com/go-openapi/loads v0.21.3/go.mod h1:Y3aMR24iHbKHppOj91nQ/SHc0cuPbAr4ndY4a02xydc= +github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= +github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= +github.com/go-openapi/loads v0.21.5 h1:jDzF4dSoHw6ZFADCGltDb2lE4F6De7aWSpe+IcsRzT0= +github.com/go-openapi/loads v0.21.5/go.mod h1:PxTsnFBoBe+z89riT+wYt3prmSBP6GDAQh2l9H1Flz8= github.com/go-openapi/runtime v0.26.2 h1:elWyB9MacRzvIVgAZCBJmqTi7hBzU0hlKD4IvfX0Zl0= github.com/go-openapi/runtime v0.26.2/go.mod h1:O034jyRZ557uJKzngbMDJXkcKJVzXJiymdSfgejrcRw= -github.com/go-openapi/spec v0.20.12 h1:cgSLbrsmziAP2iais+Vz7kSazwZ8rsUZd6TUzdDgkVI= -github.com/go-openapi/spec v0.20.12/go.mod h1:iSCgnBcwbMW9SfzJb8iYynXvcY6C/QFrI7otzF7xGM4= -github.com/go-openapi/strfmt v0.21.10 h1:JIsly3KXZB/Qf4UzvzJpg4OELH/0ASDQsyk//TTBDDk= -github.com/go-openapi/strfmt v0.21.10/go.mod h1:vNDMwbilnl7xKiO/Ve/8H8Bb2JIInBnH+lqiw6QWgis= -github.com/go-openapi/swag v0.22.5 h1:fVS63IE3M0lsuWRzuom3RLwUMVI2peDH01s6M70ugys= -github.com/go-openapi/swag v0.22.5/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= -github.com/go-openapi/validate v0.22.3 h1:KxG9mu5HBRYbecRb37KRCihvGGtND2aXziBAv0NNfyI= -github.com/go-openapi/validate v0.22.3/go.mod h1:kVxh31KbfsxU8ZyoHaDbLBWU5CnMdqBUEtadQ2G4d5M= -github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo= -github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= +github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= +github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/strfmt v0.22.0 h1:Ew9PnEYc246TwrEspvBdDHS4BVKXy/AOVsfqGDgAcaI= +github.com/go-openapi/strfmt v0.22.0/go.mod h1:HzJ9kokGIju3/K6ap8jL+OlGAbjpSv27135Yr9OivU4= +github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR8= +github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= +github.com/go-openapi/validate v0.22.6 h1:+NhuwcEYpWdO5Nm4bmvhGLW0rt1Fcc532Mu3wpypXfo= +github.com/go-openapi/validate v0.22.6/go.mod h1:eaddXSqKeTg5XpSmj1dYyFTK/95n/XHwcOY+BMxKMyM= +github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= +github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= -github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= +github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -398,12 +402,17 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb-client-go/v2 v2.2.2/go.mod h1:fa/d1lAdUHxuc1jedx30ZfNG573oQTQmUni3N6pcW+0= +github.com/influxdata/influxdb-client-go/v2 v2.13.0 h1:ioBbLmR5NMbAjP4UVA5r9b5xGjpABD7j65pI8kFphDM= +github.com/influxdata/influxdb-client-go/v2 v2.13.0/go.mod h1:k+spCbt9hcvqvUiz0sr5D8LolXHqAAOfPw9v/RIRHl4= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/jedib0t/go-pretty/v6 v6.4.9 h1:vZ6bjGg2eBSrJn365qlxGcaWu09Id+LHtrfDWlB2Usc= -github.com/jedib0t/go-pretty/v6 v6.4.9/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs= +github.com/jedib0t/go-pretty/v6 v6.5.3 h1:GIXn6Er/anHTkVUoufs7ptEvxdD6KIhR7Axa2wYCPF0= +github.com/jedib0t/go-pretty/v6 v6.5.3/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jeremija/gosubmit v0.2.7 h1:At0OhGCFGPXyjPYAsCchoBUhE099pcBXmsb4iZqROIc= +github.com/jeremija/gosubmit v0.2.7/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI= 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.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= @@ -423,6 +432,7 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kataras/go-events v0.0.3 h1:o5YK53uURXtrlg7qE/vovxd/yKOJcLuFtPQbf1rYMC4= github.com/kataras/go-events v0.0.3/go.mod h1:bFBgtzwwzrag7kQmGuU1ZaVxhK2qseYPQomXoVEMsj4= @@ -499,7 +509,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= @@ -543,6 +552,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= +github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY= +github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= @@ -554,6 +565,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo= +github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 h1:Yl0tPBa8QPjGmesFh1D0rDy+q1Twx6FyU7VWHi8wZbI= @@ -574,32 +587,32 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openziti/agent v1.0.16 h1:9Saji+8hFE1NpzP2XzDhsVJbCrDlhixoLHfOpFt5Z+U= github.com/openziti/agent v1.0.16/go.mod h1:zfm53+PVWoGFzjGGgQdKby5749G6VRYHe+eQJmoVKy4= -github.com/openziti/channel/v2 v2.0.111 h1:ZZDyUUFcyshitXjUqAMjdAKbaDMpgV7oX1Jp1I35Rc4= -github.com/openziti/channel/v2 v2.0.111/go.mod h1:abw0qwT0MzWvh1eI2P6D6CD17PRHL8EEo1d3DHCyCdM= +github.com/openziti/channel/v2 v2.0.116 h1:VUxJ3rICTQz9fmSz6tbssC2tzXafL1MAY6yvgHfSUHI= +github.com/openziti/channel/v2 v2.0.116/go.mod h1:RADBBOkbwpFMmbznU3bZmUsBB646seqZnQ7GPI6Chjg= 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-api v0.26.6 h1:qM5XRaYYZxRIkb3xDkAU1D2EkQx8a+oHvCWbd+v0fbA= -github.com/openziti/edge-api v0.26.6/go.mod h1:DX+fKivCRgnl5oxuLLoEx044arhjlgI7peGlqxN+Iks= -github.com/openziti/fablab v0.5.32 h1:F2n3m+EZ9ulXUnnox2x6SjsuYQkuNnSao62FaLhLSUA= -github.com/openziti/fablab v0.5.32/go.mod h1:qgW8yiZ7lXuE0FZ85pL4t4ohD5JAnNU1r4EdGLs2TM4= -github.com/openziti/foundation/v2 v2.0.35 h1:4VaMwZ2kAy6jwBYeQIBN2m8rcGroTDX4A2Jp7NAKb6M= -github.com/openziti/foundation/v2 v2.0.35/go.mod h1:Xnb3IxP1e1UcgLggqSunEpCjH3iHozkPi9Bd9GESbwo= -github.com/openziti/identity v1.0.68 h1:SaFr7BeFQBoWQDiT28vUb8D9w7v6lIAK6/9RkwmV0OU= -github.com/openziti/identity v1.0.68/go.mod h1:HbOu3TQ032v8xE6xZWjO51azF4fUxRLjO/l/oGqJwUI= +github.com/openziti/edge-api v0.26.8 h1:W1iHwVrb4hVKXWhfN8g/dl1d0RGdus6nOYbhM5ixOEg= +github.com/openziti/edge-api v0.26.8/go.mod h1:Tm2Qn1BC0zF+F261Y8FTyPtS/UkeUtUBYoT6ueCjVbA= +github.com/openziti/fablab v0.5.38 h1:G8ieax/d4LGeRPuMT2XHTOc18jtZTaXtPmjA+5CVO3U= +github.com/openziti/fablab v0.5.38/go.mod h1:LstfQixYgv82aUBR8ranX2Hc9KHohFC1G5/AeaeTMwg= +github.com/openziti/foundation/v2 v2.0.36 h1:ogEIvsWur8/9mUzf9NOB4hRUyx372Uy6AmnHRcurIkY= +github.com/openziti/foundation/v2 v2.0.36/go.mod h1:MdK2oAJSwo7iCfvVdG16ZGz47qP7nG97ovnqEdXW2kQ= +github.com/openziti/identity v1.0.69 h1:wNgQomnv8ar2S1wge9jQK1jpqE2virOKKG8GyfTiHMQ= +github.com/openziti/identity v1.0.69/go.mod h1:+7hQNAG5nUUdz0165OubWpMHkP/ZVJB3nv9HUXXi9H8= github.com/openziti/jwks v1.0.3 h1:hf8wkb+Cg4nH/HM0KROFd7u+C3DkRVcFZJ7tDV+4icc= github.com/openziti/jwks v1.0.3/go.mod h1:t4xxq8vlXGsPn29kiQVnZBBDDnEoOFqtJoHibkJunQQ= -github.com/openziti/metrics v1.2.41 h1:JShcFb6qJPA2cMiWQLtcSXiJjsrhEWpH+aVcjT/Mcbs= -github.com/openziti/metrics v1.2.41/go.mod h1:L9h0NrliMA3+p7+ascKgvx28qoKHymN9l+CMA+Q+sZc= -github.com/openziti/runzmd v1.0.36 h1:HOqTZFzTTFu52qmCAQfFvKDmCSl8ZqP1PQQ0UnJIA4E= -github.com/openziti/runzmd v1.0.36/go.mod h1:jYqummjskmFh63htJFF2SrUuvxNQifqd5REUhYVaY/A= -github.com/openziti/sdk-golang v0.22.0 h1:kOXziZTNvMyJc0DIPoQ9izAukkJTL8nqdrlwWfU/Ul0= -github.com/openziti/sdk-golang v0.22.0/go.mod h1:QdoqZHmiajDHywYCh25SGMMA3NipCvO5Iykf8fHi+sI= -github.com/openziti/secretstream v0.1.14 h1:Ta+nB5Prcct+L5LIKUA1nE56QhWS6lMPQYTlpxUltU0= -github.com/openziti/secretstream v0.1.14/go.mod h1:/hhuLfu+GIv0+cnapfsu/VOnXEvmTt3GKtCu+lQ0RIw= -github.com/openziti/storage v0.2.27 h1:WdFD0KxXZxSoWOaojdi5r1LO0BTvn4x/7wwdwhRPssc= -github.com/openziti/storage v0.2.27/go.mod h1:p/04So5E3NT2jsGew0AS4hYTfP5srti3VytOjlVcx0M= -github.com/openziti/transport/v2 v2.0.119 h1:KOgHU+9EZUVPvv8ncifqHmNEcFUHbJHigo3jyPvWnOc= -github.com/openziti/transport/v2 v2.0.119/go.mod h1:H2IIBP6ed9isE/eJHGXtAZL0d73ApYOpLG9sSvutNNI= +github.com/openziti/metrics v1.2.43 h1:DSrmpLhoA45DlLVNdKOn2lBfCM0/r6wKz+3SDXe8X7Y= +github.com/openziti/metrics v1.2.43/go.mod h1:+RY4avT60Vbxb9wyfvRD0msrARyYCB5+heb8VIZzCm8= +github.com/openziti/runzmd v1.0.37 h1:qj2r9z4t7OAdmIXMdGbP9Su6TqA0bLdD2RMjJ71LRS0= +github.com/openziti/runzmd v1.0.37/go.mod h1:eKhqJsGoLeDHex/o5Mw6TcNJxlVljafSVm7ZU+bX5G8= +github.com/openziti/sdk-golang v0.22.17 h1:taywYpWpWBtZUj6KewMScYXgPe8TWz2nWNl96/y/IZ4= +github.com/openziti/sdk-golang v0.22.17/go.mod h1:t0sT5N1Q/LdAd54Dxz274sQ9vJo8/B5Q0jn+VZ9vFuw= +github.com/openziti/secretstream v0.1.16 h1:tVanF7OpJL1MJ1gvWaRlR2i+kAbrGsxr3q6EXFOS08U= +github.com/openziti/secretstream v0.1.16/go.mod h1:bvjGBUW/0e5MzD5S3FW3rhGASRNWAi+kTkTENZ9qRDE= +github.com/openziti/storage v0.2.28 h1:qHnsSF4RgQpT23hOXlwkAvJ0gO5PLmvTqyBy13dm3Rc= +github.com/openziti/storage v0.2.28/go.mod h1:ahdvsmmdQWFsZXeExvXeA8MHUXPLrwuDFBJDTztLY5E= +github.com/openziti/transport/v2 v2.0.121 h1:9WB1/9YMFed2UuefqZq+odUYYkoFOr+8aBIAZEC1MNE= +github.com/openziti/transport/v2 v2.0.121/go.mod h1:hS7TzoyTIwm4lVEsGyjQkoEg+vA+6dAOR8S4FZmWIj4= 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.1.0 h1:Xhh3C2pZkq/Prr65V+SfFSibLDYteoc4f62KQCcTZF4= @@ -622,7 +635,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= -github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= @@ -673,8 +685,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= @@ -687,8 +699,8 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ= -github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -753,8 +765,9 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.18.1 h1:rmuU42rScKWlhhJDyXZRKJQHXFX02chSVW1IvkPGiVM= -github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= 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= @@ -770,7 +783,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -813,8 +825,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zitadel/oidc/v2 v2.7.0 h1:IGX4EDk6tegTjUSsZDWeTfLseFU0BdJ/Glf1tgys2lU= -github.com/zitadel/oidc/v2 v2.7.0/go.mod h1:zkUkVJS0sDVy9m0UA9RgO3f8i/C0rtjvXU36UJj7T+0= +github.com/zitadel/oidc/v2 v2.12.0 h1:4aMTAy99/4pqNwrawEyJqhRb3yY3PtcDxnoDSryhpn4= +github.com/zitadel/oidc/v2 v2.12.0/go.mod h1:LrRav74IiThHGapQgCHZOUNtnqJG0tcZKHro/91rtLw= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= @@ -878,8 +890,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= 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= @@ -924,8 +936,8 @@ 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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= @@ -979,8 +991,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= 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= @@ -995,8 +1007,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1093,16 +1105,17 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= 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= @@ -1183,8 +1196,8 @@ 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.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= 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= @@ -1222,8 +1235,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1304,8 +1318,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/AlecAivazis/survey.v1 v1.8.7 h1:oBJqtgsyBLg9K5FK9twNUbcPnbCPoh+R9a+7nag3qJM= gopkg.in/AlecAivazis/survey.v1 v1.8.7/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/zititest/models/links-test/configs/ctrl.yml.tmpl b/zititest/models/links-test/configs/ctrl.yml.tmpl new file mode 100644 index 000000000..cb270a814 --- /dev/null +++ b/zititest/models/links-test/configs/ctrl.yml.tmpl @@ -0,0 +1,197 @@ +v: 3 + +raft: + minClusterSize: 3 + dataDir: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/ctrldata + +identity: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}-server.chain.pem + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/keys/{{ .Component.Id }}-server.key + ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}.chain.pem + +# the endpoint that routers will connect to the controller over. +ctrl: + listener: tls:0.0.0.0:6262 + options: + advertiseAddress: tls:{{ .Host.PublicIp }}:6262 + # (optional) settings + # set the maximum number of connect requests that are buffered and waiting to be acknowledged (1 to 5000, default 1000) + #maxQueuedConnects: 50 + + # the maximum number of connects that have begun hello synchronization (1 to 1000, default 16) + #maxOutstandingConnects: 100 + + # the number of milliseconds to wait before a hello synchronization fails and closes the connection (30ms to 60000ms, default: 1000ms) + #connectTimeoutMs: 3000 + + # Sets the control channel write timeout. A write timeout will close the control channel, so the router will reconnect + #writeTimeout: 15s + + # A listener address which will be sent to connecting routers in order to change their configured controller + # address. If defined, routers will update address configuration to immediately use the new address for future + # connections. The value of newListener must be resolvable both via DNS and validate via certificates + #newListener: tls:localhost:6262 + +events: + jsonLogger: + subscriptions: + - type: entityChange + - type: edge.apiSessions + - type: edge.entityCounts + interval: 15s + - type: edge.sessions + - type: fabric.routers + - type: fabric.terminators +# - type: metrics +# sourceFilter: .* +# metricFilter: .*egress.*m1_rate* +# - type: fabric.circuits +# include: +# - created +# include: +# - created +# - type: fabric.usage +# - type: services +# - type: fabric.usage + handler: + type: file + format: json + path: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/logs/event.log + +healthChecks: + boltCheck: + # How often to try entering a bolt read tx. Defaults to 30 seconds + interval: 30s + # When to timeout the check. Defaults to 15 seconds + timeout: 15s + # How long to wait before starting the check. Defaults to 15 seconds + initialDelay: 15s + +# By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the edge to not run. +edge: + # This section represents the configuration of the Edge API that is served over HTTPS + api: + #(optional, default 90s) Alters how frequently heartbeat and last activity values are persisted + # activityUpdateInterval: 90s + #(optional, default 250) The number of API Sessions updated for last activity per transaction + # activityUpdateBatchSize: 250 + # sessionTimeout - optional, default 10m + # The number of minutes before an Edge API session will timeout. Timeouts are reset by + # API requests and connections that are maintained to Edge Routers + sessionTimeout: 30m + # address - required + # The default address (host:port) to use for enrollment for the Client API. This value must match one of the addresses + # defined in a bind point's address field for the `edge-client` API in the web section. + address: {{ .Host.PublicIp }}:1280 + # enrollment - required + # A section containing settings pertaining to enrollment. + enrollment: + # signingCert - required + # A Ziti Identity configuration section that specifically makes use of the cert and key fields to define + # a signing certificate from the PKI that the Ziti environment is using to sign certificates. The signingCert.cert + # will be added to the /.well-known CA store that is used to bootstrap trust with the Ziti Controller. + signingCert: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}.cert + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/keys/{{ .Component.Id }}.key + + # edgeIdentity - optional + # A section for identity enrollment specific settings + edgeIdentity: + # duration - optional, default 5m + # The length of time that a Ziti Edge Identity enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + duration: 1h + # edgeRouter - Optional + # A section for edge router enrollment specific settings. + edgeRouter: + # duration - optional, default 5m + # The length of time that a Ziti Edge Router enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + duration: 1h + + +# web - optional +# Defines webListeners that will be hosted by the controller. Each webListener can host many APIs and be bound to many +# bind points. +web: + # name - required + # Provides a name for this listener, used for logging output. Not required to be unique, but is highly suggested. + - name: all-apis-localhost + # bindPoints - required + # One or more bind points are required. A bind point specifies an interface (interface:port string) that defines + # where on the host machine the webListener will listen and the address (host:port) that should be used to + # publicly address the webListener(i.e. mydomain.com, localhost, 127.0.0.1). This public address may be used for + # incoming address resolution as well as used in responses in the API. + bindPoints: + #interface - required + # A host:port string on which network interface to listen on. 0.0.0.0 will listen on all interfaces + - interface: 0.0.0.0:1280 + + # address - required + # The public address that external incoming requests will be able to resolve. Used in request processing and + # response content that requires full host:port/path addresses. + address: {{ .Host.PublicIp }}:1280 + + # newAddress - optional + # A host:port string which will be sent out as an HTTP header "ziti-new-address" if specified. If the header + # is present, clients should update location configuration to immediately use the new address for future + # connections. The value of newAddress must be resolvable both via DNS and validate via certificates + #newAddress: localhost:1280 + # identity - optional + # Allows the webListener to have a specific identity instead of defaulting to the root `identity` section. + # identity: + # cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-client.cert.pem + # server_cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-server.cert.pem + # key: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/private/ctrl.key.pem + # ca: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ca-chain.cert.pem + # options - optional + # Allows the specification of webListener level options - mainly dealing with HTTP/TLS settings. These options are + # used for all http servers started by the current webListener. + options: + # idleTimeout - optional, default 5000ms + # The maximum amount of idle time in milliseconds allowed for pipelined HTTP requests. Setting this too high + # can cause resources on the host to be consumed as clients remain connected and idle. Lowering this value + # will cause clients to reconnect on subsequent HTTPs requests. + idleTimeout: 5000ms #http timeouts, new + + # readTimeout - optional, default 5000ms + # The maximum amount of time in milliseconds http servers will wait to read the first incoming requests. A higher + # value risks consuming resources on the host with clients that are acting bad faith or suffering from high latency + # or packet loss. A lower value can risk losing connections to high latency/packet loss clients. + + readTimeout: 5000ms + # writeTimeout - optional, default 10000ms + # The total maximum time in milliseconds that the http server will wait for a single requests to be received and + # responded too. A higher value can allow long running requests to consume resources on the host. A lower value + # can risk ending requests before the server has a chance to respond. + + writeTimeout: 100000ms + # minTLSVersion - optional, default TSL1.2 + # The minimum version of TSL to support + + minTLSVersion: TLS1.2 + # maxTLSVersion - optional, default TSL1.3 + # The maximum version of TSL to support + + maxTLSVersion: TLS1.3 + # apis - required + # Allows one or more APIs to be bound to this webListener + apis: + # binding - required + # Specifies an API to bind to this webListener. Built-in APIs are + # - health-checks + # - edge-management + # - edge-client + # - fabric-management + - binding: health-checks + options: {} + - binding: fabric + - binding: edge-management + # options - variable optional/required + # This section is used to define values that are specified by the API they are associated with. + # These settings are per API. The example below is for the `edge-api` and contains both optional values and + # required values. + options: {} + - binding: edge-client + options: {} diff --git a/zititest/models/links-test/configs/router.yml.tmpl b/zititest/models/links-test/configs/router.yml.tmpl new file mode 100644 index 000000000..2e6a24f04 --- /dev/null +++ b/zititest/models/links-test/configs/router.yml.tmpl @@ -0,0 +1,75 @@ +{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}} +{{$identity := .Component.Id}} +{{$router_ip := .Host.PublicIp}} + +v: 3 + +enableDebugOps: true + +identity: + cert: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-client.cert + server_cert: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-server.cert + key: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}.key + ca: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-server.chain.pem + +tls: + handshakeTimeout: 30s + +ctrl: + endpoints: {{ range $host := .Model.MustSelectHosts "component.ctrl" 1 }} + - tls:{{ $host.PublicIp }}:6262{{end}} + +healthChecks: + ctrlPingCheck: + # How often to ping the controller over the control channel. Defaults to 30 seconds + interval: 30s + # When to timeout the ping. Defaults to 15 seconds + timeout: 15s + # How long to wait before pinging the controller. Defaults to 15 seconds + initialDelay: 15s + +metrics: + reportInterval: 15s + messageQueueSize: 10 + +link: + listeners: + - binding: transport + bind: tls:0.0.0.0:60{{printf "%02d" .Component.ScaleIndex }} + advertise: tls:{{$router_ip}}:60{{printf "%02d" .Component.ScaleIndex }} + dialers: + - binding: transport + options: + connectTimeout: 30s + +listeners: +{{if .Component.HasTag "tunneler"}} + - binding: tunnel + options: + mode: host +{{end}} + - binding: edge + address: tls:0.0.0.0:62{{printf "%02d" .Component.ScaleIndex }} + options: + # (required) The public hostname and port combination that Ziti SDKs should connect on. Previously this was in the chanIngress section. + advertise: {{ .Host.PublicIp }}:62{{printf "%02d" .Component.ScaleIndex }} + +# By having an 'edge' section defined, the ziti-router will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge +# Router. +edge: + # (required) Information used to generate the initial registration CSR. For documentation on these fields please + # refer to the openssl documentation. These values MUST be supplied and have no defaults. + csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + + # (required) SANs that this Gateways certs should contain. At least one IP or DNS SAN should be defined that matches + # the edge listeners "advertise" value from the "listeners" section. + sans: + ip: + - {{ .Host.PublicIp }} + diff --git a/zititest/models/links-test/main.go b/zititest/models/links-test/main.go new file mode 100644 index 000000000..a59fa8c76 --- /dev/null +++ b/zititest/models/links-test/main.go @@ -0,0 +1,277 @@ +package main + +import ( + "embed" + _ "embed" + "fmt" + "github.com/openziti/fablab" + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/lib/actions/semaphore" + "github.com/openziti/fablab/kernel/lib/binding" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/aws_ssh_key" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/semaphore" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/terraform" + distribution "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution" + "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution/rsync" + aws_ssh_key2 "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/aws_ssh_key" + "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/fablab/resources" + "github.com/openziti/ziti/zititest/models/test_resources" + "github.com/openziti/ziti/zititest/zitilab" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/chaos" + "github.com/openziti/ziti/zititest/zitilab/models" + "os" + "path" + "time" +) + +const TargetZitiVersion = "" + +//go:embed configs +var configResource embed.FS + +type scaleStrategy struct{} + +func (self scaleStrategy) IsScaled(entity model.Entity) bool { + return entity.GetScope().HasTag("scaled") +} + +func (self scaleStrategy) GetEntityCount(entity model.Entity) uint32 { + if entity.GetType() == model.EntityTypeComponent { + return 20 + } + return 5 +} + +var m = &model.Model{ + Id: "links-test", + Scope: model.Scope{ + Defaults: model.Variables{ + "environment": "links-test", + "credentials": model.Variables{ + "aws": model.Variables{ + "managed_key": true, + }, + "ssh": model.Variables{ + "username": "ubuntu", + }, + "edge": model.Variables{ + "username": "admin", + "password": "admin", + }, + }, + "metrics": model.Variables{ + "influxdb": model.Variables{ + "url": "http://localhost:8086", + "db": "ziti", + }, + }, + }, + }, + StructureFactories: []model.Factory{ + model.NewScaleFactoryWithDefaultEntityFactory(scaleStrategy{}), + model.FactoryFunc(func(m *model.Model) error { + return m.ForEachHost("component.ctrl", 1, func(host *model.Host) error { + if host.InstanceType == "" { + host.InstanceType = "t3.medium" + } + return nil + }) + }), + model.FactoryFunc(func(m *model.Model) error { + return m.ForEachHost("component.router", 1, func(host *model.Host) error { + host.InstanceType = "c5.xlarge" + return nil + }) + }), + }, + Resources: model.Resources{ + resources.Configs: resources.SubFolder(configResource, "configs"), + resources.Binaries: os.DirFS(path.Join(os.Getenv("GOPATH"), "bin")), + resources.Terraform: test_resources.TerraformResources(), + }, + Regions: model.Regions{ + "us-east-1": { + Region: "us-east-1", + Site: "us-east-1a", + Hosts: model.Hosts{ + "ctrl1": { + InstanceType: "t3.medium", + Components: model.Components{ + "ctrl1": { + Scope: model.Scope{Tags: model.Tags{"ctrl"}}, + Type: &zitilab.ControllerType{ + Version: TargetZitiVersion, + }, + }, + }, + }, + "router-us-east-{{.ScaleIndex}}": { + Scope: model.Scope{Tags: model.Tags{"scaled"}}, + Components: model.Components{ + "router-us-east-{{ .Host.ScaleIndex }}.{{ .ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"router", "scaled"}}, + Type: &zitilab.RouterType{ + Version: TargetZitiVersion, + }, + }, + }, + }, + }, + }, + "us-west-2": { + Region: "us-west-2", + Site: "us-west-2b", + Hosts: model.Hosts{ + "ctrl2": { + Components: model.Components{ + "ctrl2": { + Scope: model.Scope{Tags: model.Tags{"ctrl"}}, + Type: &zitilab.ControllerType{ + Version: TargetZitiVersion, + }, + }, + }, + }, + "router-us-west-{{.ScaleIndex}}": { + Scope: model.Scope{Tags: model.Tags{"scaled"}}, + Components: model.Components{ + "router-us-west-{{ .Host.ScaleIndex }}.{{ .ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"router", "scaled"}}, + Type: &zitilab.RouterType{ + Version: TargetZitiVersion, + }, + }, + }, + }, + }, + }, + "eu-west-2": { + Region: "eu-west-2", + Site: "eu-west-2a", + Hosts: model.Hosts{ + "ctrl3": { + InstanceType: "c5.large", + Components: model.Components{ + "ctrl3": { + Scope: model.Scope{Tags: model.Tags{"ctrl"}}, + Type: &zitilab.ControllerType{ + Version: TargetZitiVersion, + }, + }, + }, + }, + "router-eu-west-{{.ScaleIndex}}": { + Scope: model.Scope{Tags: model.Tags{"scaled"}}, + Components: model.Components{ + "router-eu-west-{{ .Host.ScaleIndex }}.{{ .ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"router", "scaled"}}, + Type: &zitilab.RouterType{ + Version: TargetZitiVersion, + }, + }, + }, + }, + }, + }, + + "eu-central-1": { + Region: "eu-central-1", + Site: "eu-central-1a", + Hosts: model.Hosts{ + "router-eu-central-{{.ScaleIndex}}": { + Scope: model.Scope{Tags: model.Tags{"scaled"}}, + Components: model.Components{ + "router-eu-central-{{ .Host.ScaleIndex }}.{{ .ScaleIndex }}": { + Scope: model.Scope{Tags: model.Tags{"router", "scaled"}}, + Type: &zitilab.RouterType{ + Version: TargetZitiVersion, + }, + }, + }, + }, + }, + }, + }, + + Actions: model.ActionBinders{ + "bootstrap": model.ActionBinder(func(m *model.Model) model.Action { + workflow := actions.Workflow() + + workflow.AddAction(host.GroupExec("*", 50, "touch .hushlogin")) + workflow.AddAction(component.Stop(".ctrl")) + workflow.AddAction(host.GroupExec("*", 50, "rm -f logs/*")) + workflow.AddAction(host.GroupExec("component.ctrl", 5, "rm -rf ./fablab/ctrldata")) + + workflow.AddAction(component.Start(".ctrl")) + workflow.AddAction(edge.RaftJoin(".ctrl")) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + workflow.AddAction(edge.InitRaftController("#ctrl1")) + workflow.AddAction(edge.ControllerAvailable("#ctrl1", 30*time.Second)) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + + workflow.AddAction(edge.Login("#ctrl1")) + + workflow.AddAction(component.StopInParallel(models.RouterTag, 50)) + workflow.AddAction(edge.InitEdgeRouters(models.RouterTag, 2)) + + return workflow + }), + "clean": model.Bind(actions.Workflow( + component.StopInParallelHostExclusive("*", 15), + host.GroupExec("*", 25, "rm -f logs/*"), + )), + "login": model.Bind(edge.Login("#ctrl1")), + "login2": model.Bind(edge.Login("#ctrl2")), + "login3": model.Bind(edge.Login("#ctrl3")), + "sowChaos": model.Bind(model.ActionFunc(sowChaos)), + }, + + Infrastructure: model.Stages{ + aws_ssh_key.Express(), + &terraform_0.Terraform{ + Retries: 3, + ReadyCheck: &semaphore_0.ReadyStage{ + MaxWait: 90 * time.Second, + }, + }, + }, + + Distribution: model.Stages{ + distribution.DistributeSshKey("*"), + rsync.RsyncStaged(), + }, + + Disposal: model.Stages{ + terraform.Dispose(), + aws_ssh_key2.Dispose(), + }, +} + +func sowChaos(run model.Run) error { + controllers, err := chaos.SelectRandom(run, ".ctrl", chaos.RandomOfTotal()) + if err != nil { + return err + } + routers, err := chaos.SelectRandom(run, ".router", chaos.Percentage(15)) + if err != nil { + return err + } + toRestart := append(routers, controllers...) + fmt.Printf("restarting %v controllers and %v routers\n", len(controllers), len(routers)) + return chaos.RestartSelected(run, toRestart, 50) +} + +func main() { + m.AddActivationActions("stop", "bootstrap") + + model.AddBootstrapExtension(binding.AwsCredentialsLoader) + model.AddBootstrapExtension(aws_ssh_key.KeyManager) + + fablab.InitModel(m) + fablab.Run() +} diff --git a/zititest/models/simple/configs/ctrl.yml.tmpl b/zititest/models/simple/configs/ctrl.yml.tmpl index be10aa95a..d9627275e 100644 --- a/zititest/models/simple/configs/ctrl.yml.tmpl +++ b/zititest/models/simple/configs/ctrl.yml.tmpl @@ -9,9 +9,9 @@ db: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/ctrl.db {{end}} identity: - cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}-server.cert + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}-server.chain.pem key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/keys/{{ .Component.Id }}-server.key - ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}-server.chain.pem + ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}.chain.pem # the endpoint that routers will connect to the controller over. ctrl: diff --git a/zititest/models/test_resources/terraform/vpc/main.tf b/zititest/models/test_resources/terraform/vpc/main.tf index 1abdc99a9..62c4c466a 100644 --- a/zititest/models/test_resources/terraform/vpc/main.tf +++ b/zititest/models/test_resources/terraform/vpc/main.tf @@ -87,27 +87,15 @@ resource "aws_security_group" "fablab" { protocol = "udp" cidr_blocks = ["0.0.0.0/0"] } - ingress { - from_port = 6262 - to_port = 6262 - protocol = "tcp" - cidr_blocks = ["0.0.0.0/0"] - } - ingress { - from_port = 6262 - to_port = 6262 - protocol = "udp" - cidr_blocks = ["0.0.0.0/0"] - } ingress { from_port = 6000 - to_port = 6009 + to_port = 6400 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 6000 - to_port = 6009 + to_port = 6400 protocol = "udp" cidr_blocks = ["0.0.0.0/0"] } diff --git a/zititest/ziti-fabric-test/subcmd/loop2/dialer.go b/zititest/ziti-fabric-test/subcmd/loop2/dialer.go index 5ee6ed465..562fbf4a7 100644 --- a/zititest/ziti-fabric-test/subcmd/loop2/dialer.go +++ b/zititest/ziti-fabric-test/subcmd/loop2/dialer.go @@ -18,17 +18,18 @@ package loop2 import ( "fmt" + "net" + "strings" + "time" + "github.com/michaelquigley/pfxlog" - "github.com/openziti/ziti/router/xgress_transport" "github.com/openziti/identity" "github.com/openziti/identity/dotziti" "github.com/openziti/sdk-golang/ziti" "github.com/openziti/transport/v2" - "github.com/openziti/ziti/zititest/ziti-fabric-test/subcmd/loop2/pb" + "github.com/openziti/ziti/router/xgress_transport" + loop2_pb "github.com/openziti/ziti/zititest/ziti-fabric-test/subcmd/loop2/pb" "github.com/spf13/cobra" - "net" - "strings" - "time" ) func init() { @@ -168,7 +169,7 @@ func (cmd *dialerCmd) connect() net.Conn { context, err = ziti.NewContext(zitiCfg) if err != nil { - log.Fatalf("failed to load ziti context fromt configuration: %v", err) + log.Fatalf("failed to load ziti context from configuration: %v", err) } } else { log.Fatal("no configuration file provided") diff --git a/zititest/zitilab/actions/consul.go b/zititest/zitilab/actions/consul.go deleted file mode 100644 index 883ef89a4..000000000 --- a/zititest/zitilab/actions/consul.go +++ /dev/null @@ -1,41 +0,0 @@ -package zitilib_actions - -import ( - "fmt" - "github.com/openziti/fablab/kernel/libssh" - - "github.com/openziti/fablab/kernel/model" - "github.com/sirupsen/logrus" -) - -type consulStart struct { - hostSpec string - consulServer string - configDir string - dataPath string - logFile string -} - -func StartConsul(hostSpec, consulServer, configDir, dataPath, logFile string) model.Action { - return &consulStart{ - hostSpec: hostSpec, - consulServer: consulServer, - configDir: configDir, - dataPath: dataPath, - logFile: logFile, - } -} - -func (cs *consulStart) Execute(run model.Run) error { - return run.GetModel().ForEachHost(cs.hostSpec, 24, func(host *model.Host) error { - ssh := host.NewSshConfigFactory() - - cmd := fmt.Sprintf("screen -d -m nohup consul agent -join %s -config-dir %s -data-dir %s -log-file %s 2>&1 &", cs.consulServer, cs.configDir, cs.dataPath, cs.logFile) - - if output, err := libssh.RemoteExec(ssh, cmd); err != nil { - logrus.Errorf("error starting consul service [%s] (%v)", output, err) - return err - } - return nil - }) -} diff --git a/zititest/zitilab/chaos/chaos.go b/zititest/zitilab/chaos/chaos.go new file mode 100644 index 000000000..524a8559d --- /dev/null +++ b/zititest/zitilab/chaos/chaos.go @@ -0,0 +1,75 @@ +/* + 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 chaos + +import ( + "fmt" + "github.com/openziti/fablab/kernel/model" + "math/rand" +) + +func StaticNumber(val int) func(int) int { + return func(int) int { + return val + } +} +func RandomOfTotal() func(count int) int { + return func(count int) int { + return rand.Intn(count) + 1 + } +} + +func Percentage(pct uint8) func(count int) int { + adjustedPct := float64(pct) / 100 + return func(count int) int { + return int(float64(count) * adjustedPct) + } +} + +func SelectRandom(run model.Run, selector string, f func(count int) int) ([]*model.Component, error) { + list := run.GetModel().SelectComponents(selector) + toSelect := f(len(list)) + + if toSelect < 1 { + return nil, nil + } + + rand.Shuffle(len(list), func(i, j int) { + list[i], list[j] = list[j], list[i] + }) + + var result []*model.Component + for i := 0; i < len(list) && i < toSelect; i++ { + result = append(result, list[i]) + } + return result, nil +} + +func RestartSelected(run model.Run, list []*model.Component, concurrency int) error { + if len(list) == 0 { + return nil + } + return run.GetModel().ForEachComponentIn(list, concurrency, func(c *model.Component) error { + if sc, ok := c.Type.(model.ServerComponent); ok { + if err := c.Type.Stop(run, c); err != nil { + return err + } + return sc.Start(run, c) + } + return fmt.Errorf("component %v isn't of ServerComponent type, is of type %T", c, c.Type) + }) +} diff --git a/zititest/zitilab/component_common.go b/zititest/zitilab/component_common.go index fde736691..e33031a35 100644 --- a/zititest/zitilab/component_common.go +++ b/zititest/zitilab/component_common.go @@ -29,7 +29,7 @@ func getZitiProcessFilter(c *model.Component, zitiType string) func(string) bool return func(s string) bool { return strings.Contains(s, "ziti") && strings.Contains(s, zitiType) && - strings.Contains(s, fmt.Sprintf("--cli-agent-alias %s", c.Id)) && + strings.Contains(s, fmt.Sprintf("--cli-agent-alias %s ", c.Id)) && !strings.Contains(s, "sudo ") } } @@ -46,8 +46,8 @@ func startZitiComponent(c *model.Component, zitiType string, version string, con useSudo = "sudo" } - serviceCmd := fmt.Sprintf("nohup %s %s %s run --log-formatter pfxlog %s --cli-agent-alias %s > %s 2>&1 &", - useSudo, binaryPath, zitiType, configPath, c.Id, logsPath) + serviceCmd := fmt.Sprintf("nohup %s %s %s run --cli-agent-alias %s --log-formatter pfxlog %s > %s 2>&1 &", + useSudo, binaryPath, zitiType, c.Id, configPath, logsPath) logrus.Info(serviceCmd) value, err := c.GetHost().ExecLogged(serviceCmd) if err != nil { diff --git a/zititest/zitilab/component_router.go b/zititest/zitilab/component_router.go index 6b4cafd81..3b0ba2226 100644 --- a/zititest/zitilab/component_router.go +++ b/zititest/zitilab/component_router.go @@ -116,7 +116,15 @@ func (self *RouterType) IsRunning(_ model.Run, c *model.Component) (bool, error) return len(pids) > 0, nil } -func (self *RouterType) Start(_ model.Run, c *model.Component) error { +func (self *RouterType) Start(r model.Run, c *model.Component) error { + isRunninng, err := self.IsRunning(r, c) + if err != nil { + return err + } + if isRunninng { + fmt.Printf("router %s already started\n", c.Id) + return nil + } return startZitiComponent(c, "router", self.Version, self.getConfigName(c)) }