From 5e20e13c8e6e6eca37eb8ca89a422353024a4912 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Mon, 16 Sep 2024 16:35:49 -0400 Subject: [PATCH 01/97] ci: fix CI skip script hole (#21741) In some environments, the script will not fail despite SKIP_CHECK_BRANCH being unset, leading to the script explicitly skipping CI when it should fail fast. Prevent this by explicitly checking for the env var. --- .github/scripts/check_skip_ci.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/scripts/check_skip_ci.sh b/.github/scripts/check_skip_ci.sh index 628d8489dfad..a22b990f2692 100755 --- a/.github/scripts/check_skip_ci.sh +++ b/.github/scripts/check_skip_ci.sh @@ -13,7 +13,8 @@ set -euo pipefail # # ... `git merge-base origin/$SKIP_CHECK_BRANCH HEAD` would return commit `D` # `...HEAD` specifies from the common ancestor to the latest commit on the current branch (HEAD).. -files_to_check=$(git diff --name-only "$(git merge-base origin/$SKIP_CHECK_BRANCH HEAD~)"...HEAD) +skip_check_branch=${SKIP_CHECK_BRANCH:?SKIP_CHECK_BRANCH is required} +files_to_check=$(git diff --name-only "$(git merge-base origin/$skip_check_branch HEAD~)"...HEAD) # Define the directories to check skipped_directories=("docs/" "ui/" "website/" "grafana/" ".changelog/") @@ -46,4 +47,4 @@ for file_to_check in "${files_to_check_array[@]}"; do done echo "Changes detected in only documentation files - skipping tests and build" -echo "skip-ci=true" >> "$GITHUB_OUTPUT" \ No newline at end of file +echo "skip-ci=true" >> "$GITHUB_OUTPUT" From e0785bc4f94d377b59c41fc82991776d37970717 Mon Sep 17 00:00:00 2001 From: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:06:56 -0500 Subject: [PATCH 02/97] Initialize 1.20 Release (#21746) * init release branch * init 1.20 nightly tests * drop 1.17 nightly tests for new release cycle * drop 1.17 from test matrix * Update nightly-test-integrations-1.20.x.yml --- ...l => nightly-test-integrations-1.20.x.yml} | 30 +++++++------------ .release/versions.hcl | 3 ++ version/VERSION | 2 +- 3 files changed, 15 insertions(+), 20 deletions(-) rename .github/workflows/{nightly-test-integrations-1.17.x.yml => nightly-test-integrations-1.20.x.yml} (97%) diff --git a/.github/workflows/nightly-test-integrations-1.17.x.yml b/.github/workflows/nightly-test-integrations-1.20.x.yml similarity index 97% rename from .github/workflows/nightly-test-integrations-1.17.x.yml rename to .github/workflows/nightly-test-integrations-1.20.x.yml index 471cdb163f04..a1dd9169f3a4 100644 --- a/.github/workflows/nightly-test-integrations-1.17.x.yml +++ b/.github/workflows/nightly-test-integrations-1.20.x.yml @@ -1,7 +1,7 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly test-integrations 1.17.x +name: Nightly test-integrations 1.20.x on: schedule: @@ -19,19 +19,12 @@ env: # strip the hashicorp/ off the front of github.repository for consul CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} GOPRIVATE: github.com/hashicorp # Required for enterprise deps - BRANCH: "release/1.17.x" - BRANCH_NAME: "release-1.17.x" # Used for naming artifacts + BRANCH: "release/1.20.x" + BRANCH_NAME: "release-1.20.x" # Used for naming artifacts jobs: - check-ent: - runs-on: ubuntu-latest - if: ${{ endsWith(github.repository, '-enterprise') }} - steps: - - run: echo "Building Enterprise" - setup: runs-on: ubuntu-latest - needs: [check-ent] name: Setup outputs: compute-small: ${{ steps.runners.outputs.compute-small }} @@ -48,16 +41,14 @@ jobs: run: .github/scripts/get_runner_classes.sh get-go-version: - needs: [check-ent] uses: ./.github/workflows/reusable-get-go-version.yml with: - ref: release/1.17.x + ref: release/1.20.x get-envoy-versions: - needs: [check-ent] uses: ./.github/workflows/reusable-get-envoy-versions.yml with: - ref: release/1.17.x + ref: release/1.20.x dev-build: needs: @@ -68,7 +59,7 @@ jobs: runs-on: ${{ needs.setup.outputs.compute-large }} repository-name: ${{ github.repository }} uploaded-binary-name: 'consul-bin' - branch-name: "release/1.17.x" + branch-name: "release/1.20.x" go-version: ${{ needs.get-go-version.outputs.go-version }} secrets: elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} @@ -223,12 +214,13 @@ jobs: DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" DD_ENV: ci run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - + upgrade-integration-test: runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} needs: - setup - get-go-version + - get-envoy-versions - dev-build permissions: id-token: write # NOTE: this permission is explicitly required for Vault auth. @@ -236,7 +228,7 @@ jobs: strategy: fail-fast: false matrix: - consul-version: ["1.15", "1.16", "1.17"] + consul-version: ["1.15", "1.18", "1.19"] env: CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} # ENVOY_VERSION should be the latest version supported by _all_ Consul versions in the @@ -372,7 +364,7 @@ jobs: strategy: fail-fast: false matrix: - consul-version: [ "1.15", "1.16", "1.17"] + consul-version: ["1.15", "1.18", "1.19"] env: CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} steps: @@ -460,7 +452,7 @@ jobs: - upgrade-integration-test - upgrade-integration-test-deployer runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() && endsWith(github.repository, '-enterprise') }} + if: ${{ always() }} steps: - name: evaluate upstream job results run: | diff --git a/.release/versions.hcl b/.release/versions.hcl index fdc0f2989d27..7c5b4ee7eb28 100644 --- a/.release/versions.hcl +++ b/.release/versions.hcl @@ -6,6 +6,9 @@ schema = 1 active_versions { + version "1.20" { + ce_active = true + }, version "1.19" { ce_active = true } diff --git a/version/VERSION b/version/VERSION index ece450e8fe9b..734375f897d0 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.19.3-dev +1.20.0-dev From 176ea31ed95c7805fd88011f98165a8f929f5022 Mon Sep 17 00:00:00 2001 From: Deniz Onur Duzgun <59659739+dduzgun-security@users.noreply.github.com> Date: Tue, 17 Sep 2024 10:49:01 -0400 Subject: [PATCH 03/97] ci: update the security-scanner gha token (#21748) --- .github/workflows/security-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index 0a048c644779..ad851dca1e0c 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -59,7 +59,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: repository: hashicorp/security-scanner - token: ${{ secrets.HASHIBOT_PRODSEC_GITHUB_TOKEN }} + token: ${{ secrets.PRODSEC_SCANNER_READ_ONLY }} path: security-scanner ref: main From 29c2cbcbe229bc1b6c6eab6b1ad9cd617f4469ec Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Tue, 17 Sep 2024 11:27:35 -0400 Subject: [PATCH 04/97] ci: fix versions.hcl parsing by removing extraneous comma (#21752) Commas are not expected after HCL blocks. This is causing parsing in BPA to fail and may interfere w/ other release-related workflows. --- .release/versions.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.release/versions.hcl b/.release/versions.hcl index 7c5b4ee7eb28..7f4e5b953827 100644 --- a/.release/versions.hcl +++ b/.release/versions.hcl @@ -8,7 +8,7 @@ schema = 1 active_versions { version "1.20" { ce_active = true - }, + } version "1.19" { ce_active = true } From fe820d561a04b049b804d9c7424bd561b20eb01d Mon Sep 17 00:00:00 2001 From: Dhia Ayachi Date: Tue, 17 Sep 2024 11:48:02 -0400 Subject: [PATCH 05/97] Upgrade ubi image to 9.4 (#21750) * upgrade go to 1.23.1, upgrade ubi image to 9.4 * add changelog * revert go version upgrade --- .changelog/21750.txt | 3 +++ Dockerfile | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .changelog/21750.txt diff --git a/.changelog/21750.txt b/.changelog/21750.txt new file mode 100644 index 000000000000..c30c08179b4b --- /dev/null +++ b/.changelog/21750.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +security: upgrade ubi base image to 9.4 +``` diff --git a/Dockerfile b/Dockerfile index 55e5972bd9e5..dc617c5e0492 100644 --- a/Dockerfile +++ b/Dockerfile @@ -203,7 +203,7 @@ CMD ["agent", "-dev", "-client", "0.0.0.0"] # Red Hat UBI-based image # This target is used to build a Consul image for use on OpenShift. -FROM registry.access.redhat.com/ubi9-minimal:9.3 as ubi +FROM registry.access.redhat.com/ubi9-minimal:9.4 as ubi ARG PRODUCT_VERSION ARG PRODUCT_REVISION From 1a0b1e045bcab4f9be339e504084b0f7049d66fe Mon Sep 17 00:00:00 2001 From: NicoletaPopoviciu <87660255+NicoletaPopoviciu@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:20:14 -0400 Subject: [PATCH 06/97] Update test-integrations.yml to capture latest versions of Nomad and Vault (#21749) * Update test-integrations.yml Update Vault/Nomad versions to ensure we're testing the latest versions . * Update test to test latest available CE versions --- .github/workflows/test-integrations.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-integrations.yml b/.github/workflows/test-integrations.yml index b62a4648293f..c83338ee0c9d 100644 --- a/.github/workflows/test-integrations.yml +++ b/.github/workflows/test-integrations.yml @@ -94,7 +94,7 @@ jobs: contents: read strategy: matrix: - nomad-version: ['v1.7.7', 'v1.6.10', 'v1.5.17'] + nomad-version: ['v1.8.3', 'v1.7.7', 'v1.6.10'] steps: - name: Checkout Nomad uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 @@ -177,7 +177,7 @@ jobs: contents: read strategy: matrix: - vault-version: ["1.16.2", "1.15.6", "1.14.10"] + vault-version: ["1.17.5", "1.16.3", "1.15.6"] env: VAULT_BINARY_VERSION: ${{ matrix.vault-version }} steps: From ac9e694b98c4ccef4f2e6fc8803dc598bfcf18c5 Mon Sep 17 00:00:00 2001 From: Nick Wales <588472+nickwales@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:36:27 -0500 Subject: [PATCH 07/97] Adds initial sg documentation for the health API (#21763) Adds initial sg documentation --- website/content/api-docs/health.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/content/api-docs/health.mdx b/website/content/api-docs/health.mdx index 405c97df1f1a..c6182f441b5d 100644 --- a/website/content/api-docs/health.mdx +++ b/website/content/api-docs/health.mdx @@ -273,6 +273,9 @@ The table below shows this endpoint's support for - `ns` `(string: "")` - Specifies the namespace of the service. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +- `sg` `(string: "")` - Specifies the sameness group the service is a member of to + facilitate requests to identical services in other peers or partitions. + ### Sample Request ```shell-session From 250b1dece52123b08a17a82ac695e787d0344c16 Mon Sep 17 00:00:00 2001 From: danielehc <40759828+danielehc@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:20:44 +0200 Subject: [PATCH 08/97] CE-654 - TLS Encryption docs + CE-713 - Gossip Encryption key rotation (#21509) * New proposed structure * Fix structure and add some content * Fix structure and add some content * Fix structure and add some content * Add content * Add content * mtls steps * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * Encryption docs structure change * spacing fixes * Replace * alignment * indent fixes * spacing * More Code tabs fixes * Structure chenges * Structure chenges * Extra content and CE-713 migration * Extra content * Extra content * Extra content * Apply suggestions from code review Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> * Apply suggestions from code review * Test CodeTabs * Test CodeTabs * Apply suggestions from code review Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> --------- Co-authored-by: boruszak Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> --- website/content/docs/security/encryption.mdx | 111 ---- .../docs/security/encryption/gossip.mdx | 302 ++++++++++ .../docs/security/encryption/index.mdx | 55 ++ .../content/docs/security/encryption/mtls.mdx | 553 ++++++++++++++++++ website/content/docs/security/index.mdx | 15 +- website/data/docs-nav-data.json | 31 +- 6 files changed, 943 insertions(+), 124 deletions(-) delete mode 100644 website/content/docs/security/encryption.mdx create mode 100644 website/content/docs/security/encryption/gossip.mdx create mode 100644 website/content/docs/security/encryption/index.mdx create mode 100644 website/content/docs/security/encryption/mtls.mdx diff --git a/website/content/docs/security/encryption.mdx b/website/content/docs/security/encryption.mdx deleted file mode 100644 index 6cbbf6b3219c..000000000000 --- a/website/content/docs/security/encryption.mdx +++ /dev/null @@ -1,111 +0,0 @@ ---- -layout: docs -page_title: Encryption Systems -description: >- - Consul supports encrypting all of its network traffic. Remote Process Calls (RPCs) between client and server agents can be encrypted with TLS and authenticated with certificates. Gossip communication between all agents can also be encrypted. ---- - -# Encryption - -The Consul agent supports encrypting all of its network traffic. The exact -method of encryption is described on the [encryption internals page](/consul/docs/security). -There are two separate encryption systems, one for gossip traffic and one for RPC. - -To configure the encryption systems on a new cluster, review this following tutorials to -[enable gossip encryption](/consul/tutorials/security/gossip-encryption-secure?utm_source=consul.io&utm_medium=docs) and -[TLS encryption for agent communication](/consul/tutorials/security/tls-encryption-secure?utm_source=docs). - -## Gossip Encryption - -Enabling gossip encryption only requires that you set an encryption key when -starting the Consul agent. The key can be set via the `encrypt` parameter. - -~> **WAN Joined Datacenters Note:** If using multiple WAN joined datacenters, be sure to use _the same encryption key_ in all datacenters. - -The key must be 32-bytes, Base64 encoded. As a convenience, Consul provides the -[`consul keygen`](/consul/commands/keygen) command to generate a -cryptographically suitable key: - -```shell-session -$ consul keygen -pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s= -``` - -With that key, you can enable encryption on the agent. If encryption is enabled, -the output of [`consul agent`](/consul/commands/agent) will include "Encrypt: true": - -```shell-session -$ cat encrypt.json -{"encrypt": "pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s="} - -$ consul agent -data-dir=/tmp/consul -config-file=encrypt.json -==> WARNING: LAN keyring exists but -encrypt given, using keyring -==> WARNING: WAN keyring exists but -encrypt given, using keyring -==> Starting Consul agent... -==> Starting Consul agent RPC... -==> Consul agent running! - Node name: 'Armons-MacBook-Air.local' - Datacenter: 'dc1' - Server: false (bootstrap: false) - Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400) - Cluster Addr: 10.1.10.12 (LAN: 8301, WAN: 8302) - Gossip encrypt: true, RPC-TLS: false, TLS-Incoming: false -... -``` - -All nodes within a Consul cluster must share the same encryption key in -order to send and receive cluster information. - -## Configuring Gossip Encryption on an existing cluster - -As of version 0.8.4, Consul supports upshifting to encrypted gossip on a running cluster -through the following process. Review this [step-by-step tutorial](/consul/tutorials/security/gossip-encryption-secure?utm_source=consul.io&utm_medium=docs#enable-gossip-encryption-existing-cluster) -to encrypt gossip on an existing cluster. - -## RPC Encryption with TLS - -Consul supports using TLS to verify the authenticity of servers and clients. To enable this, -Consul requires that all clients and servers have key pairs that are generated by a single -Certificate Authority. This can be a private CA, used only internally. The -CA then signs keys for each of the agents, as in -[this tutorial on generating both a CA and signing keys](/consul/tutorials/security/tls-encryption-secure?utm_source=docs). - -~> Certificates need to be created with x509v3 extendedKeyUsage attributes for both clientAuth and serverAuth since Consul uses a single cert/key pair for both server and client communications. - -TLS can be used to verify the authenticity of the servers or verify the authenticity of clients. -These modes are controlled by the [`verify_outgoing`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_outgoing), -[`verify_server_hostname`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_server_hostname), -and [`verify_incoming`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_incoming) options, respectively. - -If [`verify_outgoing`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_outgoing) is set, agents verify the -authenticity of Consul for outgoing connections. Server nodes must present a certificate signed -by a common certificate authority present on all agents, set via the agent's -[`ca_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_ca_file) and [`ca_path`](/consul/docs/agent/config/config-files#tls_internal_rpc_ca_path) -options. All server nodes must have an appropriate key pair set using [`cert_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_cert_file) and [`key_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_key_file). - -If [`verify_server_hostname`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_server_hostname) is set, then -outgoing connections perform hostname verification. All servers must have a certificate -valid for `server..` or the client will reject the handshake. This is -a new configuration as of 0.5.1, and it is used to prevent a compromised client from being -able to restart in server mode and perform a MITM (Man-In-The-Middle) attack. New deployments should set this -to true, and generate the proper certificates, but this is defaulted to false to avoid breaking -existing deployments. - -If [`verify_incoming`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_incoming) is set, the servers verify the -authenticity of all incoming connections. All clients must have a valid key pair set using -[`cert_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_cert_file) and -[`key_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_key_file). Servers will -also disallow any non-TLS connections. To force clients to use TLS, -[`verify_outgoing`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_outgoing) must also be set. - -TLS is used to secure the RPC calls between agents, but gossip between nodes is done over UDP -and is secured using a symmetric key. See above for enabling gossip encryption. - -## Configuring TLS on an existing cluster - -As of version 0.8.4, Consul supports migrating to TLS-encrypted traffic on a running cluster -without downtime. This process assumes a starting point with no TLS settings configured and involves -an intermediate step in order to get to full TLS encryption. Review the -[Securing RPC Communication with TLS Encryption tutorial](/consul/tutorials/security/tls-encryption-secure?utm_source=docs) -for the step-by-step process to configure TLS on a new or existing cluster. Note the call outs there -for existing cluster configuration. diff --git a/website/content/docs/security/encryption/gossip.mdx b/website/content/docs/security/encryption/gossip.mdx new file mode 100644 index 000000000000..4a04e16bd7c9 --- /dev/null +++ b/website/content/docs/security/encryption/gossip.mdx @@ -0,0 +1,302 @@ +--- +layout: docs +page_title: Manage gossip encryption +description: >- + Consul supports encrypting all of its network traffic. Learn how to secure gossip communication between all agents by creating and rotating a symmetric key. +--- + +# Manage gossip encryption + +This topic describes the steps to enable gossip encryption on a Consul datacenter and rotate the gossip encryption key to maintain secure communication between agents. + +## Workflows + +We recommend enabling gossip encryption to all new deployed Consul datacenters. You can also update the agents in an existing datacenter to use gossip encryption. + +The workflow to enable gossip encryption changes depending on whether your datacenter has client agents running. + +To [enable gossip encryption on a new datacenter](#enable-gossip-encryption-on-a-new-datacenter): + +1. Use `consul keygen` to generate a new gossip encryption key. +1. Create a configuration file that sets the `encrypt` parameter to the newly generated key. +1. Distribute the configuration file to all agent nodes that are part of the datacenter. Then start the Consul agent on all the nodes. + +To [enable gossip encryption on an existing datacenter](#enable-gossip-encryption-on-an-existing-datacenter): + +1. Use `consul keygen` to generate a new gossip encryption key. +1. Create a configuration file that sets the `encrypt` parameter to the newly generated key and sets `encrypt_verify_incoming` and `encrypt_verify_outgoing` to `false`. +1. Distribute the configuration file to all agent nodes that are part of the datacenter. Then perform a rolling restart of all Consul agents. +1. Update the `encrypt_verify_outgoing` setting to `true` and perform a rolling restart of all Consul agents. +1. Update the `encrypt_verify_incoming` setting to `true` and perform a rolling restart of all Consul agents. + +If you have multiple datacenters joined in WAN federation, be sure to use _the same encryption key_ in all datacenters. + +## Enable gossip encryption on a new datacenter + +We recommend enabling gossip encryption on all new Consul datacenters. + +### Generate a gossip encryption key + +First, generate an encryption key on a Consul server. The Consul CLI includes a `consul keygen` command to generate a key. + +```shell-session +$ consul keygen +YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= +``` + +You can generate a new gossip key using any method that can create 32 random bytes encoded in base64. For example, you can use `openssl` or `dd` to create a key on Linux with one of the following commands: + +- `openssl rand -base64 32` +- `dd if=/dev/urandom bs=32 count=1 status=none | base64` + +### Add the key to the agent configuration + +Create a configuration that sets `encrypt` parameter to the newly generated key. You can edit the existing agent configuration, or you can add a file to the configuration directory. For more information, refer to [configuring Consul agents](/consul/docs/agent#configuring-consul-agents). + + + +```hcl +encrypt = "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +``` + +```json +{ + "encrypt": "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +} +``` + + + +### Add the key to all agent configurations + +Distribute the gossip key to all the agent nodes that need to be pert of the datacenter. Then start the Consul agent on all the nodes. + +When gossip encryption is properly configured, `Gossip Encryption: true` appears in the Consul logs at startup. + + + +```log +==> Starting Consul agent... + Version: '1.19.0' +Build Date: '2024-06-12 13:59:10 +0000 UTC' + Node ID: 'e74b1ade-e932-1707-cdf1-6579b8b2536c' + Node name: 'consul-server-0' +Datacenter: 'dc1' (Segment: '') +Server: true (Bootstrap: false) + Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: 8443, gRPC: -1, gRPC-TLS: 8503, DNS: 53) + Cluster Addr: 172.19.0.7 (LAN: 8301, WAN: 8302) + Gossip Encryption: true + Auto-Encrypt-TLS: true + ACL Enabled: true + Reporting Enabled: false +ACL Default Policy: deny + HTTPS TLS: Verify Incoming: false, Verify Outgoing: true, Min Version: TLSv1_2 + gRPC TLS: Verify Incoming: false, Min Version: TLSv1_2 + Internal RPC TLS: Verify Incoming: true, Verify Outgoing: true (Verify Hostname: true), Min Version: TLSv1_2 +## ... +``` + + + +## Enable gossip encryption on an existing datacenter + +You can also enable gossip encryption on existing Consul datacenters. + +### Generate a gossip encryption key + +First, generate an encryption key on a Consul server. The Consul CLI includes a `consul keygen` command to generate a key. + +```shell-session +$ consul keygen +YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= +``` + +### Add the key to the agent configuration + +Create a configuration that sets the `encrypt` parameter to the newly generated key and sets the `encrypt_verify_incoming` and `encrypt_verify_outgoing` parameters to `false`. You can edit the existing agent configuration, or you can add a file to the configuration directory. For more information, refer to [configuring Consul agents](/consul/docs/agent#configuring-consul-agents). + + + + + +```hcl +encrypt = "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +encrypt_verify_incoming = false +encrypt_verify_outgoing = false +``` + + + + + +```json +{ +"encrypt": "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=", +"encrypt_verify_incoming" : false, +"encrypt_verify_outgoing" : false +} +``` + + + + + +### Add the configuration to all agents + +Distribute the configuration to all the agent nodes that need to be part of the datacenter, and then initiate a rolling update that restarts each agent. + +You must restart all of the agents. The `consul reload` and `kill -HUP ` commands are not sufficient when changing the gossip configuration. + +### Update outgoing encryption + +The agents can decrypt gossip communication with the `encrypt` parameter set, but they are not able to send encrypted traffic. + +Update the `encrypt_verify_outgoing` setting to `true` and then perform another rolling update of all Consul agents. Complete the process on all the nodes before you begin [updates to incoming encryption](#update-the-incoming-encryption). + + + + + +```hcl +encrypt = "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +encrypt_verify_incoming = false +encrypt_verify_outgoing = true + ``` + + + + + +```json +{ +"encrypt": "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=", +"encrypt_verify_incoming": false, +"encrypt_verify_outgoing": true +} +``` + + + + + +### Update incoming encryption + +The agents can send encrypted gossip but still allow unencrypted incoming traffic. Update the `encrypt_verify_incoming` setting to `true` and then perform a final rolling update on all the agents. + + + + + +```hcl +encrypt = "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +encrypt_verify_incoming = true +encrypt_verify_outgoing = true +``` + + + + + +```json +{ +"encrypt": "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=", +"encrypt_verify_incoming": true, +"encrypt_verify_outgoing": true +} +``` + + + + + +## Rotate the gossip encryption key + +It is important to periodically rotate the gossip encryption key your Consul datacenter uses. + +The process of rotating the gossip encryption key is centralized so that you can perform it on a single datacenter node. + +The process to rotate a gossip encryption key consists of the following steps: + +1. Generate a new encryption key using the `consul keygen` command. +1. Install the new encryption key using the `consul keyring -install` command. +1. Verify the new key is installed in your Consul datacenter with the `consul keyring -list` command. +1. Instruct Consul to use the new key with the `consul keyring -use` command. +1. Remove the old key using the `consul keyring -remove` command. + +### Generate a new encryption key + +Generate a new key using `consul keygen`: + +```shell-session +$ consul keygen +FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= +``` + +### Add new key to the keyring + +Add your newly generated key to the keyring. + +```shell-session +$ consul keyring -install FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= +==> Installing new gossip encryption key... +``` + +### Verify that the new key is installed + +After you add the key to one of the Consul agents, Consul propagates it across the entire datacenter. You do not need to repeat the command on other agents. + +To ensure that the key has been propagated to all agents, list the installed encryption keys and verify that the number of agents that recognize the key is equal to the total number of agents in the datacenter. + +```shell-session +$ consul keyring -list +==> Gathering installed encryption keys... + +WAN: + FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= [1/1] + YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= [1/1] + +dc1 (LAN): + YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= [7/7] + FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= [7/7] +``` + +Confirm that the two keys are installed in the datacenter and recognized by all agents, including server agents. The server agents are listed in the `WAN` section. Do not proceed to the next step unless all agents have the new key. + +### Promote the new key to primary + +After all agents recognize the key, it is possible to promote it to be the new primary encryption key. + +```shell-session +$ consul keyring -use FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= +==> Changing primary gossip encryption key... +``` + +### Remove the old key from the keyring + +Unused keys in the keyring are a potential security risk to your Consul cluster. We recommended that you remove the former primary key from the keyring after a new key is installed. + +```shell-session +$ consul keyring -remove YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= +==> Removing gossip encryption key... +``` + +Verify that the keyring contains only one key. + +```shell-session +$ consul keyring -list +==> Gathering installed encryption keys... + +WAN: + FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= [1/1] + +dc1 (LAN): + FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= [7/7] +``` + +## Next steps + +Documentation for the commands used in this topic is available at [Consul agent configuration - Encryption Parameters](/consul/docs/agent/config/config-files#encryption-parameters). You can find more information over the gossip protocol used by Consul at [Gossip Protocol](/consul/docs/architecture/gossip). + +After you enable gossip encryption, you can continue to process to secure your Consul datacenter by enabling mutual TLS encryption. For more information, refer to [Mutual TLS (mTLS) Encryption](/consul/docs/security/encryption/mtls). + +To learn how to automate gossip key rotation using HashiCorp Vault and consul-template, refer to the [Automatically Rotate Gossip Encryption Keys Secured in Vault tutorial](/consul/tutorials/operate-consul/vault-kv-consul-secure-gossip). \ No newline at end of file diff --git a/website/content/docs/security/encryption/index.mdx b/website/content/docs/security/encryption/index.mdx new file mode 100644 index 000000000000..b5324ef63f24 --- /dev/null +++ b/website/content/docs/security/encryption/index.mdx @@ -0,0 +1,55 @@ +--- +layout: docs +page_title: Encrypted communication between Consul agents +description: >- + Consul supports encrypting all of its network traffic. Remote Procedure Calls (RPCs) between client and server agents can be encrypted with TLS and authenticated with certificates. Gossip communication between all agents can also be encrypted. +--- + +# Encrypted communication between Consul agents + +This topic provides an overview of the two distinct encryption systems available in Consul. [Gossip encryption](/consul/docs/security/encryption#gossip-encryption) and [Mutual TLS encryption](/consul/docs/security/encryption#mutual-tls-mtls-encryption) are the foundations of a secure Consul datacenter. + +The guidelines in the [Consul security model](/consul/docs/security/security-models/core) for operating a secure Consul deployment recommends using both encryption systems. + +## Gossip Encryption + +Consul uses a [gossip protocol](/consul/docs/architecture/gossip) to perform the following cluster operations: + +- Identify datacenter members. +- Quickly detect failed members and notify the rest of the cluster. +- Broadcast events and queries that can trigger custom workflows. + +The gossip protocol, as well as its membership management and message broadcasting features, use the [Serf library](https://www.serf.io/). + +In a default Consul configuration, the gossip protocol uses [port `8301`](/consul/docs/install/ports#lan-serf) for LAN communications and [port `8302`](/consul/docs/install/ports#lan-serf) for WAN communications between federated datacenters. Enabling gossip encryption on a Consul datacenter is required to secure traffic on these two ports. + +Gossip encryption is symmetric and based on a single key that is shared across all members of the datacenter. You can configure gossip encryption in Consul using the following parameters: + +- [`encrypt`](/consul/docs/agent/config/config-files#encrypt). +- [`encrypt_verify_incoming`](/consul/docs/agent/config/config-files#encrypt_verify_incoming). Only used when upshifting from unencrypted to encrypted gossip on a running cluster. +- [`encrypt_verify_outgoing`](/consul/docs/agent/config/config-files#encrypt_verify_outgoing). Only used when upshifting from unencrypted to encrypted gossip on a running cluster. + +To learn more about enabling gossip encryption on your Consul datacenter and rotating gossip keys, refer to [manage gossip encryption](/consul/docs/security/encryption/gossip). + +## Mutual TLS (mTLS) Encryption + +Consul uses several communication protocols over different ports that you can secure using mTLS: + +- A [consensus protocol](/consul/docs/architecture/consensus) provides data consistency between Consul servers. It typically uses [port `8300`](/consul/docs/install/ports#server-rpc). +- Remote Procedure Calls (RPC) forward requests from client agents to server agents. They use the same port the consensus protocol uses. +- An HTTP or HTTPS interface permits client communication with the Consul API, CLI, and UI. It typically uses [port `8500`](/consul/docs/install/ports#http) and [port `8501`](/consul/docs/install/ports#https). +- A gRPC interface receives incoming traffic from the gateways and Envoy proxies registered to the agent node. It typically uses [port `8502`](/consul/docs/install/ports#client-grpc) and [port `8503`](/consul/docs/install/ports#client-grpc-tls). + +Consul uses mTLS to verify the authenticity of server and client agents. It requires that all clients and servers have key pairs that are generated by a single Certification Authority (CA). We recommend using a private CA that is not shared with other applications. + +You can configure mTLS in Consul using the [`tls` stanza in agent configuration files](/consul/docs/agent/config/config-files#tls-1). + +You can configure mTLS encryption for each protocol separately using the following parameters in the agent configuration file: + +- [`tls.defaults`](/consul/docs/agent/config/config-files#tls_defaults) provides default settings that Consul applies to every interface unless explicitly overridden by protocol-specific configurations. +- [`tls.internal_rpc`](/consul/docs/agent/config/config-files#tls_internal_rpc) provides settings for the internal server RPC interface. +- [`tls.https`](/consul/docs/agent/config/config-files#tls_https) provides settings for the HTTP/HTTPS interface. +- [`tls.grpc`](/consul/docs/agent/config/config-files#tls_grpc) provides settings for the gRPC/xDS interface. + +To learn more about enabling mTLS on your Consul datacenter, refer to [Manage mTLS encryption](/consul/docs/security/encryption/mTLS). + diff --git a/website/content/docs/security/encryption/mtls.mdx b/website/content/docs/security/encryption/mtls.mdx new file mode 100644 index 000000000000..5017c7b509f3 --- /dev/null +++ b/website/content/docs/security/encryption/mtls.mdx @@ -0,0 +1,553 @@ +--- +layout: docs +page_title: Manage agent mTLS encryption +description: >- + Consul supports encrypting all of its network traffic. Learn how to encrypt and authenticate Remote Process Calls (RPCs) between client and server agents with TLS certificates. +--- + +# Manage agent mTLS encryption + +This topic describes mutual TLS (mTLS) encryption between agents in a Consul datacenter. + +This mTLS encryption is distinct from Consul service mesh mTLS encryption. To learn about encrypted mTLS communication between services, refer to [service mesh certificate authority](/consul/docs/connect/ca). + +## Benefits of TLS encryption + +Consul supports TLS certificates that verify the authenticity of servers and clients to secure `RCP`, `gRPC`, and `HTTP` traffic. + +Implementing TLS encryption in Consul datacenters improves your deployment's security in the following ways: + +- **Encrypt data in transit:** TLS encrypts data transmitted between Consul datacenter nodes and user interfaces such as the UI or CLI to ensure that sensitive information is not exposed to unauthorized parties. + +- **Agent authentication:** TLS ensures that only verified parties can communicate with each other using certificates. This security measure prevents unauthorized nodes, services, and users from interacting with your Consul datacenter. + +- **Prevent man-in-the-middle (MITM) attacks:** Without TLS, attackers may intercept and change communications within your Consul deployments. TLS mitigates this risk by encrypting data and verifying the identity of the communication participants. + +- **Comply with security regulations and standards:** Compliance frameworks and regulations like PCI-DSS and HIPAA mandate the encryption of data in transit, which makes TLS a requirement for Consul deployments in regulated environments. + +Mutual TLS (mTLS) requires that all clients and servers have key pairs that are generated by a single Certification Authority (CA). We recommend using a private CA that is not shared with other applications. + +The following parameters in agent configuration files define the agent verification behavior: + +- [`tls.defaults.verify_incoming`](/consul/docs/agent/config/config-files#tls_defaults_verify_incoming) +- [`tls.defaults.verify_outgoing`](/consul/docs/agent/config/config-files#tls_defaults_verify_outgoing) +- [`tls.defaults.verify_server_hostname`](/consul/docs/agent/config/config-files#tls_default_verify_server_hostname) + +## Workflow + +The process to enable TLS encryption in Consul deployments consists of the following steps: + +1. [Initialize the built-in CA](/consul/docs/security/encryption/mtls#initialize-the-built-in-ca) used to sign all certificates. +1. [Create server certificates](/consul/docs/security/encryption/mtls#create-server-certificates) to secure Consul servers. +1. [Configure server agents](/consul/docs/security/encryption/mtls#configure-server-agents) for TLS encryption. +1. [Start server agents](/consul/docs/security/encryption/mtls#start-consul-servers). +1. [Configure Consul client agents](/consul/docs/security/encryption/mtls#configure-client-agents). +1. [Start client agents](/consul/docs/security/encryption/mtls#start-consul-clients). + +## Initialize the built-in CA + +The first step to configure mTLS for Consul is to initialize the certificate authority (CA) that signs the certificates. To prevent unauthorized datacenter access, Consul requires that all certificates are signed by the same CA. We recommend using a private CA because any certificate it signs will be allowed to communicate with the Consul datacenter. + +Consul supports a variety of tools for creating and managing your own CA, like the [PKI secrets engine in Vault](/vault/docs/secrets/pki) or the [Terraform TLS provider](https://registry.terraform.io/providers/hashicorp/tls/latest/docs). Consul also ships with built-in TLS tools to create and manage certificates. + +If you have the Consul binary installed on your path, you can create the CA and certificates, even before you start a Consul server agent. + +```shell-session +$ consul tls ca create -domain=consul +==> Saved consul-agent-ca.pem +==> Saved consul-agent-ca-key.pem +``` + +The command generates two files, `-agent-ca.pem` and `-agent-ca-key.pem`. In this example, the domain used to generate the certificates is the default one, `consul`. + +The CA certificate, `consul-agent-ca.pem`, contains the public key necessary to validate Consul certificates. You must distribute this certificate to every node where a Consul agent runs. + +The CA key, `consul-agent-ca-key.pem`, signs certificates for Consul nodes. You must keep this key private. Possession of this key allows anyone to run Consul as a trusted server or generate new valid certificates for the datacenter. Malicious actors may use this key to obtain access to all Consul data, including ACL tokens. + +## Create server certificates + +To authenticate Consul servers, servers are provided with a special certificate that lists `server..` in the `Common Name` and `Subject Alternative Name` fields. When you enable [`tls.defaults.verify_server_hostname`](/consul/docs/agent/config/config-files#tls_default_verify_server_hostname), only agents that provide this certificate are allowed to boot as a server. + +Without `tls.defaults.verify_server_hostname = true`, an attacker who compromises a Consul client agent can restart the agent as a server to get access to all the data in your datacenter. You must keep the server key private to protect your Consul data. + +The following example creates a server certificate for datacenter `dc1` in the `consul` domain. If your datacenter or domain is different, modify the command to use the appropriate flag values. + +```shell-session +$ consul tls cert create -server -dc=dc1 -domain=consul +==> WARNING: Server Certificates grants authority to become a + server and access all state in the cluster including root keys + and all ACL tokens. Do not distribute them to production hosts + that are not server nodes. Store them as securely as CA keys. +==> Using consul-agent-ca.pem and consul-agent-ca-key.pem +==> Saved dc1-server-consul-0.pem +==> Saved dc1-server-consul-0-key.pem +``` + +Repeat this process on the same node where you created the CA until the number of certificates is equal to the number of servers in the datacenter. You can run the command multiple times in a row, and it automatically increases the certificate and key numbers each time. + +### Federated Consul datacenter + +A federated Consul environment requires the server certificate to include the names of all Consul datacenters that are within the federated environment. + +Use the `-additional-dnsname` flag to provide an additional DNS names for Subject Alternative Names. `localhost` is always included. You can provide this flag multiple times in a single command. + +The following example creates a certificate for a federated environment containing two Consul datacenters named `dc1` and `dc2`. + +```shell-session +$ consul tls cert create -server -dc dc1 -domain=consul -additional-dnsname="server.dc2.consul" +==> WARNING: Server Certificates grants authority to become a + server and access all state in the cluster including root keys + and all ACL tokens. Do not distribute them to production hosts + that are not server nodes. Store them as securely as CA keys. +==> Using consul-agent-ca.pem and consul-agent-ca-key.pem +==> Saved dc1-server-consul-0.pem +==> Saved dc1-server-consul-0-key.pem +``` + +## Configure server agents + +After you generate the server certificates, distribute them to the Consul servers and modify the agent configuration file to include their local location. + +Copy the following files to each Consul server: + +- `consul-agent-ca.pem`: CA public certificate. +- `dc1-server-consul-0.pem`: Consul server node public certificate for first server node in the `dc1` datacenter in the `consul` domain. +- `dc1-server-consul-0-key.pem`: Consul server node private key for first server node in the `dc1` datacenter in the `consul` domain. + +There are two methods for configuring Consul server agents depending on the way you want to distribute certificates to the client agents: + +- The _auto encryption method_ uses the Consul Connect CA to generate client certificates and then automatically distributes them to all Consul clients. +- The _operator method_ requires you to manually generate client certificates and distribute them to each client agent individually. + +We recommend using the auto-encryption method with the built-in CA because Consul can then automatically rotate certificates without requiring operator intervention. + +Use the operator method if you need to use a third-party CA or need more fine-grained control over certificate management. + + + + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 +} +tls { + defaults { + ca_file = "consul-agent-ca.pem" + cert_file = "dc1-server-consul-0.pem" + key_file = "dc1-server-consul-0-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +auto_encrypt { + allow_tls = true +} +``` + +```json +{ + "addresses": { + "https" : "0.0.0.0" + }, + "ports": { + "https" : 8501 + }, + "tls" : { + "defaults": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "dc1-server-consul-0.pem", + "key_file": "dc1-server-consul-0-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + }, + "auto_encrypt" : { + "allow_tls" : true + } +} +``` + + + + + + + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 +} +tls { + defaults { + ca_file = "consul-agent-ca.pem" + cert_file = "dc1-server-consul-0.pem" + key_file = "dc1-server-consul-0-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0" + }, + "ports": { + "https": 8501 + }, + "tls": { + "defaults": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "dc1-server-consul-0.pem", + "key_file": "dc1-server-consul-0-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + } +} +``` + + + + + + + +Consul does not enable TLS for HTTP unless the `https` port is assigned a port number greater than `0`. We recommend using `8501`, the default number for the `https` port, because this default is designed to work automatically with other tools. + +## Start Consul servers + +After you configure your servers, start the Consul process. + +```shell-session +$ systemctl start consul +``` + +Your Consul servers can now communicate with TLS encryption for RPC and consensus. + +## Configure client agents + +Next, configure your client agents with the same method you used to [configure the server agent](#distribute-the-server-certificates) + + + + +The only file you need on the local disk to configure the Consul client agents using auto-encryption is the CA certificate `consul-agent-ca-.pem`. + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 +} +tls { + defaults { + ca_file = "consul-agent-ca.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +auto_encrypt = { + tls = true +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0" + }, + "ports": { + "https": 8501 + }, + "tls": { + "defaults": { + "ca_file": "consul-agent-ca.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + }, + "auto_encrypt" : { + "tls" : true + } +} +``` + + + + + + + +On the node where you created the CA and server certificates, generate a client certificate with `consul tls cert create -client` command. + +```shell-session +$ consul tls cert create -client -dc=dc1 -domain=consul +==> Using consul-agent-ca.pem and consul-agent-ca-key.pem +==> Saved dc1-client-consul-0.pem +==> Saved dc1-client-consul-0-key.pem +``` + +The client certificate is also signed by the same CA used for the server certificates, but it does not contain `server..` in the `Common Name` and in the `Subject Alternative Name`. Because `verify_server_hostname` is enabled, a compromised client cannot use this certificate to start as a server and access datacenter data. + +Distribute the client certificates and the CA certificate `consul-agent-ca.pem` to every Consul client in the datacenter. Then add them to the client agent configuration. + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 +} +tls { + defaults { + ca_file = "consul-agent-ca.pem" + cert_file = "dc1-client-consul-0.pem" + key_file = "dc1-client-consul-0-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0" + }, + "ports": { + "https": 8501 + }, + "tls": { + "defaults": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "dc1-client-consul-0.pem", + "key_file": "dc1-client-consul-0-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + } +} +``` + + + + + + + +## Start Consul clients + +After you configure each client, start the Consul process on the node. + +```shell-session +$ systemctl start consul +``` + +Your client agents now communicate using mutual TLS encryption. + +## Rotate TLS certificates + +To maintain the security offered by TLS encryption, we recommend that you rotate TLS certificates often. + +TLS certificates are part of [Consul's reloadable configuration](/consul/docs/agent/config#reloadable-configuration), so you do not need to restart the Consul agents when you renew certificates. As a result, there is no risk of downtime. + +To rotate certificates for Consul server agents complete the following steps: +1. [Generate new certificates for all server agents](/consul/docs/security/encryption/mtls#create-server-certificates) to replace the old ones. +1. Distribute the new certificates to the server nodes. +1. Reload Consul configuration on each server with the `consul reload` command. + +To rotate certificates for Consul client agents complete the following steps: + + + + +When using the auto-encryption method, Consul automatically rotates the client certificates without operator intervention. + + + + + +1. [Generate new certificates for all client agents](/consul/docs/security/encryption/mtls#configure-client-agents) to replace the old ones. +1. Distribute the new certificates to the client nodes. +1. Reload Consul configuration on all clients with `consul reload` command. + + + + + +## API, CLI, and UI interactions + +The configuration snippets provided in this page are valid to configure complete mTLS for your Consul datacenter. This means that all interfaces require the client to provide a valid certificate in order to communicate with the Consul agent. This is valid for all requests, API, CLI, and UI. + +Since Consul v1.12 it is possible to have different settings for: + + - the HTTP protocol, used for the Consul's REST API, the CLI integration, and the UI + - the RPC protocol, used for internal communications between the Consul agents. + +### Interact with Consul without a client certificate + +If you want to avoid the need to present a valid client certificate every time you interact with Consul using the HTTP API, CLI, or UI, configure Consul to trust all incoming HTTPS connections by setting `tls.https.verify_incoming` to `false`. RPC communications are still mTLS encrypted. + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 + http = -1 +} +tls { + https { + ca_file = "/etc/consul.d/consul-agent-ca.pem" + cert_file = "/etc/consul.d/consul-agent.pem" + key_file = "/etc/consul.d/consul-agent-key.pem" + verify_incoming = false + verify_outgoing = true + } + internal_rpc { + ca_file = "/etc/consul.d/consul-agent-ca.pem" + cert_file = "/etc/consul.d/consul-agent.pem" + key_file = "/etc/consul.d/consul-agent-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0", + "http": "127.0.0.1", + }, + "ports": { + "https": 8501, + "http": 8500 + }, + "tls": { + "https": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "consul-agent.pem", + "key_file": "consul-agent-key.pem", + "verify_incoming": false, + "verify_outgoing": true + }, + "internal_rpc": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "consul-agent.pem", + "key_file": "consul-agent-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + } +} +``` + + + + +### Use HTTP for local client interaction + +If you want to avoid the need to present a valid client certificate or to use the CA certificate every time you interact with the local Consul agent, configure Consul to keep the HTTP listener active on the `localhost` interface only and set `tls.https.verify_incoming` to `false`. External requests to the API or UI are still protected by TLS encryption, but requests that originate locally do not need to present a client certificate. RPC communications are still mTLS encrypted. + + + +```hcl +addresses = { + https = "0.0.0.0" + http = "127.0.0.1" +} +ports { + https = 8501 + http = 8500 +} +tls { + https { + ca_file = "/etc/consul.d/consul-agent-ca.pem" + cert_file = "/etc/consul.d/consul-agent.pem" + key_file = "/etc/consul.d/consul-agent-key.pem" + verify_incoming = false + verify_outgoing = true + } + internal_rpc { + ca_file = "/etc/consul.d/consul-agent-ca.pem" + cert_file = "/etc/consul.d/consul-agent.pem" + key_file = "/etc/consul.d/consul-agent-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0", + "http": "127.0.0.1", + }, + "ports": { + "https": 8501, + "http": 8500 + }, + "tls": { + "https": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "consul-agent.pem", + "key_file": "consul-agent-key.pem", + "verify_incoming": false, + "verify_outgoing": true + }, + "internal_rpc": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "consul-agent.pem", + "key_file": "consul-agent-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + } +} +``` + + + +## Next steps + +Your agents are now configured with mTLS for encrypted communication. With the auto encryption method, your +client certificates are managed by the server. With the operator method, you distributed all the certificates manually, but have a more flexible configuration. + +Documentation for the commands used in this topic is available at [Consul agent configuration - TLS configuration reference](/consul/docs/agent/config/config-files#tls-configuration-reference) and the [`consul tls` CLI command reference](/consul/commands/tls). + +To learn how to automate TLS certificate generation and rotation, refer to the [Generate mTLS Certificates for Consul with Vault](/consul/tutorials/operate-consul/vault-pki-consul-secure-tls) tutorial. + +To continue securing your Consul deployment, add [gossip encryption](/consul/docs/security/encryption/gossip) and enable [Access Control Lists (ACLs)](/consul/docs/security/acl) with the default deny policy. diff --git a/website/content/docs/security/index.mdx b/website/content/docs/security/index.mdx index 0ec501aabf29..1f89ad104d23 100644 --- a/website/content/docs/security/index.mdx +++ b/website/content/docs/security/index.mdx @@ -5,11 +5,15 @@ description: >- Security requirements and recommendations for Consul vary depending on workloads and environments. Learn how ACLs and encryption can protect access to and communication within your datacenter. --- +# Consul security + +This topic describes the security requirements and recommendations for a Consul deployment. + ## Security Models Requirements and recommendations for operating a secure Consul deployment may vary drastically depending on your intended workloads, operating system, and environment. You can find detailed information about the various personas, -recommendations, requirements, and threats [here](/consul/docs/security/security-models). +recommendations, requirements, and threats in the [Security Models](/consul/docs/security/security-models) section. ## ACLs @@ -18,6 +22,9 @@ to data and APIs. ## Encryption -The Consul agent supports encrypting all of its network traffic. The exact method of encryption is described on the -[encryption security page](/consul/docs/security/encryption). There are two separate encryption systems, one for gossip -traffic and one for HTTP + RPC. +The Consul agent supports encryption for all of its network traffic. There are two separate encryption systems: + +- A gossip encryption system +- An mTLS encryption system for HTTP and RPC + +For more information about these two different encryption systems, as well as configuration guidance, refer to [Consul encryption](/consul/docs/security/encryption). diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 8af621f8d344..37a6ff0d8dc3 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -1078,6 +1078,23 @@ "title": "Overview", "path": "security" }, + { + "title": "Security Models", + "routes": [ + { + "title": "Overview", + "path": "security/security-models" + }, + { + "title": "Core", + "path": "security/security-models/core" + }, + { + "title": "Network Infrastructure Automation", + "path": "security/security-models/nia" + } + ] + }, { "title": "Access Control (ACLs)", "routes": [ @@ -1188,22 +1205,18 @@ }, { "title": "Encryption", - "path": "security/encryption" - }, - { - "title": "Security Models", "routes": [ { "title": "Overview", - "path": "security/security-models" + "path": "security/encryption" }, { - "title": "Core", - "path": "security/security-models/core" + "title": "Gossip encryption", + "path": "security/encryption/gossip" }, { - "title": "Network Infrastructure Automation", - "path": "security/security-models/nia" + "title": "mTLS", + "path": "security/encryption/mtls" } ] } From 2d19cd58107f57accd06a58f0bb619cfcf195155 Mon Sep 17 00:00:00 2001 From: John Maguire Date: Thu, 19 Sep 2024 14:09:42 -0400 Subject: [PATCH 09/97] fix spacing of bash scripts (#21760) * fix spacing of bash scripts * shellcheck all the things * cat filename rather than concatenating pr number --- build-support/scripts/gen-changelog.sh | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/build-support/scripts/gen-changelog.sh b/build-support/scripts/gen-changelog.sh index 0e2835e95e5c..3690f24e9ba6 100755 --- a/build-support/scripts/gen-changelog.sh +++ b/build-support/scripts/gen-changelog.sh @@ -6,23 +6,28 @@ set -eo pipefail pr_number=$(gh pr list -H "$(git rev-parse --abbrev-ref HEAD)" -q ".[0].number" --json "number") +if [ -z "$pr_number" ]; then + echo "Error: Could not find PR number." + exit 1 +fi + # check if this changelog is referencing an enterprise change curdir=$(pwd) -filename = ".changelog/$pr_number.txt" +filename=".changelog/$pr_number.txt" if [[ ! $curdir == *"enterprise"* ]]; then - is_enterprise = "n" - read -p "Is this an enterprise PR? (y/n): " is_enterprise + is_enterprise="n" + read -rp "Is this an enterprise PR? (y/n): " is_enterprise if [[ $is_enterprise == "y" ]]; then - filename = ".changelog/_$pr_number.txt" + filename=".changelog/_$pr_number.txt" fi else - filename = ".changelog/_$pr_number.txt" + filename=".changelog/_$pr_number.txt" fi # create a new changelog file -touch $filename +touch "$filename" echo "Created a new changelog file for PR $pr_number." @@ -35,7 +40,7 @@ echo "4. deprecation" echo "5. bug" if [ -z "$1" ]; then - read -p "Enter your choice: " choice + read -rp "Enter your choice: " choice else choice=$1 fi @@ -66,8 +71,10 @@ esac msg="" -read -ep $'Please enter the changelog message:\n' msg +read -erp $'Please enter the changelog message:\n' msg echo -e "\`\`\`release-note:$type\n$msg\n\`\`\`" >>"$filename" -cat .changelog/$pr_number.txt +echo -e "\nChangelog added to $filename. Contents:\n" + +cat "$filename" From dc0fa032e82a07a2b849b61816640c1f6f3dd1b0 Mon Sep 17 00:00:00 2001 From: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:58:56 -0500 Subject: [PATCH 10/97] Stage rc release (#21770) stage rc release --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d3f07d4361c..b13ac86b3bd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +## 1.20.0-rc1 (September 19, 2024) + +SECURITY: + +* Explicitly set 'Content-Type' header to mitigate XSS vulnerability. [[GH-21704](https://github.com/hashicorp/consul/issues/21704)] +* Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. [[GH-21711](https://github.com/hashicorp/consul/issues/21711)] +* UI: Remove codemirror linting due to package dependency [[GH-21726](https://github.com/hashicorp/consul/issues/21726)] +* Upgrade Go to use 1.22.7. This addresses CVE +[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] +* Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs +[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and +[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] +* ui: Pin a newer resolution of Braces [[GH-21710](https://github.com/hashicorp/consul/issues/21710)] +* ui: Pin a newer resolution of Codemirror [[GH-21715](https://github.com/hashicorp/consul/issues/21715)] +* ui: Pin a newer resolution of Markdown-it [[GH-21717](https://github.com/hashicorp/consul/issues/21717)] +* ui: Pin a newer resolution of ansi-html [[GH-21735](https://github.com/hashicorp/consul/issues/21735)] + +FEATURES: + +* server: remove v2 tenancy, catalog, and mesh experiments [[GH-21592](https://github.com/hashicorp/consul/issues/21592)] + +IMPROVEMENTS: + +* security: upgrade ubi base image to 9.4 [[GH-21750](https://github.com/hashicorp/consul/issues/21750)] +* connect: Add Envoy 1.31 and 1.30 to support matrix [[GH-21616](https://github.com/hashicorp/consul/issues/21616)] + +BUG FIXES: + +* jwt-provider: change dns lookup family from the default of AUTO which would prefer ipv6 to ALL if LOGICAL_DNS is used or PREFER_IPV4 if STRICT_DNS is used to gracefully handle transitions to ipv6. [[GH-21703](https://github.com/hashicorp/consul/issues/21703)] + ## 1.19.2 (August 26, 2024) SECURITY: From c16d6831e8be2eb7ebf6ed8767ca90d2945b7df8 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Thu, 19 Sep 2024 16:55:45 -0400 Subject: [PATCH 11/97] chore: Update VERSION for next major release (#21756) This should be set to the next major version now that `release/1.20.x` has been created. --- version/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/VERSION b/version/VERSION index 734375f897d0..c6ba48dc6375 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.20.0-dev +1.21.0-dev From 39104a3ce17ceafc9afca562c5645fff51360a5c Mon Sep 17 00:00:00 2001 From: Dhia Ayachi Date: Fri, 20 Sep 2024 10:35:48 -0400 Subject: [PATCH 12/97] Update raft to 1.7.0 and add configuration for prevote (#21758) * update raft to 1.7.0 * add config to disable raft prevote * add changelog --- .changelog/21758.txt | 7 ++++++ agent/agent.go | 3 +++ agent/config/builder.go | 1 + agent/config/config.go | 4 +++- agent/config/default.go | 1 + agent/config/runtime.go | 6 ++++- agent/config/runtime_test.go | 1 + .../TestRuntimeConfig_Sanitize.golden | 2 ++ go.mod | 10 ++++---- go.sum | 23 ++++++++----------- test-integ/go.mod | 4 ++-- test-integ/go.sum | 12 +++++----- test/integration/consul-container/go.mod | 4 ++-- test/integration/consul-container/go.sum | 12 +++++----- 14 files changed, 54 insertions(+), 36 deletions(-) create mode 100644 .changelog/21758.txt diff --git a/.changelog/21758.txt b/.changelog/21758.txt new file mode 100644 index 000000000000..05f97e2c4bef --- /dev/null +++ b/.changelog/21758.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +raft: update raft library to 1.7.0 which include pre-vote extension +``` + +```release-note:enhancement +raft: add a configuration `raft_prevote_disabled` to allow disabling raft prevote +``` diff --git a/agent/agent.go b/agent/agent.go index a509ea2b3445..c5fb3cc886c0 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -1434,6 +1434,9 @@ func newConsulConfig(runtimeCfg *config.RuntimeConfig, logger hclog.Logger) (*co cfg.GRPCTLSPort = runtimeCfg.GRPCTLSPort cfg.Segment = runtimeCfg.SegmentName + + cfg.RaftConfig.PreVoteDisabled = runtimeCfg.RaftPreVoteDisabled + if len(runtimeCfg.Segments) > 0 { segments, err := segmentConfig(runtimeCfg) if err != nil { diff --git a/agent/config/builder.go b/agent/config/builder.go index f8d0df7b5c93..5e8b5c215f6d 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -1073,6 +1073,7 @@ func (b *builder) build() (rt RuntimeConfig, err error) { RaftSnapshotThreshold: intVal(c.RaftSnapshotThreshold), RaftSnapshotInterval: b.durationVal("raft_snapshot_interval", c.RaftSnapshotInterval), RaftTrailingLogs: intVal(c.RaftTrailingLogs), + RaftPreVoteDisabled: boolVal(c.RaftPreVoteDisabled), RaftLogStoreConfig: b.raftLogStoreConfigVal(&c.RaftLogStore), ReconnectTimeoutLAN: b.durationVal("reconnect_timeout", c.ReconnectTimeoutLAN), ReconnectTimeoutWAN: b.durationVal("reconnect_timeout_wan", c.ReconnectTimeoutWAN), diff --git a/agent/config/config.go b/agent/config/config.go index 3201f790a752..4a93c2702021 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -8,9 +8,10 @@ import ( "fmt" "time" - "github.com/hashicorp/hcl" "github.com/mitchellh/mapstructure" + "github.com/hashicorp/hcl" + "github.com/hashicorp/consul/lib/decode" ) @@ -214,6 +215,7 @@ type Config struct { RaftSnapshotThreshold *int `mapstructure:"raft_snapshot_threshold" json:"raft_snapshot_threshold,omitempty"` RaftSnapshotInterval *string `mapstructure:"raft_snapshot_interval" json:"raft_snapshot_interval,omitempty"` RaftTrailingLogs *int `mapstructure:"raft_trailing_logs" json:"raft_trailing_logs,omitempty"` + RaftPreVoteDisabled *bool `mapstructure:"raft_prevote_disabled" json:"raft_prevote_disabled,omitempty"` ReconnectTimeoutLAN *string `mapstructure:"reconnect_timeout" json:"reconnect_timeout,omitempty"` ReconnectTimeoutWAN *string `mapstructure:"reconnect_timeout_wan" json:"reconnect_timeout_wan,omitempty"` RejoinAfterLeave *bool `mapstructure:"rejoin_after_leave" json:"rejoin_after_leave,omitempty"` diff --git a/agent/config/default.go b/agent/config/default.go index f07a8bdf46dc..1b98056aa110 100644 --- a/agent/config/default.go +++ b/agent/config/default.go @@ -146,6 +146,7 @@ func DefaultSource() Source { raft_snapshot_threshold = ` + strconv.Itoa(int(cfg.RaftConfig.SnapshotThreshold)) + ` raft_snapshot_interval = "` + cfg.RaftConfig.SnapshotInterval.String() + `" raft_trailing_logs = ` + strconv.Itoa(int(cfg.RaftConfig.TrailingLogs)) + ` + raft_prevote_disabled = false raft_logstore { wal { segment_size_mb = 64 diff --git a/agent/config/runtime.go b/agent/config/runtime.go index 2ac7ea19d9f1..e31047354dda 100644 --- a/agent/config/runtime.go +++ b/agent/config/runtime.go @@ -10,9 +10,10 @@ import ( "strings" "time" - "github.com/hashicorp/go-uuid" "golang.org/x/time/rate" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/consul" consulrate "github.com/hashicorp/consul/agent/consul/rate" @@ -1004,6 +1005,9 @@ type RuntimeConfig struct { // hcl: raft_trailing_logs = int RaftTrailingLogs int + // hcl: raft_prevote_disabled = bool + RaftPreVoteDisabled bool + RaftLogStoreConfig consul.RaftLogStoreConfig // ReconnectTimeoutLAN specifies the amount of time to wait to reconnect with diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index a36d5f67dad9..549429bf8682 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -6594,6 +6594,7 @@ func TestLoad_FullConfig(t *testing.T) { RaftSnapshotThreshold: 16384, RaftSnapshotInterval: 30 * time.Second, RaftTrailingLogs: 83749, + RaftPreVoteDisabled: false, ReconnectTimeoutLAN: 23739 * time.Second, ReconnectTimeoutWAN: 26694 * time.Second, RequestLimitsMode: consulrate.ModePermissive, diff --git a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden index 5ead1e2f764c..53e533b24620 100644 --- a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden +++ b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden @@ -71,6 +71,7 @@ "AutopilotDisableUpgradeMigration": false, "AutopilotLastContactThreshold": "0s", "AutopilotMaxTrailingLogs": 0, + "AutopilotMinQuorum": 0, "AutopilotRedundancyZoneTag": "", "AutopilotServerStabilizationTime": "0s", @@ -299,6 +300,7 @@ "RaftSnapshotInterval": "0s", "RaftSnapshotThreshold": 0, "RaftTrailingLogs": 0, + "RaftPreVoteDisabled": false, "ReadReplica": false, "ReconnectTimeoutLAN": "0s", "ReconnectTimeoutWAN": "0s", diff --git a/go.mod b/go.mod index debde423e654..2cdc8bbaab6b 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/hashicorp/hcp-sdk-go v0.80.0 github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 github.com/hashicorp/memberlist v0.5.0 - github.com/hashicorp/raft v1.5.0 + github.com/hashicorp/raft v1.7.0 github.com/hashicorp/raft-autopilot v0.1.6 github.com/hashicorp/raft-boltdb/v2 v2.2.2 github.com/hashicorp/raft-wal v0.4.1 @@ -118,7 +118,7 @@ require ( golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 golang.org/x/net v0.24.0 golang.org/x/oauth2 v0.15.0 - golang.org/x/sync v0.3.0 + golang.org/x/sync v0.4.0 golang.org/x/sys v0.20.0 golang.org/x/time v0.3.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 @@ -201,7 +201,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect - github.com/hashicorp/go-msgpack/v2 v2.0.0 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.0 // indirect @@ -263,10 +263,10 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel/trace v1.17.0 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.12.0 // indirect + golang.org/x/mod v0.13.0 // indirect golang.org/x/term v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect + golang.org/x/tools v0.14.0 // indirect google.golang.org/api v0.126.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect diff --git a/go.sum b/go.sum index 89ac14fdd68e..fd2246257fe2 100644 --- a/go.sum +++ b/go.sum @@ -426,7 +426,6 @@ github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrj github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -441,8 +440,8 @@ github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYi github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack/v2 v2.0.0 h1:c1fiLq1LNghmLOry1ipGhvLDi+/zEoaEP2JrE1oFJ9s= -github.com/hashicorp/go-msgpack/v2 v2.0.0/go.mod h1:JIxYkkFJRDDRSoWQBSh7s9QAVThq+82iWmUpmE4jKak= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -509,8 +508,8 @@ github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0/go.mod h1:6pdNz0vo0mF0GvhwDG56 github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= github.com/hashicorp/raft v1.3.11/go.mod h1:J8naEwc6XaaCfts7+28whSeRvCqTd6e20BlCU3LtEO4= -github.com/hashicorp/raft v1.5.0 h1:uNs9EfJ4FwiArZRxxfd/dQ5d33nV31/CdCHArH89hT8= -github.com/hashicorp/raft v1.5.0/go.mod h1:pKHB2mf/Y25u3AHNSXVRv+yT+WAnmeTX0BwVppVQV+M= +github.com/hashicorp/raft v1.7.0 h1:4u24Qn6lQ6uwziM++UgsyiT64Q8GyRn43CV41qPiz1o= +github.com/hashicorp/raft v1.7.0/go.mod h1:N1sKh6Vn47mrWvEArQgILTyng8GoDRNYlgKyK7PMjs0= github.com/hashicorp/raft-autopilot v0.1.6 h1:C1q3RNF2FfXNZfHWbvVAu0QixaQK8K5pX4O5lh+9z4I= github.com/hashicorp/raft-autopilot v0.1.6/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= @@ -823,7 +822,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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.2/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/tencentcloud/tencentcloud-sdk-go v1.0.162 h1:8fDzz4GuVg4skjY2B0nMN7h6uN61EDVkuLyI2+qGHhI= @@ -963,8 +961,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.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.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/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1047,8 +1045,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1164,7 +1162,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1217,8 +1214,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/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.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +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/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= diff --git a/test-integ/go.mod b/test-integ/go.mod index 7a91a5a20e5c..d6293c4744d8 100644 --- a/test-integ/go.mod +++ b/test-integ/go.mod @@ -101,10 +101,10 @@ require ( github.com/zclconf/go-cty v1.12.1 // indirect golang.org/x/crypto v0.22.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect - golang.org/x/mod v0.12.0 // indirect + golang.org/x/mod v0.13.0 // indirect golang.org/x/sys v0.20.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect + golang.org/x/tools v0.14.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/test-integ/go.sum b/test-integ/go.sum index a7b09dfb8318..4e4c0e2d5eb1 100644 --- a/test-integ/go.sum +++ b/test-integ/go.sum @@ -319,8 +319,8 @@ golang.org/x/mod v0.3.0/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.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.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/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -346,8 +346,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -408,8 +408,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/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.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +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/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= diff --git a/test/integration/consul-container/go.mod b/test/integration/consul-container/go.mod index ce7a61ef253f..aaebeb412ad1 100644 --- a/test/integration/consul-container/go.mod +++ b/test/integration/consul-container/go.mod @@ -30,7 +30,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 github.com/testcontainers/testcontainers-go v0.22.0 - golang.org/x/mod v0.12.0 + golang.org/x/mod v0.13.0 google.golang.org/grpc v1.58.3 ) @@ -99,7 +99,7 @@ require ( golang.org/x/net v0.24.0 // indirect golang.org/x/sys v0.20.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect + golang.org/x/tools v0.14.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/test/integration/consul-container/go.sum b/test/integration/consul-container/go.sum index a418b57d6d9a..2a7b3b8015a9 100644 --- a/test/integration/consul-container/go.sum +++ b/test/integration/consul-container/go.sum @@ -319,8 +319,8 @@ golang.org/x/mod v0.3.0/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.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.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/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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -351,8 +351,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -418,8 +418,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/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.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +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/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= From 1986c558a8042665eefb3111460bdd5443126dd6 Mon Sep 17 00:00:00 2001 From: "R.B. Boyer" <4903+rboyer@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:14:39 -0500 Subject: [PATCH 13/97] api: remove dependency on proto-public, protobuf, and grpc (#21780) --- .changelog/21780.txt | 3 ++ api/go.mod | 11 +------ api/go.sum | 10 ------- api/raw_test.go | 65 +++++++++++++++--------------------------- envoyextensions/go.sum | 2 -- 5 files changed, 27 insertions(+), 64 deletions(-) create mode 100644 .changelog/21780.txt diff --git a/.changelog/21780.txt b/.changelog/21780.txt new file mode 100644 index 000000000000..72550e549a42 --- /dev/null +++ b/.changelog/21780.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: remove dependency on proto-public, protobuf, and grpc +``` diff --git a/api/go.mod b/api/go.mod index e4de0fa6c17e..715a594dcf47 100644 --- a/api/go.mod +++ b/api/go.mod @@ -2,10 +2,7 @@ module github.com/hashicorp/consul/api go 1.19 -replace ( - github.com/hashicorp/consul/proto-public => ../proto-public - github.com/hashicorp/consul/sdk => ../sdk -) +replace github.com/hashicorp/consul/sdk => ../sdk retract ( v1.28.0 // tag was mutated @@ -15,7 +12,6 @@ retract ( require ( github.com/google/go-cmp v0.5.9 - github.com/hashicorp/consul/proto-public v0.6.2 github.com/hashicorp/consul/sdk v0.16.1 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-hclog v1.5.0 @@ -26,14 +22,12 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 - google.golang.org/protobuf v1.33.0 ) require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fatih/color v1.16.0 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -53,8 +47,5 @@ require ( golang.org/x/net v0.24.0 // indirect golang.org/x/sync v0.2.0 // indirect golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect - google.golang.org/grpc v1.56.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/api/go.sum b/api/go.sum index a11d68700484..de53ac240dcc 100644 --- a/api/go.sum +++ b/api/go.sum @@ -34,8 +34,6 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= @@ -219,18 +217,10 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/api/raw_test.go b/api/raw_test.go index 1f75b8f3e24b..3f48dfb736a5 100644 --- a/api/raw_test.go +++ b/api/raw_test.go @@ -4,34 +4,24 @@ package api import ( - "encoding/json" "fmt" "strings" "testing" "github.com/stretchr/testify/require" - "google.golang.org/protobuf/encoding/protojson" - - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" ) type V2WriteRequest struct { - Metadata map[string]string `json:"metadata"` - Data map[string]any `json:"data"` - Owner *pbresource.ID `json:"owner"` + Data map[string]any `json:"data"` } type V2WriteResponse struct { - Metadata map[string]string `json:"metadata"` - Data map[string]any `json:"data"` - Owner *pbresource.ID `json:"owner,omitempty"` - ID *pbresource.ID `json:"id"` - Version string `json:"version"` - Generation string `json:"generation"` - Status map[string]any `json:"status"` + ID struct { + Name string `json:"name"` + } `json:"id"` + Data map[string]any `json:"data"` } // We are testing a v2 endpoint here in the v1 api module as a temporary measure to @@ -47,43 +37,34 @@ func TestAPI_RawV2ExportedServices(t *testing.T) { endpoint := strings.ToLower(fmt.Sprintf("/api/multicluster/v2/exportedservices/e1")) wResp := &V2WriteResponse{} - var consumers []map[string]any - consumers = append(consumers, map[string]any{"peer": "p1"}) - data := map[string]any{"consumers": consumers} - data["services"] = []string{"s1"} wReq := &V2WriteRequest{ - Metadata: nil, - Data: data, - Owner: nil, + Data: map[string]any{ + "consumers": []map[string]any{ + {"peer": "p1"}, + }, + "services": []string{"s1"}, + }, } _, err := c.Raw().Write(endpoint, wReq, wResp, &WriteOptions{Datacenter: "dc1"}) - if err != nil { - t.Fatalf("err: %v", err) - } - if wResp.ID.Name == "" { - t.Fatalf("no write response") - } + require.NoError(t, err) + require.NotEmpty(t, wResp.ID.Name) qOpts := &QueryOptions{Datacenter: "dc1"} + var out map[string]interface{} _, err = c.Raw().Query(endpoint, &out, qOpts) - if err != nil { - t.Fatalf("err: %v", err) - } - respData, _ := json.Marshal(out["data"]) - readData := &pbmulticluster.ExportedServices{} - if err = protojson.Unmarshal(respData, readData); err != nil { - t.Fatalf("invalid read response") - } - if len(readData.Services) != 1 { - t.Fatalf("incorrect resource data") - } + require.NoError(t, err) + + require.Equal(t, map[string]any{ + "consumers": []any{ + map[string]any{"peer": "p1"}, + }, + "services": []any{"s1"}, + }, out["data"]) _, err = c.Raw().Delete(endpoint, qOpts) - if err != nil { - t.Fatalf("err: %v", err) - } + require.NoError(t, err) out = make(map[string]interface{}) _, err = c.Raw().Query(endpoint, &out, qOpts) diff --git a/envoyextensions/go.sum b/envoyextensions/go.sum index b215d6492103..d29e39ebe83f 100644 --- a/envoyextensions/go.sum +++ b/envoyextensions/go.sum @@ -235,7 +235,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -255,7 +254,6 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go. google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= From bfc25b17572cc14db0d5fe17db53df6786f19214 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Wed, 25 Sep 2024 13:08:24 -0400 Subject: [PATCH 14/97] [NET-11150] ci: fix conditional skip and add safeguard (#21781) ci: fix conditional skip and add safeguard Adopt a third-party action to avoid script bugs, and to fix a current issue where the script fails to detect all changes when processing push events on PR branches. Adapted from hashicorp/consul-dataplane#637. See that PR for testing details and background context. --- .github/scripts/check_skip_ci.sh | 50 -------------- .github/workflows/go-tests.yml | 13 +--- .../workflows/reusable-conditional-skip.yml | 69 +++++++++++++++++++ .github/workflows/security-scan.yml | 4 ++ .github/workflows/test-integrations.yml | 13 +--- 5 files changed, 75 insertions(+), 74 deletions(-) delete mode 100755 .github/scripts/check_skip_ci.sh create mode 100644 .github/workflows/reusable-conditional-skip.yml diff --git a/.github/scripts/check_skip_ci.sh b/.github/scripts/check_skip_ci.sh deleted file mode 100755 index a22b990f2692..000000000000 --- a/.github/scripts/check_skip_ci.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -set -euo pipefail - -# Get the list of changed files -# Using `git merge-base` ensures that we're always comparing against the correct branch point. -#For example, given the commits: -# -# A---B---C---D---W---X---Y---Z # origin/main -# \---E---F # feature/branch -# -# ... `git merge-base origin/$SKIP_CHECK_BRANCH HEAD` would return commit `D` -# `...HEAD` specifies from the common ancestor to the latest commit on the current branch (HEAD).. -skip_check_branch=${SKIP_CHECK_BRANCH:?SKIP_CHECK_BRANCH is required} -files_to_check=$(git diff --name-only "$(git merge-base origin/$skip_check_branch HEAD~)"...HEAD) - -# Define the directories to check -skipped_directories=("docs/" "ui/" "website/" "grafana/" ".changelog/") - -# Loop through the changed files and find directories/files outside the skipped ones -files_to_check_array=($files_to_check) -for file_to_check in "${files_to_check_array[@]}"; do - file_is_skipped=false - echo "checking file: $file_to_check" - - # Allow changes to: - # - This script - # - Files in the skipped directories - # - Markdown files - for dir in "${skipped_directories[@]}"; do - if [[ "$file_to_check" == */check_skip_ci.sh ]] || - [[ "$file_to_check" == "$dir"* ]] || - [[ "$file_to_check" == *.md ]]; then - file_is_skipped=true - break - fi - done - - if [ "$file_is_skipped" != "true" ]; then - echo -e "non-skippable file changed: $file_to_check" - echo "Changes detected in non-documentation files - will not skip tests and build" - echo "skip-ci=false" >> "$GITHUB_OUTPUT" - exit 0 ## if file is outside of the skipped_directory exit script - fi -done - -echo "Changes detected in only documentation files - skipping tests and build" -echo "skip-ci=true" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml index 6ea14b4fab03..c30e6e81946a 100644 --- a/.github/workflows/go-tests.yml +++ b/.github/workflows/go-tests.yml @@ -22,7 +22,6 @@ permissions: env: TEST_RESULTS: /tmp/test-results GOPRIVATE: github.com/hashicorp # Required for enterprise deps - SKIP_CHECK_BRANCH: ${{ github.head_ref || github.ref_name }} # concurrency concurrency: @@ -31,17 +30,7 @@ concurrency: jobs: conditional-skip: - runs-on: ubuntu-latest - name: Get files changed and conditionally skip CI - outputs: - skip-ci: ${{ steps.read-files.outputs.skip-ci }} - steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - with: - fetch-depth: 0 - - name: Get changed files - id: read-files - run: ./.github/scripts/check_skip_ci.sh + uses: ./.github/workflows/reusable-conditional-skip.yml setup: needs: [conditional-skip] diff --git a/.github/workflows/reusable-conditional-skip.yml b/.github/workflows/reusable-conditional-skip.yml new file mode 100644 index 000000000000..36a5eaba60e8 --- /dev/null +++ b/.github/workflows/reusable-conditional-skip.yml @@ -0,0 +1,69 @@ +name: conditional-skip + +on: + workflow_call: + outputs: + skip-ci: + description: "Whether we should skip build and test jobs" + value: ${{ jobs.check-skip.outputs.skip-ci }} + +jobs: + check-skip: + runs-on: ubuntu-latest + name: Check whether to skip build and tests + outputs: + skip-ci: ${{ steps.maybe-skip-ci.outputs.skip-ci }} + steps: + # We only allow use of conditional skip in two scenarios: + # 1. PRs + # 2. Pushes (merges) to protected branches (`main`, `release/**`) + # + # The second scenario is the only place we can be sure that checking just the + # latest change on the branch is sufficient. In PRs, we need to check _all_ commits. + # The ability to do this is ultimately determined by the triggers of the calling + # workflow, since `base_ref` (the target branch of a PR) is only available in + # `pull_request` events, not `push`. + - name: Error if conditional check is not allowed + if: ${{ !github.base_ref && !github.ref_protected }} + run: | + echo "Conditional skip requires a PR event with 'base_ref' or 'push' to a protected branch." + echo "github.base_ref: ${{ github.base_ref }}" + echo "github.ref_protected: ${{ github.ref_protected }}" + echo "github.ref_name: ${{ github.ref_name }}" + echo "Check the triggers of the calling workflow to ensure that these requirements are met." + exit 1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + fetch-depth: 0 + - name: Check for skippable file changes + id: changed-files + uses: tj-actions/changed-files@e9772d140489982e0e3704fea5ee93d536f1e275 # v45.0.1 + with: + # This is a multi-line YAML string with one match pattern per line. + # Do not use quotes around values, as it's not supported. + # See https://github.com/tj-actions/changed-files/blob/main/README.md#inputs-%EF%B8%8F + # for usage, options, and more details on match syntax. + files: | + .github/workflows/reusable-conditional-skip.yml + **.md + docs/** + ui/** + website/** + grafana/** + .changelog/** + - name: Print changed files + env: + SKIPPABLE_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} + NON_SKIPPABLE_FILES: ${{ steps.changed-files.outputs.other_changed_files }} + run: | + echo "Skippable changed files:" + for file in ${SKIPPABLE_CHANGED_FILES}; do echo " $file"; done + echo + echo "Non-skippable files:" + for file in ${NON_SKIPPABLE_FILES}; do echo " $file"; done + - name: Skip tests and build if only skippable files changed + id: maybe-skip-ci + if: ${{ steps.changed-files.outputs.only_changed == 'true' }} + run: | + echo "Skipping tests and build because only skippable files changed" + echo "skip-ci=true" >> $GITHUB_OUTPUT \ No newline at end of file diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index ad851dca1e0c..63e00847fc79 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -1,3 +1,5 @@ +# This job runs a non-blocking informational security scan on the repository. +# For release-blocking security scans, see .release/security-scan.hcl. name: Security Scan on: @@ -9,6 +11,8 @@ on: branches: - main - release/** + # paths-ignore only works for non-required checks. + # Jobs that are required for merge must use reusable-conditional-skip.yml. paths-ignore: - 'docs/**' - 'grafana/**' diff --git a/.github/workflows/test-integrations.yml b/.github/workflows/test-integrations.yml index c83338ee0c9d..f5d8e30eca2e 100644 --- a/.github/workflows/test-integrations.yml +++ b/.github/workflows/test-integrations.yml @@ -29,7 +29,6 @@ env: # strip the hashicorp/ off the front of github.repository for consul CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} GOPRIVATE: github.com/hashicorp # Required for enterprise deps - SKIP_CHECK_BRANCH: ${{ github.head_ref || github.ref_name }} concurrency: group: "${{ github.workflow }}-${{ github.head_ref || github.ref }}" @@ -37,17 +36,7 @@ concurrency: jobs: conditional-skip: - runs-on: ubuntu-latest - name: Get files changed and conditionally skip CI - outputs: - skip-ci: ${{ steps.read-files.outputs.skip-ci }} - steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - with: - fetch-depth: 0 - - name: Get changed files - id: read-files - run: ./.github/scripts/check_skip_ci.sh + uses: ./.github/workflows/reusable-conditional-skip.yml setup: needs: [conditional-skip] From 718bf7496ffcde3c69b28b3ff74fba79f49ce56f Mon Sep 17 00:00:00 2001 From: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> Date: Thu, 26 Sep 2024 10:46:43 -0500 Subject: [PATCH 15/97] Fix changelog for 1.20-rc1 (#21776) fix changelog --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b13ac86b3bd3..940ab662e068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,11 @@ SECURITY: * Explicitly set 'Content-Type' header to mitigate XSS vulnerability. [[GH-21704](https://github.com/hashicorp/consul/issues/21704)] * Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. [[GH-21711](https://github.com/hashicorp/consul/issues/21711)] * UI: Remove codemirror linting due to package dependency [[GH-21726](https://github.com/hashicorp/consul/issues/21726)] -* Upgrade Go to use 1.22.7. This addresses CVE -[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] +* Upgrade Go to use 1.22.7. This addresses CVE + [CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] * Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs -[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and -[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] + [CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and + [CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] * ui: Pin a newer resolution of Braces [[GH-21710](https://github.com/hashicorp/consul/issues/21710)] * ui: Pin a newer resolution of Codemirror [[GH-21715](https://github.com/hashicorp/consul/issues/21715)] * ui: Pin a newer resolution of Markdown-it [[GH-21717](https://github.com/hashicorp/consul/issues/21717)] From a6898939910b175db7495f02131918c0cc73027c Mon Sep 17 00:00:00 2001 From: John Maguire Date: Fri, 27 Sep 2024 13:16:31 -0400 Subject: [PATCH 16/97] Add partition field for catalog deregister docs (#21788) * Add partition field for catalog deregister docs * Update website/content/api-docs/catalog.mdx Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> --------- Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> --- website/content/api-docs/catalog.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/website/content/api-docs/catalog.mdx b/website/content/api-docs/catalog.mdx index 8c549b304376..f773353483a2 100644 --- a/website/content/api-docs/catalog.mdx +++ b/website/content/api-docs/catalog.mdx @@ -212,6 +212,8 @@ The behavior of the endpoint depends on what keys are provided. You can also specify the namespace in the `Service` or `Check` fields; if namespaces are specified in multiple places, they must all be the same. +- `Partition` `(string: "")` - Specifies the admin partition of the service and checks you deregister. + ### Sample Payloads ```json @@ -221,6 +223,14 @@ The behavior of the endpoint depends on what keys are provided. } ``` +```json +{ + "Datacenter": "dc1", + "Node": "t2.320", + "Partition": "part-1" +} +``` + ```json { "Datacenter": "dc1", From 029ac10acc45eaa1f33c4c9ea38bd852ab8930fc Mon Sep 17 00:00:00 2001 From: John Murret Date: Wed, 2 Oct 2024 13:02:23 -0600 Subject: [PATCH 17/97] update serf links (#21797) * update serf links * add .markdown file extension * update serf links to use /blob/master/ * fix broken links --------- Co-authored-by: github-team-consul-core --- internal/gossip/libserf/serf.go | 2 +- .../content/docs/architecture/coordinates.mdx | 4 +- website/content/docs/architecture/gossip.mdx | 8 +- website/content/docs/install/glossary.mdx | 374 +++++++++--------- .../docs/security/encryption/index.mdx | 8 +- website/content/docs/troubleshoot/faq.mdx | 2 +- 6 files changed, 199 insertions(+), 199 deletions(-) diff --git a/internal/gossip/libserf/serf.go b/internal/gossip/libserf/serf.go index f5d6a90e748c..4e4f7de55609 100644 --- a/internal/gossip/libserf/serf.go +++ b/internal/gossip/libserf/serf.go @@ -29,7 +29,7 @@ func DefaultConfig() *serf.Config { // This gives leaves some time to propagate through the cluster before // we shut down. The value was chosen to be reasonably short, but to // allow a leave to get to over 99.99% of the cluster with 100k nodes - // (using https://www.serf.io/docs/internals/simulator.html). + // (using https://github.com/hashicorp/serf/blob/master/docs/internals/simulator.html.erb). base.LeavePropagateDelay = 3 * time.Second return base diff --git a/website/content/docs/architecture/coordinates.mdx b/website/content/docs/architecture/coordinates.mdx index ad8f7722e2ae..7bc37cc9c029 100644 --- a/website/content/docs/architecture/coordinates.mdx +++ b/website/content/docs/architecture/coordinates.mdx @@ -14,10 +14,10 @@ very simple calculation. This allows for many useful applications, such as findi the service node nearest a requesting node, or failing over to services in the next closest datacenter. -All of this is provided through the use of the [Serf library](https://www.serf.io/). +All of this is provided through the use of the [Serf library](https://github.com/hashicorp/serf/). Serf's network tomography is based on ["Vivaldi: A Decentralized Network Coordinate System"](http://www.cs.ucsb.edu/~ravenben/classes/276/papers/vivaldi-sigcomm04.pdf), with some enhancements based on other research. There are more details about -[Serf's network coordinates here](https://www.serf.io/docs/internals/coordinates.html). +[Serf's network coordinates here](https://github.com/hashicorp/serf/blob/master/docs/internals/coordinates.html.markdown). ## Network Coordinates in Consul diff --git a/website/content/docs/architecture/gossip.mdx b/website/content/docs/architecture/gossip.mdx index 09f85b19bd5c..12a4ef8de7ac 100644 --- a/website/content/docs/architecture/gossip.mdx +++ b/website/content/docs/architecture/gossip.mdx @@ -9,15 +9,15 @@ description: >- Consul uses a [gossip protocol](https://en.wikipedia.org/wiki/Gossip_protocol) to manage membership and broadcast messages to the cluster. The protocol, membership management, and message broadcasting is provided -through the [Serf library](https://www.serf.io/). The gossip protocol +through the [Serf library](https://github.com/hashicorp/serf/). The gossip protocol used by Serf is based on a modified version of the [SWIM (Scalable Weakly-consistent Infection-style Process Group Membership)](https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf) protocol. -Refer to the [Serf documentation](https://www.serf.io/docs/internals/gossip.html) for additional information about the gossip protocol. +Refer to the [Serf documentation](https://github.com/hashicorp/serf/blob/master/docs/internals/gossip.html.markdown) for additional information about the gossip protocol. ## Gossip in Consul Consul uses a LAN gossip pool and a WAN gossip pool to perform different functions. The pools -are able to perform their functions by leveraging an embedded [Serf](https://www.serf.io/) +are able to perform their functions by leveraging an embedded [Serf](https://github.com/hashicorp/serf/) library. The library is abstracted and masked by Consul to simplify the user experience, but developers may find it useful to understand how the library is leveraged. @@ -52,5 +52,5 @@ For more details about Lifeguard, please see the [Making Gossip More Robust with Lifeguard](https://www.hashicorp.com/blog/making-gossip-more-robust-with-lifeguard/) blog post, which provides a high level overview of the HashiCorp Research paper [Lifeguard : SWIM-ing with Situational Awareness](https://arxiv.org/abs/1707.00788). The -[Serf gossip protocol guide](https://www.serf.io/docs/internals/gossip.html#lifeguard) +[Serf gossip protocol guide](https://github.com/hashicorp/serf/blob/master/docs/internals/gossip.html.markdown#lifeguard-enhancements) also provides some lower-level details about the gossip protocol and Lifeguard. diff --git a/website/content/docs/install/glossary.mdx b/website/content/docs/install/glossary.mdx index f11ae21e7be0..c8bee74d6d77 100644 --- a/website/content/docs/install/glossary.mdx +++ b/website/content/docs/install/glossary.mdx @@ -51,7 +51,7 @@ and our implementation is described [here](/consul/docs/architecture/consensus). ## Gossip -Consul is built on top of [Serf](https://www.serf.io/) which provides a full +Consul is built on top of [Serf](https://github.com/hashicorp/serf/) which provides a full [gossip protocol](https://en.wikipedia.org/wiki/Gossip_protocol) that is used for multiple purposes. Serf provides membership, failure detection, and event broadcast. Our use of these is described more in the [gossip documentation](/consul/docs/architecture/gossip). It is enough to know @@ -78,171 +78,171 @@ This section collects brief definitions of some of the terms used in the discuss ## Access Control List (ACL) -An Access Control List (ACL) is a list of user permissions for a file, folder, or -other object. It defines what users and groups can access the object and what +An Access Control List (ACL) is a list of user permissions for a file, folder, or +other object. It defines what users and groups can access the object and what operations they can perform. Consul uses Access Control Lists (ACLs) to secure the UI, API, CLI, service communications, and agent communications. Visit [Consul ACL Documentation and Guides](/consul/docs/security/acl) -## API Gateway -An Application Programming Interface (API) is a common software interface that -allows two applications to communicate. Most modern applications are built using -APIs. An API Gateway is a single point of entry into these modern applications +## API Gateway +An Application Programming Interface (API) is a common software interface that +allows two applications to communicate. Most modern applications are built using +APIs. An API Gateway is a single point of entry into these modern applications built using APIs. -## Application Security -Application Security is the process of making applications secure by detecting -and fixing any threats or information leaks. This can be done during or after -the app development lifecycle; although, it is easier for app teams and security -teams to incorporate security into an app even before the development process +## Application Security +Application Security is the process of making applications secure by detecting +and fixing any threats or information leaks. This can be done during or after +the app development lifecycle; although, it is easier for app teams and security +teams to incorporate security into an app even before the development process begins. -## Application Services -Application Services are a group of services, such as application performance -monitoring, load balancing, service discovery, service proxy, security, -autoscaling, etc. needed to deploy, run, and improve applications. +## Application Services +Application Services are a group of services, such as application performance +monitoring, load balancing, service discovery, service proxy, security, +autoscaling, etc. needed to deploy, run, and improve applications. -## Authentication and Authorization (AuthN and AuthZ) +## Authentication and Authorization (AuthN and AuthZ) Authentication (AuthN) deals with establishing user identity while Authorization (AuthZ) allows or denies access to the user based on user identity. -## Auto Scaling Groups -An Auto Scaling Group is an AWS specific term that represents a collection of -Amazon EC2 instances that are treated as a logical grouping for the purposes of -automatic scaling and management. -Learn more about Auto Scaling Groups +## Auto Scaling Groups +An Auto Scaling Group is an AWS specific term that represents a collection of +Amazon EC2 instances that are treated as a logical grouping for the purposes of +automatic scaling and management. +Learn more about Auto Scaling Groups [here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroup.html). -## Autoscaling -Autoscaling is the process of automatically scaling computational resources based -on network traffic requirements. Autoscaling can be done either horizontally or -vertically. Horizontal scaling is done by adding more machines into the pool of -resources whereas vertical scaling means increasing the capacity of an existing +## Autoscaling +Autoscaling is the process of automatically scaling computational resources based +on network traffic requirements. Autoscaling can be done either horizontally or +vertically. Horizontal scaling is done by adding more machines into the pool of +resources whereas vertical scaling means increasing the capacity of an existing machine. -## Blue-Green Deployments -Blue-Green Deployment is a deployment method designed to reduce downtime by -running two identical production environments labeled Blue and Green. Blue is -the active while Green is the idle environment. +## Blue-Green Deployments +Blue-Green Deployment is a deployment method designed to reduce downtime by +running two identical production environments labeled Blue and Green. Blue is +the active while Green is the idle environment. -## Canary Deployments -Canary deployment is the pattern used for rolling out releases to a subset of -users or servers. The goal is deploy the updates to a subset of users, test it, -and then roll out the changes to everyone. +## Canary Deployments +Canary deployment is the pattern used for rolling out releases to a subset of +users or servers. The goal is deploy the updates to a subset of users, test it, +and then roll out the changes to everyone. -## Client-side Load Balancing -Client-side load balancing is a load balancing approach that relies on clients' -decision to call the right servers. As the name indicates, this approach is part -of the client application. Servers can still have their own load balancer +## Client-side Load Balancing +Client-side load balancing is a load balancing approach that relies on clients' +decision to call the right servers. As the name indicates, this approach is part +of the client application. Servers can still have their own load balancer alongside the client-side load balancer. -## Cloud Native Computing Foundation -The [Cloud Native Computing Foundation (CNCF)](https://github.com/cncf/foundation) -is a Linux Foundation project that was founded in 2015 to help advance +## Cloud Native Computing Foundation +The [Cloud Native Computing Foundation (CNCF)](https://github.com/cncf/foundation) +is a Linux Foundation project that was founded in 2015 to help advance container technology and align the tech industry around its evolution. -HashiCorp joined Cloud Native Computing Foundation to further HashiCorp -product integrations with CNCF projects and to work more closely with the -broader cloud-native community of cloud engineers. Read more +HashiCorp joined Cloud Native Computing Foundation to further HashiCorp +product integrations with CNCF projects and to work more closely with the +broader cloud-native community of cloud engineers. Read more [here](https://www.hashicorp.com/blog/hashicorp-joins-the-cncf/). -## Custom Resource Definition (CRD) -Custom resources are the extensions of the Kubernetes API. A Custom Resource -Definition (CRD) file allows users to define their own custom resources and +## Custom Resource Definition (CRD) +Custom resources are the extensions of the Kubernetes API. A Custom Resource +Definition (CRD) file allows users to define their own custom resources and allows the API server to handle the lifecycle. -## Egress Traffic -Egress traffic is network traffic that begins inside a network and proceeds +## Egress Traffic +Egress traffic is network traffic that begins inside a network and proceeds through its routers to a destination outside the network. -## Elastic Provisioning -Elastic Provisioning is the ability to provision computing resources +## Elastic Provisioning +Elastic Provisioning is the ability to provision computing resources dynamically to meet user demand. -## Envoy Proxy -[Envoy Proxy](https://www.envoyproxy.io/) is a modern, high performance, -small footprint edge and service proxy. Originally written and deployed at +## Envoy Proxy +[Envoy Proxy](https://www.envoyproxy.io/) is a modern, high performance, +small footprint edge and service proxy. Originally written and deployed at [Lyft](https://eng.lyft.com/announcing-envoy-c-l7-proxy-and-communication-bus-92520b6c8191), - Envoy Proxy is now an official project at [Cloud Native Computing Foundation - (CNCF)](https://www.cncf.io/cncf-envoy-project-journey/) + Envoy Proxy is now an official project at [Cloud Native Computing Foundation + (CNCF)](https://www.cncf.io/cncf-envoy-project-journey/) -## Forward Proxy -A forward proxy is used to forward outgoing requests from inside the network -to the Internet, usually through a firewall. The objective is to provide a level +## Forward Proxy +A forward proxy is used to forward outgoing requests from inside the network +to the Internet, usually through a firewall. The objective is to provide a level of security and to reduce network traffic. -## Hybrid Cloud Architecture -A hybrid cloud architecture is an IT architectural approach that mixes -on-premises, private cloud, and public cloud services. A hybrid cloud -environment incorporates workload portability, orchestration, and management +## Hybrid Cloud Architecture +A hybrid cloud architecture is an IT architectural approach that mixes +on-premises, private cloud, and public cloud services. A hybrid cloud +environment incorporates workload portability, orchestration, and management across the environments. -A private cloud, traditionally on-premises, is referred to an infrastructure +A private cloud, traditionally on-premises, is referred to an infrastructure environment managed by the user themselves. -A public cloud, traditionally off-premises, is referred to an infrastructure +A public cloud, traditionally off-premises, is referred to an infrastructure service provided by a third party. -## Identity-based authorization -Identity-based authorization is a security approach to restrict or allow access +## Identity-based authorization +Identity-based authorization is a security approach to restrict or allow access based on the authenticated identity of an individual. -## Infrastructure as a Service -Infrastructure as a Service, often referred to as IaaS, is a cloud computing -approach where the computing resources are delivered online via APIs. These +## Infrastructure as a Service +Infrastructure as a Service, often referred to as IaaS, is a cloud computing +approach where the computing resources are delivered online via APIs. These APIs communicate with underlying infrastructure like physical computing resources, - location, data partitioning, scaling, security, backup, etc. + location, data partitioning, scaling, security, backup, etc. -IaaS is one of the four types of cloud services along with SaaS +IaaS is one of the four types of cloud services along with SaaS (Software as a Service), PaaS (Platform as a Service), and Serverless. -## Infrastructure as Code -Infrastructure as Code (IaC) is the process of developers and operations teams' -ability of provisioning and managing computing resources automatically through +## Infrastructure as Code +Infrastructure as Code (IaC) is the process of developers and operations teams' +ability of provisioning and managing computing resources automatically through software, instead of using configuration tools. -## Ingress Controller -In Kubernetes, "ingress" is an object that allows access Kubernetes services -from outside the Kubernetes cluster. An ingress controller is responsible for -ingress, generally with a load balancer or an edge router that can help with +## Ingress Controller +In Kubernetes, "ingress" is an object that allows access Kubernetes services +from outside the Kubernetes cluster. An ingress controller is responsible for +ingress, generally with a load balancer or an edge router that can help with traffic management. -## Ingress Gateway -An Ingress Gateway is an edge of the mesh load balancer that provides secure and -reliable access from external networks to Kubernetes clusters. +## Ingress Gateway +An Ingress Gateway is an edge of the mesh load balancer that provides secure and +reliable access from external networks to Kubernetes clusters. -## Ingress Traffic -Ingress Traffic is the network traffic that originates outside the network and +## Ingress Traffic +Ingress Traffic is the network traffic that originates outside the network and has a destination inside the network. -## Key-Value Store -A Key-Value Store (or a KV Store) also referred to as a Key-Value Database is -a data model where each key is associated with one and only one value in +## Key-Value Store +A Key-Value Store (or a KV Store) also referred to as a Key-Value Database is +a data model where each key is associated with one and only one value in a collection. -## L4 - L7 Services -L4-L7 Services are a set of functions such as load balancing, web application -firewalls, service discovery, and monitoring for network layers within the +## L4 - L7 Services +L4-L7 Services are a set of functions such as load balancing, web application +firewalls, service discovery, and monitoring for network layers within the Open Systems Interconnection (OSI) model. -## Layer 7 Observability -Layer 7 Observability is a feature of Consul Service Mesh that enables a -unified workflow for metric collection, distributed tracking, and logging. -It also allows centralized configuration and management for a distributed -data plane. +## Layer 7 Observability +Layer 7 Observability is a feature of Consul Service Mesh that enables a +unified workflow for metric collection, distributed tracking, and logging. +It also allows centralized configuration and management for a distributed +data plane. -## Load Balancer -A load balancer is a network appliance that acts as a [reverse proxy](#reverse-proxy) +## Load Balancer +A load balancer is a network appliance that acts as a [reverse proxy](#reverse-proxy) and distributes network and application traffic across the servers. -## Load Balancing -Load Balancing is the process of distributing network and application traffic -across multiple servers. +## Load Balancing +Load Balancing is the process of distributing network and application traffic +across multiple servers. -## Load Balancing Algorithms -Load balancers follow an algorithm to determine how to route the traffic across +## Load Balancing Algorithms +Load balancers follow an algorithm to determine how to route the traffic across the server farm. Some of the commonly used algorithms are: 1. Round Robin 2. Least Connections @@ -251,127 +251,127 @@ the server farm. Some of the commonly used algorithms are: 5. Least Response Time Method 6. Least Bandwidth Method -## Multi-cloud -A multi-cloud environment generally uses two or more cloud computing services -from different vendors in a single architecture. This refers to the distribution -of compute resources, storage, and networking aspects across cloud environments. -A multi-cloud environment could be either all private cloud or all public cloud -or a combination of both. +## Multi-cloud +A multi-cloud environment generally uses two or more cloud computing services +from different vendors in a single architecture. This refers to the distribution +of compute resources, storage, and networking aspects across cloud environments. +A multi-cloud environment could be either all private cloud or all public cloud +or a combination of both. -## Multi-cloud Networking -Multi-cloud Networking provides network configuration and management across +## Multi-cloud Networking +Multi-cloud Networking provides network configuration and management across multiple cloud providers via APIs. -## Mutual Transport Layer Security (mTLS) -Mutual Transport Layer Security, also known as mTLS, is an authentication -mechanism that ensures network traffic security in both directions between -a client and server. +## Mutual Transport Layer Security (mTLS) +Mutual Transport Layer Security, also known as mTLS, is an authentication +mechanism that ensures network traffic security in both directions between +a client and server. -## Network Middleware Automation -The process of publishing service changes to network middleware such as -load balancers and firewalls and automating network tasks is called Network +## Network Middleware Automation +The process of publishing service changes to network middleware such as +load balancers and firewalls and automating network tasks is called Network Middleware Automation. -## Network security -Network security is the process of protecting data and network. It consists -of a set of policies and practices that are designed to prevent and monitor -unauthorized access, misuse, modification, or denial of a computer network +## Network security +Network security is the process of protecting data and network. It consists +of a set of policies and practices that are designed to prevent and monitor +unauthorized access, misuse, modification, or denial of a computer network and network-accessible resources. -## Network traffic management -Network Traffic Management is the process of ensuring optimal network operation -by using a set of network monitoring tools. Network traffic management also -focuses on traffic management techniques such as bandwidth monitoring, deep +## Network traffic management +Network Traffic Management is the process of ensuring optimal network operation +by using a set of network monitoring tools. Network traffic management also +focuses on traffic management techniques such as bandwidth monitoring, deep packet inspection, and application based routing. -## Network Visualization -Network Visualization is the process of visually displaying networks and -connected entities in a "boxes and lines" kind of a diagram. +## Network Visualization +Network Visualization is the process of visually displaying networks and +connected entities in a "boxes and lines" kind of a diagram. -In the context of microservices architecture, visualization can provide a clear -picture of how services are connected to each other, the service-to-service +In the context of microservices architecture, visualization can provide a clear +picture of how services are connected to each other, the service-to-service communication, and resource utilization of each service. -## Observability -Observability is the process of logging, monitoring, and alerting on the +## Observability +Observability is the process of logging, monitoring, and alerting on the events of a deployment or an instance. -## Elastic Scaling -Elastic Scaling is the ability to automatically add or remove compute or +## Elastic Scaling +Elastic Scaling is the ability to automatically add or remove compute or networking resources based on the changes in application traffic patterns. -## Platform as a Service -Platform-as-a-Service (PaaS) is a category of cloud computing that allows -users to develop, run, and manage applications without the complexity of -building and maintaining the infrastructure typically associated with -developing and launching the application. - -## Reverse Proxy -A reverse proxy handles requests coming from outside, to the internal -network. Reverse Proxy provides a level of security that prevents the -external clients from having direct access to data on the corporate servers. -The reverse proxy is usually placed between the web server and the external -traffic. - -## Role-based Access Controls -The act of restricting or provisioning access +## Platform as a Service +Platform-as-a-Service (PaaS) is a category of cloud computing that allows +users to develop, run, and manage applications without the complexity of +building and maintaining the infrastructure typically associated with +developing and launching the application. + +## Reverse Proxy +A reverse proxy handles requests coming from outside, to the internal +network. Reverse Proxy provides a level of security that prevents the +external clients from having direct access to data on the corporate servers. +The reverse proxy is usually placed between the web server and the external +traffic. + +## Role-based Access Controls +The act of restricting or provisioning access to a user based on their specific role in the organization. -## Server side load balancing -A Server-side Load Balancer sits between the client and the server farm, -accepts incoming traffic, and distributes the traffic across multiple backend +## Server side load balancing +A Server-side Load Balancer sits between the client and the server farm, +accepts incoming traffic, and distributes the traffic across multiple backend servers using various load balancing methods. -## Service configuration -A service configuration includes the name, description, and the specific -function of a service. In a microservices application architecture setting, +## Service configuration +A service configuration includes the name, description, and the specific +function of a service. In a microservices application architecture setting, a service configuration file includes a service definition. -## Service Catalog -A service catalog is an organized and curated collection of services that +## Service Catalog +A service catalog is an organized and curated collection of services that are available for developers to bind to their applications. -## Service Discovery -Service Discovery is the process of detecting services and devices on a -network. In a microservices context, service discovery is how applications +## Service Discovery +Service Discovery is the process of detecting services and devices on a +network. In a microservices context, service discovery is how applications and microservices locate each other on a network. -## Service Mesh -Service Mesh is the infrastructure layer that facilitates service-to-service -communication between microservices, often using a sidecar proxy. This -network of microservices make up microservice applications and the +## Service Mesh +Service Mesh is the infrastructure layer that facilitates service-to-service +communication between microservices, often using a sidecar proxy. This +network of microservices make up microservice applications and the interactions between them. -## Service Networking -Service networking brings several entities together to deliver a particular -service. Service Networking acts as the brain of an organization's +## Service Networking +Service networking brings several entities together to deliver a particular +service. Service Networking acts as the brain of an organization's networking and monitoring operations. -## Service Proxy -A service proxy is the client-side proxy for a microservice application. -It allows applications to send and receive messages over a proxy server. +## Service Proxy +A service proxy is the client-side proxy for a microservice application. +It allows applications to send and receive messages over a proxy server. -## Service Registration -Service registration is the process of letting clients (of the service) -and routers know about the available instances of the service. +## Service Registration +Service registration is the process of letting clients (of the service) +and routers know about the available instances of the service. Service instances are registered with a service registry on startup and deregistered at shutdown. -## Service Registry -Service Registry is a database of service instances and information on +## Service Registry +Service Registry is a database of service instances and information on how to send requests to these service instances. -## Microservice Segmentation -Microservice segmentation, sometimes visual, of microservices is the -segmentation in a microservices application architecture that enables +## Microservice Segmentation +Microservice segmentation, sometimes visual, of microservices is the +segmentation in a microservices application architecture that enables administrators to view their functions and interactions. -## Service-to-service communication -Service-to-service communication, sometimes referred to as -inter-service communication, is the ability of a microservice -application instance to communicate with another to collaborate and +## Service-to-service communication +Service-to-service communication, sometimes referred to as +inter-service communication, is the ability of a microservice +application instance to communicate with another to collaborate and handle client requests. -## Software as a Service -Software as a Service is a licensing and delivery approach to software -delivery where the software is hosted by a provider and licensed -to users on a subscription basis. +## Software as a Service +Software as a Service is a licensing and delivery approach to software +delivery where the software is hosted by a provider and licensed +to users on a subscription basis. diff --git a/website/content/docs/security/encryption/index.mdx b/website/content/docs/security/encryption/index.mdx index b5324ef63f24..60a5352b8a6f 100644 --- a/website/content/docs/security/encryption/index.mdx +++ b/website/content/docs/security/encryption/index.mdx @@ -19,15 +19,15 @@ Consul uses a [gossip protocol](/consul/docs/architecture/gossip) to perform the - Quickly detect failed members and notify the rest of the cluster. - Broadcast events and queries that can trigger custom workflows. -The gossip protocol, as well as its membership management and message broadcasting features, use the [Serf library](https://www.serf.io/). +The gossip protocol, as well as its membership management and message broadcasting features, use the [Serf library](https://github.com/hashicorp/serf/). In a default Consul configuration, the gossip protocol uses [port `8301`](/consul/docs/install/ports#lan-serf) for LAN communications and [port `8302`](/consul/docs/install/ports#lan-serf) for WAN communications between federated datacenters. Enabling gossip encryption on a Consul datacenter is required to secure traffic on these two ports. Gossip encryption is symmetric and based on a single key that is shared across all members of the datacenter. You can configure gossip encryption in Consul using the following parameters: - [`encrypt`](/consul/docs/agent/config/config-files#encrypt). -- [`encrypt_verify_incoming`](/consul/docs/agent/config/config-files#encrypt_verify_incoming). Only used when upshifting from unencrypted to encrypted gossip on a running cluster. -- [`encrypt_verify_outgoing`](/consul/docs/agent/config/config-files#encrypt_verify_outgoing). Only used when upshifting from unencrypted to encrypted gossip on a running cluster. +- [`encrypt_verify_incoming`](/consul/docs/agent/config/config-files#encrypt_verify_incoming). Only used when upshifting from unencrypted to encrypted gossip on a running cluster. +- [`encrypt_verify_outgoing`](/consul/docs/agent/config/config-files#encrypt_verify_outgoing). Only used when upshifting from unencrypted to encrypted gossip on a running cluster. To learn more about enabling gossip encryption on your Consul datacenter and rotating gossip keys, refer to [manage gossip encryption](/consul/docs/security/encryption/gossip). @@ -39,7 +39,7 @@ Consul uses several communication protocols over different ports that you can se - Remote Procedure Calls (RPC) forward requests from client agents to server agents. They use the same port the consensus protocol uses. - An HTTP or HTTPS interface permits client communication with the Consul API, CLI, and UI. It typically uses [port `8500`](/consul/docs/install/ports#http) and [port `8501`](/consul/docs/install/ports#https). - A gRPC interface receives incoming traffic from the gateways and Envoy proxies registered to the agent node. It typically uses [port `8502`](/consul/docs/install/ports#client-grpc) and [port `8503`](/consul/docs/install/ports#client-grpc-tls). - + Consul uses mTLS to verify the authenticity of server and client agents. It requires that all clients and servers have key pairs that are generated by a single Certification Authority (CA). We recommend using a private CA that is not shared with other applications. You can configure mTLS in Consul using the [`tls` stanza in agent configuration files](/consul/docs/agent/config/config-files#tls-1). diff --git a/website/content/docs/troubleshoot/faq.mdx b/website/content/docs/troubleshoot/faq.mdx index c57ad30232ab..5e733f1cd1af 100644 --- a/website/content/docs/troubleshoot/faq.mdx +++ b/website/content/docs/troubleshoot/faq.mdx @@ -69,7 +69,7 @@ and [`disable_update_check`](/consul/docs/agent/config/config-files#disable_upda ### Q: Does Consul rely on UDP Broadcast or Multicast? -Consul uses the [Serf](https://www.serf.io) gossip protocol which relies on +Consul uses the [Serf](https://github.com/hashicorp/serf/) gossip protocol which relies on TCP and UDP unicast. Broadcast and Multicast are rarely available in a multi-tenant or cloud network environment. For that reason, Consul and Serf were both designed to avoid any dependence on those capabilities. From 09735ec72fbb92188fa3f71d232888605eaa2403 Mon Sep 17 00:00:00 2001 From: Lens0021 / Leslie Date: Tue, 8 Oct 2024 03:52:46 +0900 Subject: [PATCH 18/97] docs: Add missing `&&` in DNS forwading tutorial (#21804) Add missing `&&` to iptables command. The original commands fail when being directly pasted into a shell. --- .../content/docs/services/discovery/dns-forwarding/enable.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/content/docs/services/discovery/dns-forwarding/enable.mdx b/website/content/docs/services/discovery/dns-forwarding/enable.mdx index b165c2c8fa37..e7def0b4bc25 100644 --- a/website/content/docs/services/discovery/dns-forwarding/enable.mdx +++ b/website/content/docs/services/discovery/dns-forwarding/enable.mdx @@ -66,7 +66,7 @@ When using the Consul Docker image, add the following to the environment to allo To avoid running Consul as a privileged user, the following `iptables` commands are sufficient to map port `53` to `8600` and redirect DNS queries to Consul. ```shell-session -# iptables --table nat --append OUTPUT --destination localhost --protocol udp --match udp --dport 53 --jump REDIRECT --to-ports 8600 \ +# iptables --table nat --append OUTPUT --destination localhost --protocol udp --match udp --dport 53 --jump REDIRECT --to-ports 8600 && \ iptables --table nat --append OUTPUT --destination localhost --protocol tcp --match tcp --dport 53 --jump REDIRECT --to-ports 8600 ``` @@ -417,4 +417,4 @@ This instructions on this page helped you configure your node to forward DNS req To learn more on how to query Consul DNS once forwarding is enabled, refer to [DNS forwarding workflow](/consul/docs/services/discovery/dns-forwarding#workflow). -For more information on other DNS features and configurations available in Consul, refer to [DNS usage overview](/consul/docs/services/discovery/dns-overview). \ No newline at end of file +For more information on other DNS features and configurations available in Consul, refer to [DNS usage overview](/consul/docs/services/discovery/dns-overview). From 738acfee1a759e5ca2fb625e8644ccf72a6b9e0c Mon Sep 17 00:00:00 2001 From: Yasmin Lorin Kaygalak Date: Wed, 9 Oct 2024 13:30:28 -0400 Subject: [PATCH 19/97] Adds grafana dashboards (#21806) --- .changelog/21806.txt | 3 + grafana/README.md | 15 - grafana/consuldataplanedashboard.json | 1453 +++++++++++++ grafana/consulservicedashboard.json | 1513 ++++++++++++++ grafana/consulservicetoservicedashboard.json | 1921 ++++++++++++++++++ 5 files changed, 4890 insertions(+), 15 deletions(-) create mode 100644 .changelog/21806.txt delete mode 100644 grafana/README.md create mode 100644 grafana/consuldataplanedashboard.json create mode 100644 grafana/consulservicedashboard.json create mode 100644 grafana/consulservicetoservicedashboard.json diff --git a/.changelog/21806.txt b/.changelog/21806.txt new file mode 100644 index 000000000000..0f47c49bd9bf --- /dev/null +++ b/.changelog/21806.txt @@ -0,0 +1,3 @@ +```release-note:feature +grafana: added the dashboards service-to-service dashboard, service dashboard, and consul dataplane dashboard +``` diff --git a/grafana/README.md b/grafana/README.md deleted file mode 100644 index 2e8b2b588b75..000000000000 --- a/grafana/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Grafana Publishing - -The page for publishing this dashboard is https://grafana.com/grafana/dashboards/13396 - -## How to edit and Publish - - Start grafana locally (consul-docker-test/mesh-gateways-l7 will provide you two Consul DCs, grafana, and prometheus)_ - - Import the dashboard json into a new dashboard - - Make changes - - Click "share" and export for external publishing - - Login to Grafana via the team account (message a manager) - - Publish as a new version, including change notes. - -### Grafana dashboard for consul-k8s (control plane) - -A grafana dashboard for monitoring consul-k8s (control plane) can also be found in this directory: `consul-k8s-control-plane-monitoring.json`. This dashboard has not been published to https://grafana.com. diff --git a/grafana/consuldataplanedashboard.json b/grafana/consuldataplanedashboard.json new file mode 100644 index 000000000000..e8b6278bc4b3 --- /dev/null +++ b/grafana/consuldataplanedashboard.json @@ -0,0 +1,1453 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Envoy proxy monitoring Dashboard with cluster and service level templates. ", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 11021, + "graphTooltip": 0, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 3, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 1 + }, + { + "color": "#299c46", + "value": 2 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 9, + "maxDataPoints": 100, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(envoy_server_live{app=~\"$service\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Live servers", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 70, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!=\"5\", envoy_response_code_class!=\"4\",consul_destination_service=~\"$service\"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~\"$service\"}[10m])) ", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Request Success Rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [] + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 68, + "options": { + "displayLabels": [ + "name", + "value" + ], + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "values": [ + "value" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(increase(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~\"4|5\", consul_destination_service=~\"$service\"}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "{{consul_destination_service}}", + "refId": "A" + } + ], + "title": "Total Failed Requests", + "type": "piechart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 7 + }, + "id": 64, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "value_and_name", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(envoy_http_downstream_rq_total{service=~\"$service\",envoy_http_conn_manager_prefix=\"public_listener\"}[5m])) by (service)", + "hide": false, + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Requests / sec", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 5, + "y": 7 + }, + "id": 19, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "(sum(envoy_cluster_membership_healthy{app=~\"$service\",envoy_cluster_name=~\"$cluster\"}) - sum(envoy_cluster_membership_total{app=~\"$service\",envoy_cluster_name=~\"$cluster\"}))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Unhealthy Clusters", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 32 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 7 + }, + "id": 58, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "titleSize": 12 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by (app) (envoy_cluster_upstream_cx_active{app=~\"$service\",envoy_cluster_name!~\"consul-dataplane|prometheus.*|local_app|original-.*\"})", + "instant": true, + "interval": "", + "legendFormat": "{{envoy_cluster_name}}", + "range": false, + "refId": "A" + } + ], + "title": "Connections ( $service)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 2, + "x": 16, + "y": 7 + }, + "id": 13, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "SUM(envoy_server_memory_heap_size{app=~\"$service\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Heap Size", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 18, + "y": 7 + }, + "id": 11, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "SUM(envoy_server_memory_allocated{app=~\"$service\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Allocated Memory", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 21, + "y": 7 + }, + "id": 12, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "avg(envoy_server_uptime{app=~\"$service\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Avg uptime per node", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "text": "NOT WELL" + }, + "1": { + "text": "OK" + } + }, + "type": "value" + }, + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#299c46", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 5, + "y": 10 + }, + "id": 20, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "(sum(envoy_cluster_membership_total{app=~\"$service\",envoy_cluster_name=~\"$cluster\"})-sum(envoy_cluster_membership_healthy{app=~\"$service\",envoy_cluster_name=~\"$cluster\"})) == bool 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Cluster State", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 0.00001 + }, + { + "color": "red", + "value": 0.00002 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 20, + "x": 0, + "y": 13 + }, + "id": 18, + "options": { + "legend": { + "calcs": [ + "last" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\"}[5m])", + "interval": "", + "legendFormat": "{{pod}}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Throttled Seconds by Namespace", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 2, + "x": 20, + "y": 13 + }, + "id": 49, + "options": { + "displayMode": "gradient", + "maxVizHeight": 300, + "minVizHeight": 10, + "minVizWidth": 0, + "namePlacement": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "100 * max (container_memory_working_set_bytes{namespace=~\"$namespace\"} / on(container, pod) label_replace(kube_pod_container_resource_limits{resource=\"memory\"}, \"pod\", \"$1\", \"exported_pod\", \"(.+)\")) by (pod)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Mem Usage % by pod limits", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 2, + "x": 22, + "y": 13 + }, + "id": 28, + "options": { + "displayMode": "gradient", + "maxVizHeight": 300, + "minVizHeight": 10, + "minVizWidth": 0, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "100 * max(\n container_memory_working_set_bytes{namespace=~\"$namespace\"} / \n on(container, pod) label_replace(kube_pod_container_resource_limits{resource=\"memory\"}, \"pod\", \"$1\", \"exported_pod\", \"(.+)\")\n) by (pod)\n\n", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "CPU Usage % by pod limits", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 3, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(envoy_cluster_upstream_cx_active{app=~\"$service\",envoy_cluster_name=~\"$cluster\"}) by (app, envoy_cluster_name)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{envoy_cluster_name}} ({{service}})", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "exemplar": true, + "expr": "sum(envoy_cluster_upstream_cx_active{app=~\"$service\"}) by (app)", + "hide": true, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Total Active Upstream Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 7, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(envoy_http_downstream_cx_active{app=~\"$service\"}) by (app)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{service}}", + "refId": "A" + } + ], + "title": "Total Active Downstream Connections", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "PBFA97CFB590B2093" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "definition": "label_values(envoy_server_live, app)", + "hide": 0, + "includeAll": true, + "label": "", + "multi": true, + "name": "service", + "options": [], + "query": { + "query": "label_values(envoy_server_live, app)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "definition": "label_values(envoy_cluster_upstream_cx_total{service=~\"$service\"}, envoy_cluster_name)", + "hide": 0, + "includeAll": true, + "label": "Cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(envoy_cluster_upstream_cx_total{service=~\"$service\"}, envoy_cluster_name)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(container_memory_working_set_bytes, namespace)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(container_memory_working_set_bytes, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Consul DataPlane Dashboard", + "uid": "hashicupso", + "version": 4, + "weekStart": "" +} \ No newline at end of file diff --git a/grafana/consulservicedashboard.json b/grafana/consulservicedashboard.json new file mode 100644 index 000000000000..785b17ed26b4 --- /dev/null +++ b/grafana/consulservicedashboard.json @@ -0,0 +1,1513 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Envoy proxy monitoring Dashboard with cluster and service level templates. ", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 11021, + "graphTooltip": 0, + "id": 2, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 103, + "panels": [], + "title": "Overall Service Mesh Performance", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "#EAB839", + "value": 5 + }, + { + "color": "green", + "value": 6 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 65, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(envoy_server_live{app!=\"traffic-generator\"})", + "instant": false, + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Total Running Services", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 1 + }, + "id": 89, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!=\"5\", envoy_response_code_class!=\"4\",consul_destination_service=~\"$service\"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~\"$service\"}[10m])) ", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Request Success Rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 93, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~\"4|5\", consul_destination_service=~\"$service\"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~\"$service\"}[10m]))", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Failed Request Rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 95, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_cluster_upstream_rq_time_sum{consul_destination_service=~\"$service\"}[10m])) / sum(rate(envoy_cluster_upstream_rq_total{consul_destination_service=~\"$service\"}[10m]))", + "hide": false, + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "1000 * (sum(rate(envoy_cluster_upstream_rq_time_sum{consul_destination_service=~\"$service\"}[10m])) / sum(rate(envoy_cluster_upstream_rq_total{consul_destination_service=~\"$service\"}[10m])))", + "hide": true, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Average Request Response Time In MiliSeconds", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 10 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 91, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(increase(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~\"4|5\", consul_destination_service=~\"$service\"}[10m]))by(local_cluster)", + "interval": "", + "legendFormat": "{{consul_destination_service}}", + "refId": "A" + } + ], + "title": "Total Failed Requests", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 5 + }, + { + "color": "orange", + "value": 8 + }, + { + "color": "semi-dark-green", + "value": 10 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 31, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "vertical", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "value_and_name", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.50, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~\"$namespace\" , local_cluster=~\"$service\"}[5m])))\n", + "hide": false, + "interval": "", + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.75, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~\"$namespace\", local_cluster=~\"$service\"}[5m])))", + "hide": false, + "interval": "", + "legendFormat": "p75", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.90, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~\"$namespace\", local_cluster=~\"$service\"}[5m])))", + "hide": false, + "interval": "", + "legendFormat": "p90", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(.999, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~\"$namespace\", local_cluster=~\"$service\"}[5m])))", + "hide": false, + "interval": "", + "legendFormat": "p99.9", + "range": true, + "refId": "D" + } + ], + "title": "Dataplane Latency: $service ", + "transparent": true, + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 102, + "panels": [], + "title": "TCP Metrics: High Level", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 0, + "y": 18 + }, + "id": 99, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_rx_bytes_total{}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_tx_bytes_total{}[10m])) by (local_cluster)", + "hide": false, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Total TCP Inbound and Outbound Bytes", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 8, + "y": 18 + }, + "id": 101, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_rx_bytes_buffered{}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_tx_bytes_buffered{}[10m])) by (local_cluster)", + "hide": false, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Total TCP Inbound and Outbound Bytes Buffered", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 16, + "y": 18 + }, + "id": 81, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_total{}[10m])) by(local_cluster)", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total TCP Downstream Active Connections", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 77, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "Service Dashboard", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 71, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(envoy_cluster_upstream_cx_active{app=~\"$service\"}) by (app)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{service}}", + "range": true, + "refId": "A" + } + ], + "title": "Total Active Http Upstream Connections", + "transformations": [ + { + "id": "calculateField", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 75, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(envoy_http_downstream_cx_active{app=~\"$service\"}) by (app)", + "interval": "", + "legendFormat": "{{service}}", + "refId": "A" + } + ], + "title": "Total Active Http Downstream Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 41, + "options": { + "legend": { + "calcs": [ + "last", + "sum" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by(namespace,app,envoy_response_code_class) (rate(envoy_cluster_upstream_rq_xx[5m]))", + "interval": "", + "legendFormat": "{{namespace}} : {{app}}-{{envoy_response_code_class}}xx", + "range": true, + "refId": "A" + } + ], + "title": "Upstream Rq by Status Code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 51, + "options": { + "legend": { + "calcs": [ + "last", + "sum" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "sum(rate(envoy_http_downstream_rq_xx{envoy_http_conn_manager_prefix=\"public_listener\"}[5m])) by (namespace, app,envoy_response_code_class)\n", + "legendFormat": "{{namespace}} : {{app}}-{{envoy_response_code_class}}xx", + "range": true, + "refId": "A" + } + ], + "title": "Downstream Rq by Status Code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 47 + }, + "id": 61, + "options": { + "legend": { + "calcs": [ + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(envoy_listener_downstream_cx_overload_reject{}[$__interval])", + "hide": false, + "instant": false, + "interval": "3m", + "legendFormat": "{{namespace}} : {{consul_source_service}}-{{envoy_listener_address}}-overload", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "rate(envoy_listener_downstream_global_cx_overflow{}[$__interval])", + "hide": false, + "interval": "3m", + "legendFormat": "{{namespace}} : {{consul_source_service}}-{{envoy_listener_address}}-overflow", + "range": true, + "refId": "B" + } + ], + "title": "Connections Rejected", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "PBFA97CFB590B2093" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "definition": "label_values(envoy_server_live, consul_source_service)", + "hide": 0, + "includeAll": true, + "label": "", + "multi": true, + "name": "service", + "options": [], + "query": { + "query": "label_values(envoy_server_live, consul_source_service)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(container_memory_working_set_bytes, namespace)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(container_memory_working_set_bytes, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Consul Service Dashboard", + "uid": "hashicupsnm", + "version": 8, + "weekStart": "" +} \ No newline at end of file diff --git a/grafana/consulservicetoservicedashboard.json b/grafana/consulservicetoservicedashboard.json new file mode 100644 index 000000000000..fe452d8c564e --- /dev/null +++ b/grafana/consulservicetoservicedashboard.json @@ -0,0 +1,1921 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 3, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 34, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "Access Logs and Errors Monitoring", + "type": "row" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "description": "Total Count of log lines in the specified time range", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "rgb(31, 255, 7)", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "green", + "value": 10 + }, + { + "color": "green", + "value": 50 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "code", + "expr": "sum(count_over_time(({container=\"consul-dataplane\",namespace=~\"$namespace\"})[$__interval]))", + "hide": false, + "queryType": "range", + "refId": "A" + } + ], + "title": "Total Logs", + "type": "stat" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "description": "Total count of logs containing the search filter term in the specified time range", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "rgb(222, 15, 43)", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "red", + "value": 10 + }, + { + "color": "red", + "value": 50 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 8, + "y": 1 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "code", + "expr": "sum(count_over_time({container=\"consul-dataplane\", namespace=~\"$namespace\"} |~ `(?i)(?i)$searchable_pattern` [$__interval]))", + "hide": false, + "queryType": "range", + "refId": "A" + } + ], + "title": "Total Logs Containing \"$searchable_pattern\"", + "type": "stat" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "description": "Percentage of logs containing the search filter term in the specified time range", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "#299c46", + "text": "0" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 14, + "maxDataPoints": 1, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "builder", + "expr": "(sum(count_over_time({container=\"consul-dataplane\", namespace=~\"$namespace\"} |~ `(?i)(?i)$searchable_pattern` [$__interval])) * 100) / sum(count_over_time({container=\"consul-dataplane\", namespace=~\"$namespace\"} [$__interval]))", + "hide": false, + "queryType": "range", + "refId": "A" + } + ], + "title": "Percentage of Logs Containing \"$searchable_pattern\"", + "type": "stat" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [] + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 4 + }, + "id": 4, + "maxDataPoints": 1, + "options": { + "displayLabels": [ + "percent" + ], + "legend": { + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "code", + "expr": "sum by(response_code) (count_over_time({container=\"consul-dataplane\", namespace=\"$namespace\"} | json | response_code != `0` | __error__=`` [$__range]))", + "key": "Q-aac7d4c8-664f-43c0-8064-9f737ce3e78e-0", + "legendFormat": "{{response_code}}", + "queryType": "range", + "refId": "A" + } + ], + "title": "Total Response Code Distribution", + "type": "piechart" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 15, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 4 + }, + "id": 16, + "maxDataPoints": 100, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "builder", + "expr": "sum by(app) (rate({container=\"consul-dataplane\", namespace=~\"$namespace\"} |~ `(?i)(?i)$searchable_pattern` [$__range]))", + "hide": false, + "legendFormat": "{{pod}}", + "queryType": "range", + "refId": "A" + } + ], + "title": "Rate of Logs Containing \"$searchable_pattern\" per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 4 + }, + "id": 15, + "interval": "1m", + "maxDataPoints": 1, + "options": { + "displayLabels": [ + "value" + ], + "legend": { + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "builder", + "expr": "sum by(app) (count_over_time({container=\"consul-dataplane\", namespace=~\"$namespace\"} |~ `(?i)(?i)$searchable_pattern` [$__interval]))", + "legendFormat": "{{pod}}", + "queryType": "instant", + "refId": "A" + } + ], + "title": "Total Logs Containing \"$searchable_pattern\" by Service", + "type": "piechart" + }, + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 26, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "TCP Metrics: Service Level", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 0, + "y": 11 + }, + "id": 38, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_rx_bytes_total{}[10m])) by (service, destination_service)", + "interval": "", + "legendFormat": "$source_service", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_tx_bytes_total{}[10m])) by (service, destination_service)", + "hide": false, + "interval": "", + "legendFormat": "$destination_service", + "refId": "B" + } + ], + "title": "TCP Inbound and Outbound Bytes: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 8, + "y": 11 + }, + "id": 40, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_rx_bytes_buffered{}[10m])) by (service, destination_service)", + "interval": "", + "legendFormat": "$source_service", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_tx_bytes_buffered{}[10m])) by (service, destination_service)", + "hide": false, + "interval": "", + "legendFormat": "$destination_service", + "range": true, + "refId": "B" + } + ], + "title": "TCP Inbound and Outbound Bytes Buffered: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 16, + "y": 11 + }, + "id": 28, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(envoy_tcp_downstream_cx_total) by (service, destination_service)", + "hide": false, + "interval": "", + "legendFormat": "$source_service ", + "range": true, + "refId": "A" + } + ], + "title": "TCP Downstream Connections: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 41, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "Outbound Traffic Monitoring", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_total{local_cluster=~\"$source_service\",\nconsul_destination_service=~\"$destination_service\"}[10m])) by ( local_cluster, consul_destination_service)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Upstream Traffic: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{local_cluster=~\"$source_service\",consul_destination_target!=\"\"}[10m])) by (le, consul_destination_target))", + "interval": "", + "legendFormat": "{{consul_destination_target}}", + "refId": "A" + } + ], + "title": "Upstream Request Response Timeliness: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!=\"5\",local_cluster=~\"$source_service\",\nconsul_destination_service=~\"$destination_service\"}[10m])) by (local_cluster, consul_destination_service) / sum(irate(envoy_cluster_upstream_rq_xx{local_cluster=~\"$source_service\",consul_destination_service=~\"$destination_service\"}[10m])) by (local_cluster,consul_destination_service)\n", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Upstream Request Success Rate: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 42, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "Inbound Traffic Monitoring", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_total{consul_destination_datacenter=\"dc1\", local_cluster=~\"$source_service\",\nconsul_destination_service=~\"$destination_service\"}[10m])) by (consul_destination_service, local_cluster)\n", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Requests Sent: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 43, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!=\"5\", local_cluster=~\"$source_service\", consul_destination_service=~\"$destination_service\"}[10m])) by (local_cluster, consul_destination_service) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~\"$destination_service\"}[10m])) by (local_cluster , consul_destination_service)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Request Success Rate: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 50 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(envoy_http_downstream_rq_xx{local_cluster=~\"$source_service\", envoy_http_conn_manager_prefix=\"public_listener\"}[10m])) by (local_cluster, envoy_response_code_class)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Response Success by Status Code: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 50 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{consul_destination_datacenter=\"dc1\", consul_destination_service=~\"$destination_service\",local_cluster=~\"$source_service\"}[10m])) by (le, cluster, local_cluster, consul_destination_service))", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Request Duration: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(envoy_http_downstream_rq_total{local_cluster=~\"$source_service\", envoy_http_conn_manager_prefix=\"public_listener\"}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Response Success: $source_service ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(irate(envoy_http_downstream_rq_total{local_cluster=~\"$source_service\",envoy_http_conn_manager_prefix=\"public_listener\"}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Request Response Rate: $source_service", + "type": "stat" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "PBFA97CFB590B2093" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(envoy_server_live, consul_source_service)", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "source_service", + "options": [], + "query": { + "query": "label_values(envoy_server_live, consul_source_service)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(envoy_cluster_upstream_rq_total, consul_destination_service)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "destination_service", + "options": [], + "query": { + "query": "label_values(envoy_cluster_upstream_rq_total, consul_destination_service)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "definition": "label_values(namespace)", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "namespace", + "options": [], + "query": "label_values(namespace)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "hide": 0, + "label": "Search (case insensitive)", + "name": "searchable_pattern", + "options": [ + { + "selected": true, + "text": "\"response_code\":200", + "value": "\"response_code\":200" + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Consul Service_To_Service Dashboard", + "uid": "qTEWJ0XSkm", + "version": 8, + "weekStart": "" +} \ No newline at end of file From eda961f4a2a04f951d15a5a3a73bf75a73c0e649 Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Fri, 11 Oct 2024 17:12:48 -0400 Subject: [PATCH 20/97] Upgrade test improvements for 1.20.x (#21813) * Bump Envoy version used for 1.20.x upgrade tests * Improve README + docstrings --- .../nightly-test-integrations-1.20.x.yml | 2 +- .../consul-container/test/upgrade/README.md | 26 ++++++++++++------- .../test/upgrade/peering/peering_http_test.go | 4 ++- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.github/workflows/nightly-test-integrations-1.20.x.yml b/.github/workflows/nightly-test-integrations-1.20.x.yml index a1dd9169f3a4..2687ea6992b9 100644 --- a/.github/workflows/nightly-test-integrations-1.20.x.yml +++ b/.github/workflows/nightly-test-integrations-1.20.x.yml @@ -241,7 +241,7 @@ jobs: # matrix.consul-version (i.e. whenever the highest common Envoy version across active # Consul versions changes). The minor Envoy version does not necessarily need to be # kept current for the purpose of these tests, but the major (1.N) version should be. - ENVOY_VERSION: 1.27.6 + ENVOY_VERSION: 1.28.7 steps: - name: Checkout code uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 diff --git a/test/integration/consul-container/test/upgrade/README.md b/test/integration/consul-container/test/upgrade/README.md index 598bdfab3480..0577cf7ba59e 100644 --- a/test/integration/consul-container/test/upgrade/README.md +++ b/test/integration/consul-container/test/upgrade/README.md @@ -12,9 +12,11 @@ ## Introduction -The goal of upgrade tests is to ensure problem-free upgrades on supported upgrade paths. At any given time, Consul supports the latest minor release, and two older minor releases, e.g. 1.15, 1.14, and 1.13. Upgrades to any higher version are permitted, including skipping a minor version e.g. from 1.13 to 1.15. +The goal of upgrade tests is to ensure problem-free upgrades on supported upgrade paths. +At any given time, Consul supports the latest minor release, and two older minor releases, e.g. 1.15, 1.14, and 1.13. +Upgrades to any higher version are permitted, including skipping a minor version e.g. from 1.13 to 1.15. -The upgrade tests also aims to highlight errors that may occur as users attempt to upgrade their current version to a newer version. +The upgrade tests also aim to highlight errors that may occur as users attempt to upgrade their current version to a newer version. ### How it works @@ -49,7 +51,13 @@ To run the upgrade test, the following tools are required: ### Running Upgrade integration tests - run `make dev-docker` -- build a consul-envoy container image `cd test/integration/consul-container docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/consul:1.15 --build-arg ENVOY_VERSION=1.24.6 -f ./assets/Dockerfile-consul-envoy ./assets` +- build a consul-envoy container image + ```shell + cd test/integration/consul-container + docker build -t consul-envoy:latest-version \ + --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/consul:1.20.0-rc1 \ + --build-arg ENVOY_VERSION=1.31.2 -f ./assets/Dockerfile-consul-envoy ./assets + ``` - run the single test `go test -v -timeout 30m -run ^TestACL_Upgrade_Node_Token$ ./.../upgrade/` - run all upgrade tests `go test -v -timeout 30m -run ./.../upgrade` @@ -66,13 +74,13 @@ this makes it hard to debug, when the test case creates many containers. To disable following container logs, run the test with `-follow-log false`. Below are the supported CLI options -| Flags | Default value | Description | +| Flags | Default value | Description | | ----------- | ----------- | ----------- | -| --latest-image | `consul` in CE, `hashicorp/consulenterprise` in ENT | Name of the Docker image to deploy initially. -| --latest-version | latest | Tag of the Docker image to deploy initially. -| --target-image | `consul` in Ce, `hashicorp/consulenterprise` in ENT | Name of the Docker image to upgrade to. -| --target-version | local | Tag of the Docker image to upgrade to. `local` is the tag built by `make dev-docker` above. -| -follow-log | true | Emit all container logs. These can be noisy, so we recommend `--follow-log=false` for local development. +| --latest-image | `consul` in CE, `hashicorp/consulenterprise` in ENT | Name of the Docker image to deploy initially. +| --latest-version | latest | Tag of the Docker image to deploy initially. +| --target-image | `consul` in Ce, `hashicorp/consulenterprise` in ENT | Name of the Docker image to upgrade to. +| --target-version | local | Tag of the Docker image to upgrade to. `local` is the tag built by `make dev-docker` above. +| -follow-log | true | Emit all container logs. These can be noisy, so we recommend `--follow-log=false` for local development. ## Adding a new upgrade integration test diff --git a/test/integration/consul-container/test/upgrade/peering/peering_http_test.go b/test/integration/consul-container/test/upgrade/peering/peering_http_test.go index 9c48727d83a6..a329fabfe324 100644 --- a/test/integration/consul-container/test/upgrade/peering/peering_http_test.go +++ b/test/integration/consul-container/test/upgrade/peering/peering_http_test.go @@ -95,7 +95,7 @@ func TestPeering_HTTPRouter(t *testing.T) { } // Verify resolver and failover can direct traffic to server in peered cluster -// In addtional to the basic topology, this case provisions the following +// In addition to the basic topology, this case provisions the following // services in the dialing cluster: // // - a new static-client at server_0 that has two upstreams: static-server (5000) @@ -313,6 +313,8 @@ func TestPeering_HTTPResolverAndSplitter(t *testing.T) { // TODO: restart static-server-2's sidecar } +// peeringUpgrade upgrades the accepting cluster, verifies that peering is still active, +// and then upgrades the dialing cluster and verifies that peering is still active. func peeringUpgrade(t *testing.T, accepting, dialing *libtopology.BuiltCluster, targetVersion string) { t.Helper() From 4275e8fa82b3b54ee1ed04373fa8a659cce2e484 Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Mon, 14 Oct 2024 12:52:22 -0400 Subject: [PATCH 21/97] Update ENVOY_VERSIONS (#21820) No new minor versions, just incrementing the patches for hygiene's sake --- envoyextensions/xdscommon/ENVOY_VERSIONS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/envoyextensions/xdscommon/ENVOY_VERSIONS b/envoyextensions/xdscommon/ENVOY_VERSIONS index 264a0d56cfe8..884f30573206 100644 --- a/envoyextensions/xdscommon/ENVOY_VERSIONS +++ b/envoyextensions/xdscommon/ENVOY_VERSIONS @@ -8,7 +8,7 @@ # # See https://www.consul.io/docs/connect/proxies/envoy#supported-versions for more information on Consul's Envoy # version support. -1.31.0 -1.30.4 -1.29.7 -1.28.5 \ No newline at end of file +1.31.2 +1.30.6 +1.29.9 +1.28.7 From 1648c890dd83ef459ebbaabb72ae6a91f7e3d8be Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Mon, 14 Oct 2024 15:02:29 -0400 Subject: [PATCH 22/97] ci: ensure int test docker pull goes through proxy (#21819) --- .github/workflows/test-integrations.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-integrations.yml b/.github/workflows/test-integrations.yml index f5d8e30eca2e..ba4eecdf4210 100644 --- a/.github/workflows/test-integrations.yml +++ b/.github/workflows/test-integrations.yml @@ -412,7 +412,7 @@ jobs: env: ENVOY_VERSION: ${{ needs.get-envoy-versions.outputs.max-envoy-version }} #TODO don't harcode this image name - CONSUL_DATAPLANE_IMAGE: "docker.io/hashicorppreview/consul-dataplane:1.6-dev-ubi" + CONSUL_DATAPLANE_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-dataplane:1.6-dev-ubi" steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. From 8f78d7cafd7c21ccd6ec551164ea9d0fb79141e0 Mon Sep 17 00:00:00 2001 From: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:38:23 -0700 Subject: [PATCH 23/97] docs: Consul DNS views on Kubernetes (#21802) * Backport of ci: update the security-scanner gha token into release/1.20.x (#21754) backport of commit eb9dbc93f88e8b87d60ed55101a577e49e9299e4 Co-authored-by: dduzgun-security * Backport of Initialize 1.20 Release into release/1.20.x (#21753) * backport of commit a33e903cdf367c9be90b61464aee97fdd4294fd9 * backport of commit 37163dc1a81abb4ba88c18c204ccca5ee61dae5d * backport of commit 38f0907c7a9f4851080bdec3bb182f1b9e5bed1e * backport of commit 6ab7ec254b51e6f5012688f8fff3d36a33e8ee57 * backport of commit 7ac4178186a22d1e11cdf0ef69c00a658a6484d0 * backport of commit 5dfebb2cf3a46d3c8a96881b5ab77bd0ff23f5c0 * backport of commit 316d68cb847193f184d3a54fc103996151d1d68a --------- Co-authored-by: Sarah Alsmiller Co-authored-by: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> * Backport of Stage rc release into release/1.20.x (#21772) backport of commit d311f2b63836e1cae1b342f6b0fc07ff69e93f6c Co-authored-by: Sarah Alsmiller * Backport of Upgrade ubi image to 9.4 into release/1.20.x (#21773) * backport of commit 888e302f6e87f27d0c8a0c6facfd6c3a6c8033c5 * backport of commit 17499dc4dcca4aa6f67b3f95bd24b433cd32556b * backport of commit d933d3727d1ddf4566d0ee7612e3a64029034314 --------- Co-authored-by: Dhia Ayachi Co-authored-by: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> * Backport of security: update alpine base image to 3.20 into release/1.20.x (#21774) * backport of commit 4421ce1677605ae118f741f4251fce65faa8ff87 * Upgrade ubi image to 9.4 (#21750) --------- Co-authored-by: Michael Zalimeni Co-authored-by: Sarah Alsmiller Co-authored-by: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> * Backport of fix spacing of bash scripts into release/1.20.x (#21769) * backport of commit 1e97297215f985e153dd4e92c4444acebbfce0db * backport of commit b7053f53617fec902a7bf07ebb3b8077334a5cdb * backport of commit a391f2fa3ce1eb250e5c10546cc1459b5649e587 --------- Co-authored-by: jm96441n * Backport of [NET-11150] ci: fix conditional skip and add safeguard into release/1.20.x (#21783) backport of commit c3db6c90013eaa3f4a03d2d06ffea2eb9df3698f Co-authored-by: Michael Zalimeni * initial commit * Initial pages * Edits to other pages + nav & redirects * minor fixes * Backport of security: update alpine base image to 3.20 into release/1.20.x (#21774) * backport of commit 4421ce1677605ae118f741f4251fce65faa8ff87 * Upgrade ubi image to 9.4 (#21750) --------- Co-authored-by: Michael Zalimeni Co-authored-by: Sarah Alsmiller Co-authored-by: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> * CE-679 * align with main * Content updates * minor edit * Apply suggestions from code review Co-authored-by: Aimee Ukasick Co-authored-by: Blake Covarrubias * CoreDNS config update * small edits * typo fix --------- Co-authored-by: hc-github-team-consul-core Co-authored-by: dduzgun-security Co-authored-by: Sarah Alsmiller Co-authored-by: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> Co-authored-by: Dhia Ayachi Co-authored-by: Michael Zalimeni Co-authored-by: jm96441n Co-authored-by: Aimee Ukasick Co-authored-by: Blake Covarrubias --- consul-k8s | 1 + version/VERSION | 2 +- .../docs/k8s/{dns.mdx => dns/enable.mdx} | 7 +- website/content/docs/k8s/dns/views/enable.mdx | 102 ++++++++++++++++++ website/content/docs/k8s/dns/views/index.mdx | 48 +++++++++ .../docs/services/discovery/dns-cache.mdx | 27 +++-- .../discovery/dns-forwarding/index.mdx | 5 +- .../docs/services/discovery/dns-overview.mdx | 15 ++- website/data/docs-nav-data.json | 20 +++- website/redirects.js | 10 ++ 10 files changed, 220 insertions(+), 17 deletions(-) create mode 160000 consul-k8s rename website/content/docs/k8s/{dns.mdx => dns/enable.mdx} (96%) create mode 100644 website/content/docs/k8s/dns/views/enable.mdx create mode 100644 website/content/docs/k8s/dns/views/index.mdx diff --git a/consul-k8s b/consul-k8s new file mode 160000 index 000000000000..0d85bbc3131c --- /dev/null +++ b/consul-k8s @@ -0,0 +1 @@ +Subproject commit 0d85bbc3131ce8be23c57e30b213ba6056623976 diff --git a/version/VERSION b/version/VERSION index c6ba48dc6375..b148ac3829b7 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.21.0-dev +1.21.0-dev \ No newline at end of file diff --git a/website/content/docs/k8s/dns.mdx b/website/content/docs/k8s/dns/enable.mdx similarity index 96% rename from website/content/docs/k8s/dns.mdx rename to website/content/docs/k8s/dns/enable.mdx index 8e713a86e183..708ca9241c26 100644 --- a/website/content/docs/k8s/dns.mdx +++ b/website/content/docs/k8s/dns/enable.mdx @@ -5,16 +5,15 @@ description: >- Use a k8s ConfigMap to configure KubeDNS or CoreDNS so that you can use Consul's `.service.consul` syntax for queries and other DNS requests. In Kubernetes, this process uses either stub-domain or proxy configuration. --- -# Resolve Consul DNS Requests in Kubernetes +# Resolve Consul DNS requests in Kubernetes -One of the primary query interfaces to Consul is the -[DNS interface](/consul/docs/services/discovery/dns-overview). You can configure Consul DNS in +This topic describes how to configure Consul DNS in Kubernetes using a [stub-domain configuration](https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#configure-stub-domain-and-upstream-dns-servers) if using KubeDNS or a [proxy configuration](https://coredns.io/plugins/forward/) if using CoreDNS. Once configured, DNS requests in the form `.service.consul` will -resolve for services in Consul. This will work from all Kubernetes namespaces. +resolve for services in Consul. This works from all Kubernetes namespaces. -> **Note:** If you want requests to just `` (without the `.service.consul`) to resolve, then you'll need to turn on [Consul to Kubernetes Service Sync](/consul/docs/k8s/service-sync#consul-to-kubernetes). diff --git a/website/content/docs/k8s/dns/views/enable.mdx b/website/content/docs/k8s/dns/views/enable.mdx new file mode 100644 index 000000000000..3f29eac346c6 --- /dev/null +++ b/website/content/docs/k8s/dns/views/enable.mdx @@ -0,0 +1,102 @@ +--- +layout: docs +page_title: Enable Consul DNS proxy for Kubernetes +description: -> + Learn how to schedule a Consul DNS proxy for a Kubernetes Pod so that your services can return Consul DNS results for service discovery. +--- + +# Enable Consul DNS proxy for Kubernetes + +This page describes the process to deploy a Consul DNS proxy in a Kubernetes Pod so that Services can resolve Consul DNS requests. For more information, refer to [Consul DNS views for Kubernetes](/consul/docs/k8s/dns/views). + +## Prerequisites + +You must meet the following minimum application versions to enable the Consul DNS proxy for Kubernetes: + +- Consul v1.20.0 or higher +- Either Consul on Kubernetes or the Consul Helm chart, v1.6.0 or higher + +## Update Helm values + +To enable the Consul DNS proxy, add the required [Helm values](/consul/docs/k8s/helm) to your Consul on Kubernetes deployment. + +```yaml +connectInject: + enabled: true +dns: + enabled: true + proxy: true +``` + +### ACLs + +We recommend you create a dedicated [ACL token with DNS permissions](/consul/docs/security/acl/tokens/create/create-a-dns-token) for the Consul DNS proxy. The Consul DNS proxy requires these ACL permissions. + +```hcl +node_prefix "" { + policy = "read" +} + +service_prefix "" { + policy = "read" +} +``` + +You can manage ACL tokens with Consul on Kubernetes, or you can configure the DNS proxy to access a token stored in Kubernetes secret. To use a Kubernetes secret, add the following configuration to your Helm chart. + +```yaml +dns: + proxy: + aclToken: + secretName: + secretKey: +``` + +## Retrieve Consul DNS proxy's address + +To look up the IP address for the Consul DNS proxy in the Kubernetes Pod, run the following command. + +```shell-session +$ kubectl get services –-all-namespaces --selector="app=consul,component=dns-proxy" --output jsonpath='{.spec.clusterIP}' +10.96.148.46 +``` + +Use this address when you update the ConfigMap resource. + +## Update Kubernetes ConfigMap + +Create or update a [ConfigMap object in the Kubernetes cluster](https://kubernetes.io/docs/concepts/configuration/configmap/) so that Kubernetes forwards DNS requests with the `.consul` domain to the IP address of the Consul DNS proxy. + +The following example of a `coredns-custom` ConfigMap configures Kubernetes to forward Consul DNS requests in the cluster to the Consul DNS Proxy running on `10.96.148.46`. This resource modifies the CoreDNS without modifications to the original `Corefile`. + +```yaml +kind: ConfigMap +metadata: + name: coredns-custom + namespace: kube-system +data: + consul.server: | + consul:53 { + errors + cache 30 + forward . 10.96.148.46 + reload + } +``` + +After updating the DNS configuration, perform a rolling restart of the CoreDNS. + +```shell-session +kubectl -n kube-system rollout restart deployment coredns +``` + +For more information about using a `coredns-custom` resource, refer to the [Rewrite DNS guide in the Azure documentation](https://learn.microsoft.com/en-us/azure/aks/coredns-custom#rewrite-dns). For general information about modifying a ConfigMap, refer to [the Kubernetes documentation](https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#coredns). + +## Next steps + +After you enable the Consul DNS proxy, services in the Kubernetes cluster can resolve Consul DNS addresses. + +- To learn more about Consul DNS for service discovery, refer to [DNS usage overview](/consul/docs/services/discovery/dns-overview). +- If your datacenter has ACLs enabled, create a [Consul ACL token](/consul/docs/security/acl/tokens) for the Consul DNS proxy and then restart the DNS proxy. +- To enable service discovery across admin partitions, [export services between partitions](/consul/docs/connect/config-entries/exported-services). +- To use Consul DNS for service discovery with other runtimes, across cloud regions, or between cloud providers, [establish a cluster peering connection](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering). diff --git a/website/content/docs/k8s/dns/views/index.mdx b/website/content/docs/k8s/dns/views/index.mdx new file mode 100644 index 000000000000..7d482a9d3e84 --- /dev/null +++ b/website/content/docs/k8s/dns/views/index.mdx @@ -0,0 +1,48 @@ +--- +layout: docs +page_title: Consul DNS views for Kubernetes +description: -> + Kubernetes clusters can use the Consul DNS proxy to return service discovery results from the Consul catalog. Learn about how to configure your k8s cluster so that applications can resolve Consul DNS addresses without gossip communication. +--- + +# Consul DNS views for Kubernetes + +This topic describes how to schedule a dedicated Consul DNS proxy in a Kubernetes Pod so that applications in Kubernetes can resolve Consul DNS addresses. You can use the Consul DNS proxy to enable service discovery across admin partitions in Kubernetes deployments without needing to deploy Consul client agents. + +## Introduction + +Kubernetes operators typically choose networking tools such as [kube-dns](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) or [CoreDNS](https://kubernetes.io/docs/tasks/administer-cluster/coredns/) for their service discovery operations, and choose to bypass Consul DNS entirely. These DNS options are often sufficient for service networking operations within a single Kubernetes cluster. + +Consul on Kubernetes supports [configuring Kubernetes to resolve Consul DNS](/consul/docs/k8s/dns). However, two common challenges result when you rely on these configurations: + +- Kubernetes requires Consul to use gossip communication with agents or dataplanes in order to enable Consul DNS. +- Consul requires that admin partitions be included in the DNS address. Otherwise, DNS queries assume the `default` partition by default. + +The `consul-dns` proxy does not require the presence of Consul client agents or Consul dataplanes, removing gossip communication as a requirement for Consul DNS on Kubernetes. The proxy is also designed for deployment in a Kubernetes cluster with [external servers enabled](/consul/docs/k8s/deployment-configurations/servers-outside-kubernetes). When a cluster runs in a non-default admin partition and uses the proxy to query external servers, Consul automatically recognizes the admin partition that originated the request and returns service discovery results scoped to that specific admin partition. + +To use Consul DNS for service discovery on Kubernetes, deploy a `dns-proxy` service in each Kubernetes Pod that needs to resolve Consul DNS. Kubernetes sends all DNS requests to the Kubernetes controller first. The controller forwards requests for the `.consul` domain to the `dns-proxy` service, which then queries the Consul catalog and returns service discovery results. + +## Workflows + +The process to enable Consul DNS views for service discovery in Kubernetes deployments consists of the following steps: + +1. In a cluster configured to use [external Consul servers](/consul/docs/k8s/deployment-configurations/servers-outside-kubernetes), update the Helm values for your Consul on Kubernetes deployment so that `dns.proxy.enabled=true`. When you apply the updated configuration, Kubernetes deploys the Consul DNS proxy. +1. Look up the IP address for the Consul DNS proxy in the Kubernetes cluster. +1. Update the ConfigMap resource in the Kubernetes cluster so that it forwards requests for the `.consul` domain to the IP address of the Consul DNS proxy. + +For more information about the underlying concepts described in this workflow, refer to [DNS forwarding overview](/consul/docs/services/discovery/dns-forwarding). + +## Benefits + +Consul on Kubernetes currently uses [Consul dataplanes](/consul/docs/connect/dataplane) by default. These lightweight processes provide Consul access to the sidecar proxies in the service mesh, but leave Kubernetes in charge of most other service discovery and service mesh operations. + +- **Use Kubernetes DNS and Consul DNS in a single deployment**. The Consul DNS proxy enables any application in a Pod to resolve an address through Consul DNS without disrupting the underlying Kubernetes DNS functionality. +- **Consul service discovery using fewer resources**. When you use the Consul DNS proxy for service discovery, you do not need to schedule Consul client agents or dataplanes as sidecars. One Kubernetes Service that uses the same resources as a single Consul dataplane provides Pods access to the Consul service catalog. +- **Consul DNS without gossip communication**. The Consul DNS service runs on both Consul server and Consul client agents, which use [gossip communication](/consul/docs/security/encryption/gossip) to ensure that service discovery results are up-to-date. The Consul DNS proxy provides access to Consul DNS without the security overhead of agent-to-agent gossip. + +## Constraints and limitations + +If you experience issues using the Consul DNS proxy for Kubernetes, refer to the following list of technical constraints and limitations. + +- You must use Kubernetes as your runtime to use the Consul DNS proxy. You cannot schedule the Consul DNS proxy in other container-based environments. +- To perform DNS lookups on other admin partitions, you must [export services between partitions](/consul/docs/connect/config-entries/exported-services) before you can query them. \ No newline at end of file diff --git a/website/content/docs/services/discovery/dns-cache.mdx b/website/content/docs/services/discovery/dns-cache.mdx index daf85846252e..68b531d1b699 100644 --- a/website/content/docs/services/discovery/dns-cache.mdx +++ b/website/content/docs/services/discovery/dns-cache.mdx @@ -1,22 +1,33 @@ --- layout: docs -page_title: Enable dynamic DNS queries +page_title: Scale Consul DNS description: -> You tune Consul DNS query handling to balance between current information and reducing request response time. Learn how to enable caching by modifying TTL values, how to return stale results from the DNS cache, and how to configure Consul for negative response caching. --- -# DNS caching +# Scale Consul DNS This page describes the process to return cached results in response to DNS lookups. Consul agents can use DNS caching to reduce response time, but might provide stale information in the process. -## Introduction +## Scaling techniques -By default, Consul serves all DNS results with a `0` TTL value, which prevents any -caching. This configuration returns the most recent information because each DNS lookup -runs every time. However, this configuration adds latency to each lookup and can potentially -exhaust the query throughput of a datacenter. +By default, Consul serves all DNS results with a `0` TTL value so that it returns the most recent information. When operating at scale, this configuration may result in additional latency because servers must respond to every DNS query. There are several strategies for distributing this burden in your datacenter: -There are several ways you can modify to fine-tune Consul DNS lookup behavior to best suit your network's requirements. +- [Allow Stale Reads](#stale-reads). Allows other servers besides the leader to answer the query rather than forwarding it to the leader. +- [Configure DNS TTLs](#ttl-values). Configure DNS time-to-live (TTL) values for nodes or services so that the DNS subsystem on the container’s operating system can cache responses. Services then resolve DNS queries locally without any external requests. +- [Add Read Replicas](/consul/docs/enterprise/read-scale). Enterprise users can use read replicas, which are additional Consul servers that replicate cluster data without participating in the Raft quorum. +- [Use Cache to prevent server requests](/consul/docs/agent/config/config-files#dns_use_cache). Configure the Consul client to use its agent cache to subscribe to events about a service or node. After you establish the watch, the local Consul client agent can resolve DNS queries about the service or node without querying Consul servers. + +The following table describes the availability of each scaling technique depending on whether you configure Consul to offload DNS requests from the cluster leader to a client agent, dataplane, or DNS proxy. + +| Scaling technique | Supported by client agents | Supported by dataplanes | Supported by Consul DNS Proxy | +| :---------------------------------- | :---------------------------: | :---------------------------: | :---------------------------: | +| Configure DNS TTLs | ✅ | ✅ | ✅ | +| Allow Stale Reads | ✅ | ✅ | ✅ | +| Add Read Replicas | ✅ | ✅ | ✅ | +| Use Cache to prevent server request | ✅ | ❌ | ❌ | + +For more information about considerations for Consul deployments that operate at scale, refer to [Operating Consul at Scale](/consul/docs/architecture/scale). ## TTL values ((#ttl)) diff --git a/website/content/docs/services/discovery/dns-forwarding/index.mdx b/website/content/docs/services/discovery/dns-forwarding/index.mdx index 1ee28417397f..d47638bdfac7 100644 --- a/website/content/docs/services/discovery/dns-forwarding/index.mdx +++ b/website/content/docs/services/discovery/dns-forwarding/index.mdx @@ -20,12 +20,13 @@ When configured with default values, Consul exposes the DNS interface on port `8 Instead of running Consul with an administrative or root account, you can forward appropriate queries to Consul, running on an unprivileged port, from another DNS server or using port redirect. There are two configurations for a node's DNS forwarding behavior: + - **Conditional DNS forwarding**: the local DNS servers are configured to forward to Consul only queries relative to the `.consul` zone. All other queries are still served via the default DNS server in the node. - **Full DNS forwarding**: Consul serves all DNS queries and forwards to a remote DNS server the ones outside `.consul` domain. ### Conditional DNS forwarding -We recommend the conditional DNS forwarding approach. This configuration lowers the Consul agent's resource consumption by limiting the number of DNS requests it handles. +We recommend the conditional DNS forwarding approach. This configuration lowers the Consul agent's resource consumption by limiting the number of DNS requests it handles. ![Consul DNS conditional forwarding - Only .consul requests are routed to Consul](/img/consul-dns-conditional-forwarding.png#light-theme-only) ![Consul DNS conditional forwarding - Only .consul requests are routed to Consul](/img/consul-dns-conditional-forwarding-dark.png#dark-theme-only) @@ -43,7 +44,7 @@ This approach can be useful in scenarios where the Consul agent's node is alloca This behavior is not enabled by default. Consul standard configuration only resolves DNS records inside the `.consul` zone. To enable DNS forwarding, you need to set the [recursors](/consul/docs/agent/config/config-files#recursors) option in your Consul configuration. -In this scenario, if a Consul DNS reply includes a `CNAME` record pointing outside the `.consul` top level domain, then the DNS reply only includes `CNAME` records by default. +In this scenario, if a Consul DNS reply includes a `CNAME` record pointing outside the `.consul` top level domain, then the DNS reply only includes `CNAME` records by default. When `recursors` is set and the upstream resolver is functioning correctly, Consul tries to resolve CNAMEs and include any records (for example, A, AAAA, PTR) for them in its DNS reply. In these scenarios, Consul is used for full DNS forwarding and is able to serve queries for all domains. diff --git a/website/content/docs/services/discovery/dns-overview.mdx b/website/content/docs/services/discovery/dns-overview.mdx index dd2b22bcf113..d961cc884d8f 100644 --- a/website/content/docs/services/discovery/dns-overview.mdx +++ b/website/content/docs/services/discovery/dns-overview.mdx @@ -10,6 +10,7 @@ description: >- This topic provides overview information about how to look up Consul nodes and services using the Consul DNS. ## Consul DNS + The Consul DNS is the primary interface for discovering services registered in the Consul catalog. The DNS enables you to look up services and nodes registered with Consul using terminal commands instead of making HTTP API requests to Consul. We recommend using the DNS for service discovery in virtual machine (VM) environments because it removes the need to modify native applications so that they can consume the Consul service discovery APIs. @@ -17,19 +18,29 @@ We recommend using the DNS for service discovery in virtual machine (VM) environ The DNS has several default configurations, but you can customize how the server processes lookups. Refer to [Configure DNS Behaviors](/consul/docs/services/discovery/dns-configuration) for additional information. ### DNS versus native app integration + You can use DNS to reach services registered with Consul or modify your application to natively consume the Consul service discovery HTTP APIs. We recommend using the DNS because it is less invasive. You do not have to modify your application with Consul to retrieve the service’s connection information. Instead, you can use a DNS fully qualified domain (FQDN) that conforms to Consul's lookup format to retrieve the relevant information. -Refer to [ Native App Integration](/consul/docs/connect/native) and its [Go package](/consul/docs/connect/native/go) for additional information. +Refer to [Native App Integration](/consul/docs/connect/native) and its [Go package](/consul/docs/connect/native/go) for additional information. ### DNS versus upstreams + If you are using Consul for service discovery and have not enabled service mesh features, then use the DNS to discover services and nodes in the Consul catalog. If you are using Consul for service mesh on VMs, you can use upstreams or DNS. We recommend using upstreams because you can query services and nodes without modifying the application code or environment variables. Refer to [Upstream Configuration Reference](/consul/docs/connect/proxies/proxy-config-reference#upstream-configuration-reference) for additional information. If you are using Consul on Kubernetes, refer to [the upstreams annotation documentation](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-connect-service-upstreams) for additional information. +## Consul DNS on Kubernetes + +Consul on Kubernetes supports approaches to using the Consul DNS in Kubernetes clusters. + +For service discovery operations, refer to [Consul DNS views on Kubernetes](/consul/docs/k8s/dns/views). + +For service mesh operations, refer to [Resolve Consul DNS requests in Kubernetes](/consul/docs/k8s/dns/enable). + ## DNS forwarding You can configure your local DNS servers to use Consul. @@ -37,6 +48,7 @@ You can configure your local DNS servers to use Consul. Refer to [DNS Forwarding](/consul/docs/services/discovery/dns-forwarding) for additional information. ## Static queries + Node lookups and service lookups are the fundamental types of static queries. Depending on your use case, you may need to use different query methods and syntaxes to query the DNS for services and nodes. Consul relies on a very specific format for queries to resolve names. Note that all queries are case-sensitive. @@ -44,4 +56,5 @@ Consul relies on a very specific format for queries to resolve names. Note that Refer to [Perform Static DNS Lookups](/consul/docs/services/discovery/dns-static-lookups) for details about how to perform node and service lookups. ## Prepared queries + Prepared queries are configurations that enable you to register complex DNS queries. They provide lookup features that extend Consul's service discovery capabilities, such as filtering by multiple tags and automatically querying remote datacenters for services if no healthy nodes are available in the local datacenter. You can also create prepared query templates that match names using a prefix match, allowing a single template to apply to potentially many services. Refer to [Enable Dynamic DNS Queries](/consul/docs/services/discovery/dns-dynamic-lookups) for additional information. diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 37a6ff0d8dc3..cccac5a270c5 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -1675,7 +1675,25 @@ }, { "title": "Consul DNS", - "path": "k8s/dns" + "routes": [ + { + "title": "DNS proxy for service discovery", + "routes": [ + { + "title": "Overview", + "path": "k8s/dns/views" + }, + { + "title": "Enable Consul DNS proxy", + "path": "k8s/dns/views/enable" + } + ] + }, + { + "title": "Enable on dataplanes", + "path": "k8s/dns/enable" + } + ] }, { "title": "Upgrade", diff --git a/website/redirects.js b/website/redirects.js index 362b3526af02..536a11abadf2 100644 --- a/website/redirects.js +++ b/website/redirects.js @@ -247,4 +247,14 @@ module.exports = [ destination: '/consul/docs/architecture/catalog#v2-catalog', permanent: true, }, + { + source: '/consul/docs/k8s/dns', + destination: '/consul/docs/k8s/dns/enable', + permanent: true, + }, + { + source: '/consul/docs/:version(v1\.(?:11|12|13|14|15|16|17|18)\.x)/k8s/dns/enable', + destination: '/consul/docs/:version/k8s/dns', + permanent: true, + } ] From 044e4083914c19857fa0ca7f29e7d47d92f17d69 Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Tue, 15 Oct 2024 11:55:02 -0400 Subject: [PATCH 24/97] Post-release updates for 1.20.0 (#21829) * Update active version list in .release/versions.hcl * Remove nightly tests for 1.17.x * Add nightly tests for 1.20.x * Gate nightly tests for 1.19.x to Enterprise only * Update CHANGELOG.md --- .github/workflows/nightly-test-1.19.x.yaml | 9 ++++++ ...t-1.17.x.yaml => nightly-test-1.20.x.yaml} | 12 +++---- .release/versions.hcl | 5 +-- CHANGELOG.md | 31 +++++++++++++++++++ 4 files changed, 47 insertions(+), 10 deletions(-) rename .github/workflows/{nightly-test-1.17.x.yaml => nightly-test-1.20.x.yaml} (97%) diff --git a/.github/workflows/nightly-test-1.19.x.yaml b/.github/workflows/nightly-test-1.19.x.yaml index 2f5398596b2f..20c80dcb2395 100644 --- a/.github/workflows/nightly-test-1.19.x.yaml +++ b/.github/workflows/nightly-test-1.19.x.yaml @@ -14,8 +14,15 @@ env: GOPRIVATE: github.com/hashicorp # Required for enterprise deps jobs: + check-ent: + runs-on: ubuntu-latest + if: ${{ endsWith(github.repository, '-enterprise') }} + steps: + - run: echo "Building Enterprise" + frontend-test-workspace-node: runs-on: ubuntu-latest + needs: [ check-ent ] steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: @@ -45,6 +52,7 @@ jobs: frontend-build-ce: runs-on: ubuntu-latest + needs: [ check-ent ] env: JOBS: 2 CONSUL_NSPACES_ENABLED: 0 @@ -117,6 +125,7 @@ jobs: frontend-build-ent: runs-on: ubuntu-latest + needs: [ check-ent ] env: JOBS: 2 CONSUL_NSPACES_ENABLED: 1 diff --git a/.github/workflows/nightly-test-1.17.x.yaml b/.github/workflows/nightly-test-1.20.x.yaml similarity index 97% rename from .github/workflows/nightly-test-1.17.x.yaml rename to .github/workflows/nightly-test-1.20.x.yaml index 10eb3d9e0173..37f035def29b 100644 --- a/.github/workflows/nightly-test-1.17.x.yaml +++ b/.github/workflows/nightly-test-1.20.x.yaml @@ -1,7 +1,7 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly Frontend Test 1.17.x +name: Nightly Frontend Test 1.20.x on: schedule: - cron: '0 4 * * *' @@ -9,8 +9,8 @@ on: env: EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "release/1.17.x" - BRANCH_NAME: "release-1.17.x" # Used for naming artifacts + BRANCH: "release/1.20.x" + BRANCH_NAME: "release-1.20.x" # Used for naming artifacts GOPRIVATE: github.com/hashicorp # Required for enterprise deps jobs: @@ -22,7 +22,7 @@ jobs: frontend-test-workspace-node: runs-on: ubuntu-latest - needs: [check-ent] + needs: [ check-ent ] steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: @@ -52,7 +52,7 @@ jobs: frontend-build-ce: runs-on: ubuntu-latest - needs: [check-ent] + needs: [ check-ent ] env: JOBS: 2 CONSUL_NSPACES_ENABLED: 0 @@ -125,7 +125,7 @@ jobs: frontend-build-ent: runs-on: ubuntu-latest - needs: [check-ent] + needs: [ check-ent ] env: JOBS: 2 CONSUL_NSPACES_ENABLED: 1 diff --git a/.release/versions.hcl b/.release/versions.hcl index 7f4e5b953827..253430f3ccc1 100644 --- a/.release/versions.hcl +++ b/.release/versions.hcl @@ -9,13 +9,10 @@ active_versions { version "1.20" { ce_active = true } - version "1.19" { - ce_active = true - } + version "1.19" {} version "1.18" { lts = true } - version "1.17" {} version "1.15" { lts = true } diff --git a/CHANGELOG.md b/CHANGELOG.md index 940ab662e068..675b8d5bf572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,34 @@ +## 1.20.0 (October 14, 2024) + +SECURITY: + +* Explicitly set 'Content-Type' header to mitigate XSS vulnerability. [[GH-21704](https://github.com/hashicorp/consul/issues/21704)] +* Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. [[GH-21711](https://github.com/hashicorp/consul/issues/21711)] +* UI: Remove codemirror linting due to package dependency [[GH-21726](https://github.com/hashicorp/consul/issues/21726)] +* Upgrade Go to use 1.22.7. This addresses CVE +[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] +* Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs +[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and +[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] +* ui: Pin a newer resolution of Braces [[GH-21710](https://github.com/hashicorp/consul/issues/21710)] +* ui: Pin a newer resolution of Codemirror [[GH-21715](https://github.com/hashicorp/consul/issues/21715)] +* ui: Pin a newer resolution of Markdown-it [[GH-21717](https://github.com/hashicorp/consul/issues/21717)] +* ui: Pin a newer resolution of ansi-html [[GH-21735](https://github.com/hashicorp/consul/issues/21735)] + +FEATURES: + +* grafana: added the dashboards service-to-service dashboard, service dashboard, and consul dataplane dashboard [[GH-21806](https://github.com/hashicorp/consul/issues/21806)] +* server: remove v2 tenancy, catalog, and mesh experiments [[GH-21592](https://github.com/hashicorp/consul/issues/21592)] + +IMPROVEMENTS: + +* security: upgrade ubi base image to 9.4 [[GH-21750](https://github.com/hashicorp/consul/issues/21750)] +* connect: Add Envoy 1.31 and 1.30 to support matrix [[GH-21616](https://github.com/hashicorp/consul/issues/21616)] + +BUG FIXES: + +* jwt-provider: change dns lookup family from the default of AUTO which would prefer ipv6 to ALL if LOGICAL_DNS is used or PREFER_IPV4 if STRICT_DNS is used to gracefully handle transitions to ipv6. [[GH-21703](https://github.com/hashicorp/consul/issues/21703)] + ## 1.20.0-rc1 (September 19, 2024) SECURITY: From 7e61148f866d2933d4090dc5213f522acc47bccd Mon Sep 17 00:00:00 2001 From: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:40:47 -0700 Subject: [PATCH 25/97] docs: Consul v1.20 release notes (#21826) * Page creation * DNS views description * Catalog sync and openshift * Grafana + consul-k8s release notes * nav update * Fix known issues language --- .../docs/release-notes/consul-k8s/v1_6_x.mdx | 51 +++++++++++++++++++ .../docs/release-notes/consul/v1_20_x.mdx | 38 ++++++++++++++ website/data/docs-nav-data.json | 8 +++ 3 files changed, 97 insertions(+) create mode 100644 website/content/docs/release-notes/consul-k8s/v1_6_x.mdx create mode 100644 website/content/docs/release-notes/consul/v1_20_x.mdx diff --git a/website/content/docs/release-notes/consul-k8s/v1_6_x.mdx b/website/content/docs/release-notes/consul-k8s/v1_6_x.mdx new file mode 100644 index 000000000000..98aab6df59ed --- /dev/null +++ b/website/content/docs/release-notes/consul-k8s/v1_6_x.mdx @@ -0,0 +1,51 @@ +--- +layout: docs +page_title: 1.6.x +description: >- + Consul on Kubernetes release notes for version 1.6.x +--- + +# Consul on Kubernetes 1.6.0 + +We are pleased to announce the following Consul updates. + +## Release highlights + + +- **Consul DNS views for Kubernetes**: Consul on Kubernetes now supports scheduling a dedicated Consul DNS proxy in a Kubernetes Pod instead of using client agents or dataplanes. The proxy is designed for deployment in a Kubernetes cluster with [external servers enabled](/consul/docs/k8s/deployment-configurations/servers-outside-kubernetes) to provide applications in Kubernetes the ability to resolve Consul DNS addresses. You can use the Consul DNS proxy to enable service discovery across admin partitions in Kubernetes deployments. For more information, refer to [Consul DNS views for Kubernetes](/consul/docs/k8s/dns/views). + +- **Catalog sync improvements**: Consul v1.20 includes improved metrics for Consul catalog sync. Consul catalog sync is a feature that automatically registers Kubernetes services with Consul’s catalog. Prior to this enhancement, operators had limited visibility into the status of Kubernetes services being synced to Consul and the performance of the sync catalog process. At scale, it was difficult to discern if the sync process was healthy and progressing normally. Catalog sync enhancements now provide more insights that include status and performance metrics of the sync process. New performance metrics include the rate of registered or deregistered services, the status and health of the sync process, and additional metadata related to registered services. + +- **OpenShift improvements**: Prior to this release, deploying Consul service mesh on Kubernetes required the transparent proxy to have elevated permissions through `anyuid` security context constraint (SCC) privileges. This requirement prevented users from deploying the transparent proxy in OpenShift environments where elevated pod permissions were prohibited. Consul v1.20 no longer requires elevated permissions for the transparent proxy in OpenShift deployments. + +- **Service dashboards for Grafana**: Consul v1.20 includes JSON templates for Grafana dashboards to help you monitor Consul services, service-to-service communication, and Consuld dataplane operations. You can [find these dashboards in the GitHub repo](https://github.com/hashicorp/consul/tree/main/grafana). For more information about configuring Consul to use Grafana, refer to [Configure Metrics for Consul on Kubernetes](/consul/docs/k8s/connect/observability/metrics). + +## Supported software + +This version of Consul on Kubernetes supports the following software versions: + +- Consul v1.20.x +- Consul Dataplane v1.6.x. Refer to [Envoy and Consul Dataplane](/consul/docs/v1.19.x/connect/proxies/envoy#envoy-and-consul-dataplane) for details about Consul Dataplane versions and the available packaged Envoy version. +- Kubernetes 1.28.x - 1.31.x +- kubectl 1.28.x - 1.31.x +- Helm 3.11.3+ + +Refer to [Supported Consul and Kubernetes versions](/consul/docs/v1.19.x/k8s/compatibility#supported-consul-and-kubernetes-versions) for more information. + +## Upgrading + +For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. + +## Known issues + +There are no known issues at this time. These release notes are updated as issues are discovered. + +[Report issues on Github](https://github.com/hashicorp/consul-k8s/issues). + +## Changelogs + +The changelogs for this major release version and any maintenance versions are listed below. + + These links take you to the changelogs on the GitHub website. + +- [1.6.0](https://github.com/hashicorp/consul-k8s/releases/tag/v1.6.0) diff --git a/website/content/docs/release-notes/consul/v1_20_x.mdx b/website/content/docs/release-notes/consul/v1_20_x.mdx new file mode 100644 index 000000000000..17e19a3de573 --- /dev/null +++ b/website/content/docs/release-notes/consul/v1_20_x.mdx @@ -0,0 +1,38 @@ +--- +layout: docs +page_title: 1.20.x +description: >- + Consul release notes for version 1.20.x +--- + +# Consul 1.20.0 + +We are pleased to announce the following Consul updates. + +## Release highlights + +- **Consul DNS views for Kubernetes**: Consul on Kubernetes now supports scheduling a dedicated Consul DNS proxy in a Kubernetes Pod instead of using client agents or dataplanes. The proxy is designed for deployment in a Kubernetes cluster with [external servers enabled](/consul/docs/k8s/deployment-configurations/servers-outside-kubernetes) to provide applications in Kubernetes the ability to resolve Consul DNS addresses. You can use the Consul DNS proxy to enable service discovery across admin partitions in Kubernetes deployments. For more information, refer to [Consul DNS views for Kubernetes](/consul/docs/k8s/dns/views). + +- **Catalog sync improvements**: Consul v1.20 includes improved metrics for Consul catalog sync. Consul catalog sync is a feature that automatically registers Kubernetes services with Consul’s catalog. Prior to this enhancement, operators had limited visibility into the status of Kubernetes services being synced to Consul and the performance of the sync catalog process. At scale, it was difficult to discern if the sync process was healthy and progressing normally. Catalog sync enhancements now provide more insights that include status and performance metrics of the sync process. New performance metrics include the rate of registered or deregistered services, the status and health of the sync process, and additional metadata related to registered services. + +- **OpenShift improvements**: Prior to this release, deploying Consul service mesh on Kubernetes required the transparent proxy to have elevated permissions through `anyuid` security context constraint (SCC) privileges. This requirement prevented users from deploying the transparent proxy in OpenShift environments where elevated pod permissions were prohibited. Consul v1.20 no longer requires elevated permissions for the transparent proxy in OpenShift deployments. + +- **Service dashboards for Grafana**: Consul v1.20 includes JSON templates for Grafana dashboards to help you monitor Consul services, service-to-service communication, and Consuld dataplane operations. You can [find these dashboards in the GitHub repo](https://github.com/hashicorp/consul/tree/main/grafana). For more information about configuring Consul to use Grafana, refer to [Configure Metrics for Consul on Kubernetes](/consul/docs/k8s/connect/observability/metrics). + +## Upgrading + +For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. + +## Known issues + +There are no known issues at this time. These release notes are updated as issues are discovered. + +[Report issues on Github](https://github.com/hashicorp/consul/issues). + +## Changelogs + +The changelogs for this major release version and any maintenance versions are listed below. + + These links take you to the changelogs on the GitHub website. + +- [1.20.0](https://github.com/hashicorp/consul/releases/tag/v1.20.0) diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index cccac5a270c5..204303ef9b59 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -153,6 +153,10 @@ { "title": "Consul", "routes": [ + { + "title": "v1.20.x", + "path": "release-notes/consul/v1_20_x" + }, { "title": "v1.19.x", "path": "release-notes/consul/v1_19_x" @@ -202,6 +206,10 @@ { "title": "Consul K8s", "routes": [ + { + "title": "v1.6.x", + "path": "release-notes/consul-k8s/v1_6_x" + }, { "title": "v1.5.x", "path": "release-notes/consul-k8s/v1_5_x" From 3370f6b250a50148f1303c4d4f4d095f7f38911f Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Wed, 16 Oct 2024 10:36:04 -0400 Subject: [PATCH 26/97] chore: remove unintentionally committed consul-k8s submodule (#21833) Also prevent future re-commits of this submodule path by adding to .gitignore. --- .gitignore | 3 +++ consul-k8s | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) delete mode 160000 consul-k8s diff --git a/.gitignore b/.gitignore index 9649c4a8cb98..fcd852606c5e 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,6 @@ terraform.rc /go.work /go.work.sum .docker + +# Avoid accidental commits of consul-k8s submodule used by some dev environments +consul-k8s/ diff --git a/consul-k8s b/consul-k8s deleted file mode 160000 index 0d85bbc3131c..000000000000 --- a/consul-k8s +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0d85bbc3131ce8be23c57e30b213ba6056623976 From d9206fc7e284a9244af4d62f8653a63ca30bd00c Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Wed, 16 Oct 2024 12:23:33 -0400 Subject: [PATCH 27/97] [NET-1151 NET-11228] security: Add request normalization and header match options to prevent L7 intentions bypass (#21816) mesh: add options for HTTP incoming request normalization Expose global mesh configuration to enforce inbound HTTP request normalization on mesh traffic via Envoy xDS config. mesh: enable inbound URL path normalization by default mesh: add support for L7 header match contains and ignore_case Enable partial string and case-insensitive matching in L7 intentions header match rules. ui: support L7 header match contains and ignore_case Co-authored-by: Phil Renaud test: add request normalization integration bats tests Add both "positive" and "negative" test suites, showing normalization in action as well as expected results when it is not enabled, for the same set of test cases. Also add some alternative service container test helpers for verifying raw HTTP request paths, which is difficult to do with Fortio. docs: update security and reference docs for L7 intentions bypass prevention - Update security docs with best practices for service intentions configuration - Update configuration entry references for mesh and intentions to reflect new values and add guidance on usage --- .changelog/21816.txt | 9 + agent/structs/config_entry_intentions.go | 24 +- agent/structs/config_entry_intentions_test.go | 455 +- agent/structs/config_entry_mesh.go | 202 + agent/structs/config_entry_mesh_test.go | 161 + agent/structs/config_entry_test.go | 70 +- agent/structs/structs.deepcopy.go | 8 + agent/xds/listeners.go | 60 +- agent/xds/listeners_test.go | 70 + agent/xds/rbac.go | 18 +- agent/xds/rbac_test.go | 18 + agent/xds/resources_test.go | 52 + ...uthz-http-local-grpc-service.latest.golden | 3 +- ...uthz-http-local-http-service.latest.golden | 3 +- ...z-http-upstream-grpc-service.latest.golden | 3 +- ...z-http-upstream-http-service.latest.golden | 3 +- ...lambda-and-lua-connect-proxy.latest.golden | 3 +- ...a-inbound-applies-to-inbound.latest.golden | 3 +- ...snt-apply-to-local-upstreams.latest.golden | 3 +- ...es-to-local-upstreams-tproxy.latest.golden | 3 +- ...d-applies-to-local-upstreams.latest.golden | 3 +- ...ound-doesnt-apply-to-inbound.latest.golden | 3 +- ...-consul-constraint-violation.latest.golden | 3 +- ...h-envoy-constraint-violation.latest.golden | 3 +- .../otel-access-logging-http.latest.golden | 3 +- ...opertyoverride-add-keepalive.latest.golden | 3 +- ...d-outlier-detection-multiple.latest.golden | 3 +- ...erride-add-outlier-detection.latest.golden | 3 +- ...de-add-round-robin-lb-config.latest.golden | 3 +- ...-load-assignment-inbound-add.latest.golden | 3 +- ...load-assignment-outbound-add.latest.golden | 3 +- ...und-doesnt-apply-to-outbound.latest.golden | 3 +- ...verride-listener-inbound-add.latest.golden | 3 +- ...erride-listener-outbound-add.latest.golden | 3 +- ...ound-doesnt-apply-to-inbound.latest.golden | 3 +- ...ic-upstream-service-failover.latest.golden | 3 +- ...ic-upstream-service-splitter.latest.golden | 3 +- ...ide-remove-outlier-detection.latest.golden | 3 +- ...ive-mtls-and-envoy-extension.latest.golden | 3 +- .../wasm-http-local-file.latest.golden | 3 +- .../wasm-http-remote-file.latest.golden | 3 +- ...alization-all-consul-options.latest.golden | 136 + ...on-all-envoy-options-enabled.latest.golden | 136 + ...alization-all-consul-options.latest.golden | 75 + ...on-all-envoy-options-enabled.latest.golden | 75 + ...alization-all-consul-options.latest.golden | 275 + ...on-all-envoy-options-enabled.latest.golden | 276 + .../custom-trace-listener.latest.golden | 3 +- ...paths-grpc-new-cluster-http1.latest.golden | 3 +- .../grpc-public-listener.latest.golden | 3 +- .../http-listener-with-timeouts.latest.golden | 3 +- ...http-public-listener-no-xfcc.latest.golden | 3 +- .../http-public-listener.latest.golden | 3 +- .../http2-public-listener.latest.golden | 3 +- ...with-kitchen-sink-perms--httpfilter.golden | 55 +- ...with-kitchen-sink-perms--httpfilter.golden | 55 +- ...alization-all-consul-options.latest.golden | 5 + ...on-all-envoy-options-enabled.latest.golden | 5 + ...alization-all-consul-options.latest.golden | 5 + ...on-all-envoy-options-enabled.latest.golden | 5 + api/config_entry_intentions.go | 16 +- api/config_entry_mesh.go | 41 + command/helpers/helpers_test.go | 129 +- .../private/pbconfigentry/config_entry.gen.go | 52 + proto/private/pbconfigentry/config_entry.go | 60 + .../pbconfigentry/config_entry.pb.binary.go | 20 + .../private/pbconfigentry/config_entry.pb.go | 4766 +++++++++-------- .../private/pbconfigentry/config_entry.proto | 40 + .../acl.hcl | 5 + .../capture.sh | 7 + .../setup.sh | 101 + .../vars.sh | 6 + .../verify.bats | 99 + .../acl.hcl | 5 + .../capture.sh | 7 + .../setup.sh | 101 + .../vars.sh | 6 + .../verify.bats | 129 + .../connect/envoy/case-l7-intentions/setup.sh | 54 + .../envoy/case-l7-intentions/verify.bats | 65 +- test/integration/connect/envoy/helpers.bash | 59 +- test/integration/connect/envoy/run-tests.sh | 59 +- .../permission/header/form/index.hbs | 15 +- .../intention/permission/header/form/index.js | 11 +- .../permission/header/form/pageobject.js | 9 +- .../consul-ui/app/helpers/route-match.js | 17 +- .../intention-permission-http-header.js | 4 +- ui/packages/consul-ui/mock-api/v1/connect/_ | 4 + .../mock-api/v1/connect/intentions/_ | 4 + .../mock-api/v1/connect/intentions/exact | 4 + .../docs/connect/config-entries/mesh.mdx | 103 + .../config-entries/service-intentions.mdx | 67 +- .../content/docs/connect/intentions/index.mdx | 6 +- website/content/docs/connect/security.mdx | 32 + .../docs/security/security-models/core.mdx | 15 + .../docs/upgrading/upgrade-specific.mdx | 17 + 96 files changed, 5859 insertions(+), 2634 deletions(-) create mode 100644 .changelog/21816.txt create mode 100644 agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden create mode 100644 agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden create mode 100644 agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden create mode 100644 agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden create mode 100644 agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden create mode 100644 agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden create mode 100644 agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden create mode 100644 agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden create mode 100644 agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden create mode 100644 agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/acl.hcl create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/capture.sh create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/setup.sh create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/vars.sh create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/verify.bats create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization/acl.hcl create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization/capture.sh create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization/setup.sh create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization/vars.sh create mode 100644 test/integration/connect/envoy/case-l7-intentions-request-normalization/verify.bats diff --git a/.changelog/21816.txt b/.changelog/21816.txt new file mode 100644 index 000000000000..40bc844beee9 --- /dev/null +++ b/.changelog/21816.txt @@ -0,0 +1,9 @@ +```release-note:security +mesh: Add `http.incoming.requestNormalization` to Mesh configuration entry to support inbound service traffic request normalization. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005) and [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +``` +```release-note:security +mesh: Add `contains` and `ignoreCase` to L7 Intentions HTTP header matching criteria to support configuration resilient to variable casing and multiple values. This resolves [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +``` +```release-note:breaking-change +mesh: Enable Envoy `HttpConnectionManager.normalize_path` by default on inbound traffic to mesh proxies. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005). +``` diff --git a/agent/structs/config_entry_intentions.go b/agent/structs/config_entry_intentions.go index d06a260a59d8..6da3160dd610 100644 --- a/agent/structs/config_entry_intentions.go +++ b/agent/structs/config_entry_intentions.go @@ -426,13 +426,15 @@ func (p *IntentionHTTPPermission) Clone() *IntentionHTTPPermission { } type IntentionHTTPHeaderPermission struct { - Name string - Present bool `json:",omitempty"` - Exact string `json:",omitempty"` - Prefix string `json:",omitempty"` - Suffix string `json:",omitempty"` - Regex string `json:",omitempty"` - Invert bool `json:",omitempty"` + Name string + Present bool `json:",omitempty"` + Exact string `json:",omitempty"` + Prefix string `json:",omitempty"` + Suffix string `json:",omitempty"` + Contains string `json:",omitempty"` + Regex string `json:",omitempty"` + Invert bool `json:",omitempty"` + IgnoreCase bool `json:",omitempty" alias:"ignore_case"` } func cloneStringStringMap(m map[string]string) map[string]string { @@ -880,8 +882,14 @@ func (e *ServiceIntentionsConfigEntry) validate(legacyWrite bool) error { if hdr.Suffix != "" { hdrParts++ } + if hdr.Contains != "" { + hdrParts++ + } if hdrParts != 1 { - return fmt.Errorf(errorPrefix+".Header[%d] should only contain one of Present, Exact, Prefix, Suffix, or Regex", i, j, k) + return fmt.Errorf(errorPrefix+".Header[%d] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex", i, j, k) + } + if hdr.IgnoreCase && (hdr.Present || hdr.Regex != "") { + return fmt.Errorf(errorPrefix+".Header[%d] should set one of Exact, Prefix, Suffix, or Contains when using IgnoreCase", i, j, k) } permParts++ } diff --git a/agent/structs/config_entry_intentions_test.go b/agent/structs/config_entry_intentions_test.go index ea8703de05d8..9449dc9b7771 100644 --- a/agent/structs/config_entry_intentions_test.go +++ b/agent/structs/config_entry_intentions_test.go @@ -574,323 +574,164 @@ func TestServiceIntentionsConfigEntry(t *testing.T) { validateErr: `Sources[0].Permissions[0].HTTP.Header[0] missing required Name field`, }, "permission header has too many parts (1)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - Exact: "foo", - // Regex: "foo", - // Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + Exact: "foo", + // Regex: "foo", + // Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (2)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - // Exact: "foo", - Regex: "foo", - // Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + Regex: "foo", + Prefix: "foo", + // Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (3)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - // Exact: "foo", - // Regex: "foo", - Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (4)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - // Exact: "foo", - // Regex: "foo", - // Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (5)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - Exact: "foo", - Regex: "foo", - // Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + Present: true, + Exact: "foo", + Regex: "foo", + Prefix: "foo", + Suffix: "foo", + Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (6)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - Exact: "foo", - // Regex: "foo", - Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + Present: true, + Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (7)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - Exact: "foo", - // Regex: "foo", - // Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (8)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - // Exact: "foo", - Regex: "foo", - Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + Regex: "foo", + Prefix: "foo", + // Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (9)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - // Exact: "foo", - Regex: "foo", - // Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + Regex: "foo", + // Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (10)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - // Exact: "foo", - // Regex: "foo", - Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, + }, + "permission header invalid ignore case (1)": { + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + Present: true, + IgnoreCase: true, }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should set one of Exact, Prefix, Suffix, or Contains when using IgnoreCase`, }, - "permission header has too many parts (11)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - Exact: "foo", - Regex: "foo", - Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, + "permission header invalid ignore case (2)": { + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + Regex: "qux", + IgnoreCase: true, }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should set one of Exact, Prefix, Suffix, or Contains when using IgnoreCase`, }, "permission invalid method": { entry: &ServiceIntentionsConfigEntry{ @@ -1677,3 +1518,25 @@ func TestMigrateIntentions(t *testing.T) { }) } } + +// httpHeaderPermissionEntry is a helper to generate a ServiceIntentionsConfigEntry for testing +// IntentionHTTPHeaderPermission values. +func httpHeaderPermissionEntry(header []IntentionHTTPHeaderPermission) *ServiceIntentionsConfigEntry { + return &ServiceIntentionsConfigEntry{ + Kind: ServiceIntentions, + Name: "test", + Sources: []*SourceIntention{ + { + Name: "foo", + Permissions: []*IntentionPermission{ + { + Action: IntentionActionAllow, + HTTP: &IntentionHTTPPermission{ + Header: header, + }, + }, + }, + }, + }, + } +} diff --git a/agent/structs/config_entry_mesh.go b/agent/structs/config_entry_mesh.go index 210e82c87db7..0fa36d0854d7 100644 --- a/agent/structs/config_entry_mesh.go +++ b/agent/structs/config_entry_mesh.go @@ -6,6 +6,7 @@ package structs import ( "encoding/json" "fmt" + "strings" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/types" @@ -72,6 +73,17 @@ type MeshDirectionalTLSConfig struct { type MeshHTTPConfig struct { SanitizeXForwardedClientCert bool `alias:"sanitize_x_forwarded_client_cert"` + // Incoming configures settings for incoming HTTP traffic to mesh proxies. + Incoming *MeshDirectionalHTTPConfig `json:",omitempty"` + // There is not currently an outgoing MeshDirectionalHTTPConfig, as + // the only required config for either direction at present is inbound + // request normalization. +} + +// MeshDirectionalHTTPConfig holds mesh configuration specific to HTTP +// requests for a given traffic direction. +type MeshDirectionalHTTPConfig struct { + RequestNormalization *RequestNormalizationMeshConfig `json:",omitempty" alias:"request_normalization"` } // PeeringMeshConfig contains cluster-wide options pertaining to peering. @@ -84,6 +96,104 @@ type PeeringMeshConfig struct { PeerThroughMeshGateways bool `alias:"peer_through_mesh_gateways"` } +// RequestNormalizationMeshConfig contains options pertaining to the +// normalization of HTTP requests processed by mesh proxies. +type RequestNormalizationMeshConfig struct { + // InsecureDisablePathNormalization sets the value of the \`normalize_path\` option in the Envoy listener's + // `HttpConnectionManager`. The default value is \`false\`. When set to \`true\` in Consul, \`normalize_path\` is + // set to \`false\` for the Envoy proxy. This parameter disables the normalization of request URL paths according to + // RFC 3986, conversion of \`\\\` to \`/\`, and decoding non-reserved %-encoded characters. When using L7 intentions + // with path match rules, we recommend enabling path normalization in order to avoid match rule circumvention with + // non-normalized path values. + InsecureDisablePathNormalization bool `alias:"insecure_disable_path_normalization"` + // MergeSlashes sets the value of the \`merge_slashes\` option in the Envoy listener's \`HttpConnectionManager\`. + // The default value is \`false\`. This option controls the normalization of request URL paths by merging + // consecutive \`/\` characters. This normalization is not part of RFC 3986. When using L7 intentions with path + // match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path + // values, unless legitimate service traffic depends on allowing for repeat \`/\` characters, or upstream services + // are configured to differentiate between single and multiple slashes. + MergeSlashes bool `alias:"merge_slashes"` + // PathWithEscapedSlashesAction sets the value of the \`path_with_escaped_slashes_action\` option in the Envoy + // listener's \`HttpConnectionManager\`. The default value of this option is empty, which is equivalent to + // \`IMPLEMENTATION_SPECIFIC_DEFAULT\`. This parameter controls the action taken in response to request URL paths + // with escaped slashes in the path. When using L7 intentions with path match rules, we recommend enabling this + // setting to avoid match rule circumvention through non-normalized path values, unless legitimate service traffic + // depends on allowing for escaped \`/\` or \`\\\` characters, or upstream services are configured to differentiate + // between escaped and unescaped slashes. Refer to the Envoy documentation for more information on available + // options. + PathWithEscapedSlashesAction PathWithEscapedSlashesAction `alias:"path_with_escaped_slashes_action"` + // HeadersWithUnderscoresAction sets the value of the \`headers_with_underscores_action\` option in the Envoy + // listener's \`HttpConnectionManager\` under \`common_http_protocol_options\`. The default value of this option is + // empty, which is equivalent to \`ALLOW\`. Refer to the Envoy documentation for more information on available + // options. + HeadersWithUnderscoresAction HeadersWithUnderscoresAction `alias:"headers_with_underscores_action"` +} + +// PathWithEscapedSlashesAction is an enum that defines the action to take when +// a request path contains escaped slashes. It mirrors exactly the set of options +// in Envoy's UriPathNormalizationOptions.PathWithEscapedSlashesAction enum. +type PathWithEscapedSlashesAction string + +// See github.com/envoyproxy/go-control-plane envoy_http_v3.HttpConnectionManager_PathWithEscapedSlashesAction. +const ( + PathWithEscapedSlashesActionDefault PathWithEscapedSlashesAction = "IMPLEMENTATION_SPECIFIC_DEFAULT" + PathWithEscapedSlashesActionKeep PathWithEscapedSlashesAction = "KEEP_UNCHANGED" + PathWithEscapedSlashesActionReject PathWithEscapedSlashesAction = "REJECT_REQUEST" + PathWithEscapedSlashesActionUnescapeAndRedirect PathWithEscapedSlashesAction = "UNESCAPE_AND_REDIRECT" + PathWithEscapedSlashesActionUnescapeAndForward PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD" +) + +// PathWithEscapedSlashesActionStrings returns an ordered slice of all PathWithEscapedSlashesAction values as strings. +func PathWithEscapedSlashesActionStrings() []string { + return []string{ + string(PathWithEscapedSlashesActionDefault), + string(PathWithEscapedSlashesActionKeep), + string(PathWithEscapedSlashesActionReject), + string(PathWithEscapedSlashesActionUnescapeAndRedirect), + string(PathWithEscapedSlashesActionUnescapeAndForward), + } +} + +// pathWithEscapedSlashesActions contains the canonical set of PathWithEscapedSlashesActionValues values. +var pathWithEscapedSlashesActions = (func() map[PathWithEscapedSlashesAction]struct{} { + m := make(map[PathWithEscapedSlashesAction]struct{}) + for _, v := range PathWithEscapedSlashesActionStrings() { + m[PathWithEscapedSlashesAction(v)] = struct{}{} + } + return m +})() + +// HeadersWithUnderscoresAction is an enum that defines the action to take when +// a request contains headers with underscores. It mirrors exactly the set of +// options in Envoy's HttpProtocolOptions.HeadersWithUnderscoresAction enum. +type HeadersWithUnderscoresAction string + +// See github.com/envoyproxy/go-control-plane envoy_core_v3.HttpProtocolOptions_HeadersWithUnderscoresAction. +const ( + HeadersWithUnderscoresActionAllow HeadersWithUnderscoresAction = "ALLOW" + HeadersWithUnderscoresActionRejectRequest HeadersWithUnderscoresAction = "REJECT_REQUEST" + HeadersWithUnderscoresActionDropHeader HeadersWithUnderscoresAction = "DROP_HEADER" +) + +// HeadersWithUnderscoresActionStrings returns an ordered slice of all HeadersWithUnderscoresAction values as strings +// for use in returning validation errors. +func HeadersWithUnderscoresActionStrings() []string { + return []string{ + string(HeadersWithUnderscoresActionAllow), + string(HeadersWithUnderscoresActionRejectRequest), + string(HeadersWithUnderscoresActionDropHeader), + } +} + +// headersWithUnderscoresActions contains the canonical set of HeadersWithUnderscoresAction values. +var headersWithUnderscoresActions = (func() map[HeadersWithUnderscoresAction]struct{} { + m := make(map[HeadersWithUnderscoresAction]struct{}) + for _, v := range HeadersWithUnderscoresActionStrings() { + m[HeadersWithUnderscoresAction(v)] = struct{}{} + } + return m +})() + func (e *MeshConfigEntry) GetKind() string { return MeshConfig } @@ -141,6 +251,10 @@ func (e *MeshConfigEntry) Validate() error { } } + if err := validateRequestNormalizationMeshConfig(e.GetHTTPIncomingRequestNormalization()); err != nil { + return fmt.Errorf("error in HTTP incoming request normalization configuration: %v", err) + } + return e.validateEnterpriseMeta() } @@ -193,6 +307,61 @@ func (e *MeshConfigEntry) PeerThroughMeshGateways() bool { return e.Peering.PeerThroughMeshGateways } +func (e *MeshConfigEntry) GetHTTP() *MeshHTTPConfig { + if e == nil { + return nil + } + return e.HTTP +} + +func (e *MeshHTTPConfig) GetIncoming() *MeshDirectionalHTTPConfig { + if e == nil { + return nil + } + return e.Incoming +} + +func (e *MeshDirectionalHTTPConfig) GetRequestNormalization() *RequestNormalizationMeshConfig { + if e == nil { + return nil + } + return e.RequestNormalization +} + +// GetHTTPIncomingRequestNormalization is a convenience accessor for mesh.http.incoming.request_normalization +// since no other fields currently exist under mesh.http.incoming. +func (e *MeshConfigEntry) GetHTTPIncomingRequestNormalization() *RequestNormalizationMeshConfig { + return e.GetHTTP().GetIncoming().GetRequestNormalization() +} + +func (r *RequestNormalizationMeshConfig) GetInsecureDisablePathNormalization() bool { + if r == nil { + return false + } + return r.InsecureDisablePathNormalization +} + +func (r *RequestNormalizationMeshConfig) GetMergeSlashes() bool { + if r == nil { + return false + } + return r.MergeSlashes +} + +func (r *RequestNormalizationMeshConfig) GetPathWithEscapedSlashesAction() PathWithEscapedSlashesAction { + if r == nil || r.PathWithEscapedSlashesAction == "" { + return PathWithEscapedSlashesActionDefault + } + return r.PathWithEscapedSlashesAction +} + +func (r *RequestNormalizationMeshConfig) GetHeadersWithUnderscoresAction() HeadersWithUnderscoresAction { + if r == nil || r.HeadersWithUnderscoresAction == "" { + return HeadersWithUnderscoresActionAllow + } + return r.HeadersWithUnderscoresAction +} + func validateMeshDirectionalTLSConfig(cfg *MeshDirectionalTLSConfig) error { if cfg == nil { return nil @@ -237,3 +406,36 @@ func validateTLSConfig( return nil } + +func validateRequestNormalizationMeshConfig(cfg *RequestNormalizationMeshConfig) error { + if cfg == nil { + return nil + } + if err := validatePathWithEscapedSlashesAction(cfg.PathWithEscapedSlashesAction); err != nil { + return err + } + if err := validateHeadersWithUnderscoresAction(cfg.HeadersWithUnderscoresAction); err != nil { + return err + } + return nil +} + +func validatePathWithEscapedSlashesAction(v PathWithEscapedSlashesAction) error { + if v == "" { + return nil + } + if _, ok := pathWithEscapedSlashesActions[v]; !ok { + return fmt.Errorf("no matching PathWithEscapedSlashesAction value found for %s, please specify one of [%s]", string(v), strings.Join(PathWithEscapedSlashesActionStrings(), ", ")) + } + return nil +} + +func validateHeadersWithUnderscoresAction(v HeadersWithUnderscoresAction) error { + if v == "" { + return nil + } + if _, ok := headersWithUnderscoresActions[v]; !ok { + return fmt.Errorf("no matching HeadersWithUnderscoresAction value found for %s, please specify one of [%s]", string(v), strings.Join(HeadersWithUnderscoresActionStrings(), ", ")) + } + return nil +} diff --git a/agent/structs/config_entry_mesh_test.go b/agent/structs/config_entry_mesh_test.go index f6eaea9e9c54..a4afbc6c9ff5 100644 --- a/agent/structs/config_entry_mesh_test.go +++ b/agent/structs/config_entry_mesh_test.go @@ -47,3 +47,164 @@ func TestMeshConfigEntry_PeerThroughMeshGateways(t *testing.T) { }) } } + +func TestMeshConfigEntry_GetHTTPIncomingRequestNormalization(t *testing.T) { + tests := map[string]struct { + input *MeshConfigEntry + want *RequestNormalizationMeshConfig + }{ + // Ensure nil is gracefully handled at each level of config path. + "nil entry": { + input: nil, + want: nil, + }, + "nil http config": { + input: &MeshConfigEntry{ + HTTP: nil, + }, + want: nil, + }, + "nil http incoming config": { + input: &MeshConfigEntry{ + HTTP: &MeshHTTPConfig{ + Incoming: nil, + }, + }, + want: nil, + }, + "nil http incoming request normalization config": { + input: &MeshConfigEntry{ + HTTP: &MeshHTTPConfig{ + Incoming: &MeshDirectionalHTTPConfig{ + RequestNormalization: nil, + }, + }, + }, + want: nil, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.want, tc.input.GetHTTPIncomingRequestNormalization()) + }) + } +} + +func TestMeshConfigEntry_RequestNormalizationMeshConfig(t *testing.T) { + tests := map[string]struct { + input *RequestNormalizationMeshConfig + getFn func(*RequestNormalizationMeshConfig) any + want any + }{ + // Ensure defaults are returned when config is not set. + "nil entry gets false GetInsecureDisablePathNormalization": { + input: nil, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetInsecureDisablePathNormalization() + }, + want: false, + }, + "nil entry gets false GetMergeSlashes": { + input: nil, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetMergeSlashes() + }, + want: false, + }, + "nil entry gets default GetPathWithEscapedSlashesAction": { + input: nil, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetPathWithEscapedSlashesAction() + }, + want: PathWithEscapedSlashesAction("IMPLEMENTATION_SPECIFIC_DEFAULT"), + }, + "nil entry gets default GetHeadersWithUnderscoresAction": { + input: nil, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetHeadersWithUnderscoresAction() + }, + want: HeadersWithUnderscoresAction("ALLOW"), + }, + "empty entry gets default GetPathWithEscapedSlashesAction": { + input: &RequestNormalizationMeshConfig{}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetPathWithEscapedSlashesAction() + }, + want: PathWithEscapedSlashesAction("IMPLEMENTATION_SPECIFIC_DEFAULT"), + }, + "empty entry gets default GetHeadersWithUnderscoresAction": { + input: &RequestNormalizationMeshConfig{}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetHeadersWithUnderscoresAction() + }, + want: HeadersWithUnderscoresAction("ALLOW"), + }, + // Ensure values are returned when set. + "non-default entry gets expected InsecureDisablePathNormalization": { + input: &RequestNormalizationMeshConfig{InsecureDisablePathNormalization: true}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetInsecureDisablePathNormalization() + }, + want: true, + }, + "non-default entry gets expected MergeSlashes": { + input: &RequestNormalizationMeshConfig{MergeSlashes: true}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetMergeSlashes() + }, + want: true, + }, + "non-default entry gets expected PathWithEscapedSlashesAction": { + input: &RequestNormalizationMeshConfig{PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD"}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetPathWithEscapedSlashesAction() + }, + want: PathWithEscapedSlashesAction("UNESCAPE_AND_FORWARD"), + }, + "non-default entry gets expected HeadersWithUnderscoresAction": { + input: &RequestNormalizationMeshConfig{HeadersWithUnderscoresAction: "REJECT_REQUEST"}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetHeadersWithUnderscoresAction() + }, + want: HeadersWithUnderscoresAction("REJECT_REQUEST"), + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.want, tc.getFn(tc.input)) + }) + } +} + +func TestMeshConfigEntry_validateRequestNormalizationMeshConfig(t *testing.T) { + tests := map[string]struct { + input *RequestNormalizationMeshConfig + wantErr string + }{ + "nil entry is valid": { + input: nil, + wantErr: "", + }, + "invalid PathWithEscapedSlashesAction is rejected": { + input: &RequestNormalizationMeshConfig{ + PathWithEscapedSlashesAction: PathWithEscapedSlashesAction("INVALID"), + }, + wantErr: "no matching PathWithEscapedSlashesAction value found for INVALID, please specify one of [IMPLEMENTATION_SPECIFIC_DEFAULT, KEEP_UNCHANGED, REJECT_REQUEST, UNESCAPE_AND_REDIRECT, UNESCAPE_AND_FORWARD]", + }, + "invalid HeadersWithUnderscoresAction is rejected": { + input: &RequestNormalizationMeshConfig{ + HeadersWithUnderscoresAction: HeadersWithUnderscoresAction("INVALID"), + }, + wantErr: "no matching HeadersWithUnderscoresAction value found for INVALID, please specify one of [ALLOW, REJECT_REQUEST, DROP_HEADER]", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + if tc.wantErr == "" { + assert.NoError(t, validateRequestNormalizationMeshConfig(tc.input)) + } else { + assert.EqualError(t, validateRequestNormalizationMeshConfig(tc.input), tc.wantErr) + } + }) + } +} diff --git a/agent/structs/config_entry_test.go b/agent/structs/config_entry_test.go index 4c092acc46e2..978e808be443 100644 --- a/agent/structs/config_entry_test.go +++ b/agent/structs/config_entry_test.go @@ -1910,6 +1910,10 @@ func TestDecodeConfigEntry(t *testing.T) { name = "hdr-suffix" suffix = "suffix" }, + { + name = "hdr-contains" + contains = "contains" + }, { name = "hdr-regex" regex = "regex" @@ -1918,7 +1922,12 @@ func TestDecodeConfigEntry(t *testing.T) { name = "hdr-absent" present = true invert = true - } + }, + { + name = "hdr-ignore-case" + exact = "exact" + ignore_case = true + }, ] } }, @@ -1987,6 +1996,10 @@ func TestDecodeConfigEntry(t *testing.T) { Name = "hdr-suffix" Suffix = "suffix" }, + { + Name = "hdr-contains" + Contains = "contains" + }, { Name = "hdr-regex" Regex = "regex" @@ -1995,6 +2008,11 @@ func TestDecodeConfigEntry(t *testing.T) { Name = "hdr-absent" Present = true Invert = true + }, + { + Name = "hdr-ignore-case" + Exact = "exact" + IgnoreCase = true } ] } @@ -2064,6 +2082,10 @@ func TestDecodeConfigEntry(t *testing.T) { Name: "hdr-suffix", Suffix: "suffix", }, + { + Name: "hdr-contains", + Contains: "contains", + }, { Name: "hdr-regex", Regex: "regex", @@ -2073,6 +2095,11 @@ func TestDecodeConfigEntry(t *testing.T) { Present: true, Invert: true, }, + { + Name: "hdr-ignore-case", + Exact: "exact", + IgnoreCase: true, + }, }, }, }, @@ -2134,7 +2161,7 @@ func TestDecodeConfigEntry(t *testing.T) { }, }, { - name: "mesh", + name: "mesh: kitchen sink", snake: ` kind = "mesh" meta { @@ -2145,6 +2172,7 @@ func TestDecodeConfigEntry(t *testing.T) { mesh_destinations_only = true } allow_enabling_permissive_mutual_tls = true + validate_clusters = true tls { incoming { tls_min_version = "TLSv1_1" @@ -2163,9 +2191,17 @@ func TestDecodeConfigEntry(t *testing.T) { ] } } - http { - sanitize_x_forwarded_client_cert = true - } + http { + sanitize_x_forwarded_client_cert = true + incoming { + request_normalization { + insecure_disable_path_normalization = true + merge_slashes = true + path_with_escaped_slashes_action = "UNESCAPE_AND_FORWARD" + headers_with_underscores_action = "DROP_HEADER" + } + } + } peering { peer_through_mesh_gateways = true } @@ -2180,6 +2216,7 @@ func TestDecodeConfigEntry(t *testing.T) { MeshDestinationsOnly = true } AllowEnablingPermissiveMutualTLS = true + ValidateClusters = true TLS { Incoming { TLSMinVersion = "TLSv1_1" @@ -2198,9 +2235,17 @@ func TestDecodeConfigEntry(t *testing.T) { ] } } - HTTP { - SanitizeXForwardedClientCert = true - } + HTTP { + SanitizeXForwardedClientCert = true + Incoming { + RequestNormalization { + InsecureDisablePathNormalization = true + MergeSlashes = true + PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD" + HeadersWithUnderscoresAction = "DROP_HEADER" + } + } + } Peering { PeerThroughMeshGateways = true } @@ -2214,6 +2259,7 @@ func TestDecodeConfigEntry(t *testing.T) { MeshDestinationsOnly: true, }, AllowEnablingPermissiveMutualTLS: true, + ValidateClusters: true, TLS: &MeshTLSConfig{ Incoming: &MeshDirectionalTLSConfig{ TLSMinVersion: types.TLSv1_1, @@ -2234,6 +2280,14 @@ func TestDecodeConfigEntry(t *testing.T) { }, HTTP: &MeshHTTPConfig{ SanitizeXForwardedClientCert: true, + Incoming: &MeshDirectionalHTTPConfig{ + RequestNormalization: &RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: true, // note: this is the opposite of the recommended default + MergeSlashes: true, + PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD", + HeadersWithUnderscoresAction: "DROP_HEADER", + }, + }, }, Peering: &PeeringMeshConfig{ PeerThroughMeshGateways: true, diff --git a/agent/structs/structs.deepcopy.go b/agent/structs/structs.deepcopy.go index 52621d2c9190..893514538a5b 100644 --- a/agent/structs/structs.deepcopy.go +++ b/agent/structs/structs.deepcopy.go @@ -809,6 +809,14 @@ func (o *MeshConfigEntry) DeepCopy() *MeshConfigEntry { if o.HTTP != nil { cp.HTTP = new(MeshHTTPConfig) *cp.HTTP = *o.HTTP + if o.HTTP.Incoming != nil { + cp.HTTP.Incoming = new(MeshDirectionalHTTPConfig) + *cp.HTTP.Incoming = *o.HTTP.Incoming + if o.HTTP.Incoming.RequestNormalization != nil { + cp.HTTP.Incoming.RequestNormalization = new(RequestNormalizationMeshConfig) + *cp.HTTP.Incoming.RequestNormalization = *o.HTTP.Incoming.RequestNormalization + } + } } if o.Peering != nil { cp.Peering = new(PeeringMeshConfig) diff --git a/agent/xds/listeners.go b/agent/xds/listeners.go index b5e1e781963c..5b01bdc4dfe2 100644 --- a/agent/xds/listeners.go +++ b/agent/xds/listeners.go @@ -1396,6 +1396,7 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot filterOpts.httpAuthzFilters = append(filterOpts.httpAuthzFilters, addMeta) } + setNormalizationOptions(cfgSnap.MeshConfig().GetHTTPIncomingRequestNormalization(), &filterOpts) } // If an inbound connect limit is set, inject a connection limit filter on each chain. @@ -1464,6 +1465,28 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot return l, err } +// setNormalizationOptions sets the normalization options for the listener filter. +// This is only used for inbound listeners today (see MeshHTTPConfig). +func setNormalizationOptions(rn *structs.RequestNormalizationMeshConfig, opts *listenerFilterOpts) { + // Note that these options are _always_ set, not just when rn is non-nil. This enables us to set + // Consul defaults (e.g. InsecureDisablePathNormalization = false) that override Envoy defaults + // (e.g. normalize_path = false). We override defaults here rather than in xDS code s.t. Consul + // defaults are only applied where Consul configuration dictates it should be. + + opts.normalizePath = !rn.GetInsecureDisablePathNormalization() // invert to enable path normalization by default + opts.mergeSlashes = rn.GetMergeSlashes() + if rn.GetPathWithEscapedSlashesAction() != "" { + v := string(rn.GetPathWithEscapedSlashesAction()) + a := envoy_http_v3.HttpConnectionManager_PathWithEscapedSlashesAction_value[v] + opts.pathWithEscapedSlashesAction = envoy_http_v3.HttpConnectionManager_PathWithEscapedSlashesAction(a) + } + if rn.GetHeadersWithUnderscoresAction() != "" { + v := string(rn.GetHeadersWithUnderscoresAction()) + a := envoy_core_v3.HttpProtocolOptions_HeadersWithUnderscoresAction_value[v] + opts.headersWithUnderscoresAction = envoy_core_v3.HttpProtocolOptions_HeadersWithUnderscoresAction(a) + } +} + func makePermissiveFilterChain(cfgSnap *proxycfg.ConfigSnapshot, opts listenerFilterOpts) (*envoy_listener_v3.FilterChain, error) { servicePort := cfgSnap.Proxy.LocalServicePort if servicePort <= 0 { @@ -2365,16 +2388,20 @@ type listenerFilterOpts struct { statPrefix string // HTTP listener filter options - forwardClientDetails bool - forwardClientPolicy envoy_http_v3.HttpConnectionManager_ForwardClientCertDetails - httpAuthzFilters []*envoy_http_v3.HttpFilter - idleTimeoutMs *int - requestTimeoutMs *int - routeName string - routePath string - tracing *envoy_http_v3.HttpConnectionManager_Tracing - useRDS bool - fetchTimeoutRDS *durationpb.Duration + forwardClientDetails bool + forwardClientPolicy envoy_http_v3.HttpConnectionManager_ForwardClientCertDetails + httpAuthzFilters []*envoy_http_v3.HttpFilter + idleTimeoutMs *int + requestTimeoutMs *int + routeName string + routePath string + tracing *envoy_http_v3.HttpConnectionManager_Tracing + normalizePath bool + mergeSlashes bool + pathWithEscapedSlashesAction envoy_http_v3.HttpConnectionManager_PathWithEscapedSlashesAction + headersWithUnderscoresAction envoy_core_v3.HttpProtocolOptions_HeadersWithUnderscoresAction + useRDS bool + fetchTimeoutRDS *durationpb.Duration } func makeListenerFilter(opts listenerFilterOpts) (*envoy_listener_v3.Filter, error) { @@ -2490,6 +2517,19 @@ func makeHTTPFilter(opts listenerFilterOpts) (*envoy_listener_v3.Filter, error) cfg.Tracing = opts.tracing } + // Request normalization + if opts.normalizePath { + cfg.NormalizePath = &wrapperspb.BoolValue{Value: true} + } + cfg.MergeSlashes = opts.mergeSlashes + cfg.PathWithEscapedSlashesAction = opts.pathWithEscapedSlashesAction + if opts.headersWithUnderscoresAction != 0 { // check for non-default to avoid needless instantiation of options + if cfg.CommonHttpProtocolOptions == nil { + cfg.CommonHttpProtocolOptions = &envoy_core_v3.HttpProtocolOptions{} + } + cfg.CommonHttpProtocolOptions.HeadersWithUnderscoresAction = opts.headersWithUnderscoresAction + } + if opts.useRDS { if opts.cluster != "" { return nil, fmt.Errorf("cannot specify cluster name when using RDS") diff --git a/agent/xds/listeners_test.go b/agent/xds/listeners_test.go index cec681a9adeb..757310fc3c16 100644 --- a/agent/xds/listeners_test.go +++ b/agent/xds/listeners_test.go @@ -8,6 +8,8 @@ import ( "testing" "text/template" + envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -369,3 +371,71 @@ func TestGetAlpnProtocols(t *testing.T) { }) } } + +func Test_setNormalizationOptions(t *testing.T) { + tests := map[string]struct { + rn *structs.RequestNormalizationMeshConfig + opts *listenerFilterOpts + want *listenerFilterOpts + }{ + "nil entry": { + rn: nil, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: true, + }, + }, + "empty entry": { + rn: &structs.RequestNormalizationMeshConfig{}, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: true, + }, + }, + "empty is equivalent to defaults": { + rn: &structs.RequestNormalizationMeshConfig{}, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: true, + mergeSlashes: false, + pathWithEscapedSlashesAction: envoy_http_v3.HttpConnectionManager_IMPLEMENTATION_SPECIFIC_DEFAULT, + headersWithUnderscoresAction: envoy_core_v3.HttpProtocolOptions_ALLOW, + }, + }, + "some options": { + rn: &structs.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: false, + MergeSlashes: true, + PathWithEscapedSlashesAction: "", + HeadersWithUnderscoresAction: "DROP_HEADER", + }, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: true, + mergeSlashes: true, + headersWithUnderscoresAction: envoy_core_v3.HttpProtocolOptions_DROP_HEADER, + }, + }, + "all options": { + rn: &structs.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: true, // note: this is the opposite of the recommended default + MergeSlashes: true, + PathWithEscapedSlashesAction: "REJECT_REQUEST", + HeadersWithUnderscoresAction: "DROP_HEADER", + }, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: false, + mergeSlashes: true, + pathWithEscapedSlashesAction: envoy_http_v3.HttpConnectionManager_REJECT_REQUEST, + headersWithUnderscoresAction: envoy_core_v3.HttpProtocolOptions_DROP_HEADER, + }, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + setNormalizationOptions(tc.rn, tc.opts) + assert.Equal(t, tc.want, tc.opts) + }) + } +} diff --git a/agent/xds/rbac.go b/agent/xds/rbac.go index fbae7e95c4c1..09c1cd63c8f0 100644 --- a/agent/xds/rbac.go +++ b/agent/xds/rbac.go @@ -1250,7 +1250,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ Exact: hdr.Exact, }, - IgnoreCase: false, + IgnoreCase: hdr.IgnoreCase, }, } case hdr.Regex != "": @@ -1259,7 +1259,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ SafeRegex: response.MakeEnvoyRegexMatch(hdr.Regex), }, - IgnoreCase: false, + // IgnoreCase is not supported for SafeRegex matching per Envoy docs. }, } @@ -1269,7 +1269,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss MatchPattern: &envoy_matcher_v3.StringMatcher_Prefix{ Prefix: hdr.Prefix, }, - IgnoreCase: false, + IgnoreCase: hdr.IgnoreCase, }, } @@ -1279,7 +1279,17 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss MatchPattern: &envoy_matcher_v3.StringMatcher_Suffix{ Suffix: hdr.Suffix, }, - IgnoreCase: false, + IgnoreCase: hdr.IgnoreCase, + }, + } + + case hdr.Contains != "": + eh.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{ + StringMatch: &envoy_matcher_v3.StringMatcher{ + MatchPattern: &envoy_matcher_v3.StringMatcher_Contains{ + Contains: hdr.Contains, + }, + IgnoreCase: hdr.IgnoreCase, }, } diff --git a/agent/xds/rbac_test.go b/agent/xds/rbac_test.go index b315de28d1ce..399f46301010 100644 --- a/agent/xds/rbac_test.go +++ b/agent/xds/rbac_test.go @@ -786,11 +786,19 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { {Name: "x-bar", Exact: "xyz"}, {Name: "x-dib", Prefix: "gaz"}, {Name: "x-gir", Suffix: "zim"}, + {Name: "x-baz", Contains: "qux"}, {Name: "x-zim", Regex: "gi[rR]"}, + // Present does not support IgnoreCase + {Name: "y-bar", Exact: "xyz", IgnoreCase: true}, + {Name: "y-dib", Prefix: "gaz", IgnoreCase: true}, + {Name: "y-gir", Suffix: "zim", IgnoreCase: true}, + {Name: "y-baz", Contains: "qux", IgnoreCase: true}, + // Regex does not support IgnoreCase {Name: "z-foo", Present: true, Invert: true}, {Name: "z-bar", Exact: "xyz", Invert: true}, {Name: "z-dib", Prefix: "gaz", Invert: true}, {Name: "z-gir", Suffix: "zim", Invert: true}, + {Name: "z-baz", Contains: "qux", Invert: true}, {Name: "z-zim", Regex: "gi[rR]", Invert: true}, }, }, @@ -825,15 +833,25 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { Action: structs.IntentionActionDeny, HTTP: &structs.IntentionHTTPPermission{ Header: []structs.IntentionHTTPHeaderPermission{ + // Valid vanilla match options {Name: "x-foo", Present: true}, {Name: "x-bar", Exact: "xyz"}, {Name: "x-dib", Prefix: "gaz"}, {Name: "x-gir", Suffix: "zim"}, + {Name: "x-baz", Contains: "qux"}, {Name: "x-zim", Regex: "gi[rR]"}, + // Valid ignore case match options + // (Present and Regex do not support IgnoreCase) + {Name: "y-bar", Exact: "xyz", IgnoreCase: true}, + {Name: "y-dib", Prefix: "gaz", IgnoreCase: true}, + {Name: "y-gir", Suffix: "zim", IgnoreCase: true}, + {Name: "y-baz", Contains: "qux", IgnoreCase: true}, + // Valid invert match options {Name: "z-foo", Present: true, Invert: true}, {Name: "z-bar", Exact: "xyz", Invert: true}, {Name: "z-dib", Prefix: "gaz", Invert: true}, {Name: "z-gir", Suffix: "zim", Invert: true}, + {Name: "z-baz", Contains: "qux", Invert: true}, {Name: "z-zim", Regex: "gi[rR]", Invert: true}, }, }, diff --git a/agent/xds/resources_test.go b/agent/xds/resources_test.go index 29ed428da80b..622127a99251 100644 --- a/agent/xds/resources_test.go +++ b/agent/xds/resources_test.go @@ -1835,6 +1835,58 @@ func getCustomConfigurationGoldenTestCases(enterprise bool) []goldenTestCase { }, nil) }, }, + { + // Same as below case, but keeps the recommended default value of InsecureDisablePathNormalization + // to show that the inverse value is reflected in xDS `normalize_path` config. + name: "connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + cfgSnap := proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + // Ensure public inbound listener has HTTP filter so normalization applies. + ns.Proxy.Config["protocol"] = "http" + // Ensure outbound HTTP listener has HTTP filter so we can observe normalization is not applied. + ns.Proxy.Upstreams[0].Config["protocol"] = "http" + }, nil) + cfgSnap.ConnectProxy.MeshConfig = &structs.MeshConfigEntry{ + HTTP: &structs.MeshHTTPConfig{ + Incoming: &structs.MeshDirectionalHTTPConfig{ + RequestNormalization: &structs.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: false, + MergeSlashes: true, + PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD", + HeadersWithUnderscoresAction: "REJECT_REQUEST", + }, + }, + }, + } + return cfgSnap + }, + }, + { + // Same as above case, but inverts the recommended default value of InsecureDisablePathNormalization + // to show that the value is respected when explicitly set (does not set `normalize_path`). + name: "connect-proxy-with-mesh-config-request-normalization-all-consul-options", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + cfgSnap := proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + // Ensure public inbound listener has HTTP filter so normalization applies. + ns.Proxy.Config["protocol"] = "http" + // Ensure outbound HTTP listener has HTTP filter so we can observe normalization is not applied. + ns.Proxy.Upstreams[0].Config["protocol"] = "http" + }, nil) + cfgSnap.ConnectProxy.MeshConfig = &structs.MeshConfigEntry{ + HTTP: &structs.MeshHTTPConfig{ + Incoming: &structs.MeshDirectionalHTTPConfig{ + RequestNormalization: &structs.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: true, // note: this is the opposite of the recommended default + MergeSlashes: true, + PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD", + HeadersWithUnderscoresAction: "REJECT_REQUEST", + }, + }, + }, + } + return cfgSnap + }, + }, } } diff --git a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-grpc-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-grpc-service.latest.golden index 9c7b4d7e6f99..1e0abe2e8e22 100644 --- a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-grpc-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-grpc-service.latest.golden @@ -172,6 +172,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -248,4 +249,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-http-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-http-service.latest.golden index 7a635fc0e462..f36ab9bd4f76 100644 --- a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-http-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-http-service.latest.golden @@ -173,6 +173,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -249,4 +250,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-grpc-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-grpc-service.latest.golden index 978531f301d0..79de5b7ea751 100644 --- a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-grpc-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-grpc-service.latest.golden @@ -196,6 +196,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -272,4 +273,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-http-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-http-service.latest.golden index 11b165f0544b..dcd1f6473ccd 100644 --- a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-http-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-http-service.latest.golden @@ -270,6 +270,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -346,4 +347,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lambda-and-lua-connect-proxy.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lambda-and-lua-connect-proxy.latest.golden index 0d3fcbd8243b..e4ed710e26e8 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lambda-and-lua-connect-proxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lambda-and-lua-connect-proxy.latest.golden @@ -209,6 +209,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -285,4 +286,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-inbound-applies-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-inbound-applies-to-inbound.latest.golden index 11e229356514..327996fc8ba7 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-inbound-applies-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-inbound-applies-to-inbound.latest.golden @@ -164,6 +164,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -240,4 +241,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden index ab7aa39f4de6..48329b29199b 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden @@ -200,6 +200,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -276,4 +277,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden index 096c399d8918..b8eb216fd362 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden @@ -274,6 +274,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -350,4 +351,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams.latest.golden index cbacd52309b6..5f397f4faf4d 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams.latest.golden @@ -200,6 +200,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -276,4 +277,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-inbound.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-inbound.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden index d54a1a90e45b..ac46c9294aac 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden @@ -191,6 +191,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -267,4 +268,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden index d54a1a90e45b..ac46c9294aac 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden @@ -191,6 +191,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -267,4 +268,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/otel-access-logging-http.latest.golden b/agent/xds/testdata/builtin_extension/listeners/otel-access-logging-http.latest.golden index bd0f4691bb22..2192863e8f4f 100644 --- a/agent/xds/testdata/builtin_extension/listeners/otel-access-logging-http.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/otel-access-logging-http.latest.golden @@ -205,6 +205,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -281,4 +282,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-keepalive.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-keepalive.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-keepalive.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-keepalive.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection-multiple.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection-multiple.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection-multiple.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection-multiple.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-round-robin-lb-config.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-round-robin-lb-config.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-round-robin-lb-config.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-round-robin-lb-config.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-inbound-add.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-inbound-add.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-inbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-inbound-add.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-outbound-add.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-outbound-add.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-outbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-outbound-add.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden index 79ed3b50c990..a2637fb045c2 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden @@ -157,6 +157,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -234,4 +235,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-inbound-add.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-inbound-add.latest.golden index 00e176e779f7..b49e8bbc3deb 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-inbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-inbound-add.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -232,4 +233,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-outbound-add.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-outbound-add.latest.golden index ffb8ffc47f97..8b22c6e75fb1 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-outbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-outbound-add.latest.golden @@ -157,6 +157,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -233,4 +234,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden index 79ed3b50c990..a2637fb045c2 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden @@ -157,6 +157,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -234,4 +235,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden index fa5f1bb2bd78..150c780fa90c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden @@ -156,6 +156,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -232,4 +233,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden index 3c57971a7f8b..7db42b9abb7e 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden @@ -178,6 +178,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -254,4 +255,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-remove-outlier-detection.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-remove-outlier-detection.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-remove-outlier-detection.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-remove-outlier-detection.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden b/agent/xds/testdata/builtin_extension/listeners/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden index a23c2e6e2678..fa869cc25ef7 100644 --- a/agent/xds/testdata/builtin_extension/listeners/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden @@ -203,6 +203,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -302,4 +303,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/wasm-http-local-file.latest.golden b/agent/xds/testdata/builtin_extension/listeners/wasm-http-local-file.latest.golden index 4a1c29f1cd9b..75ca9826a8b5 100644 --- a/agent/xds/testdata/builtin_extension/listeners/wasm-http-local-file.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/wasm-http-local-file.latest.golden @@ -176,6 +176,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -252,4 +253,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/wasm-http-remote-file.latest.golden b/agent/xds/testdata/builtin_extension/listeners/wasm-http-remote-file.latest.golden index 224371a5f904..3d168a28ce60 100644 --- a/agent/xds/testdata/builtin_extension/listeners/wasm-http-remote-file.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/wasm-http-remote-file.latest.golden @@ -181,6 +181,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -257,4 +258,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..22df9de55275 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..22df9de55275 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..41ea4a4f0206 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..41ea4a4f0206 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..459678e2a339 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,275 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db.default.default.dc1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "commonHttpProtocolOptions": { + "headersWithUnderscoresAction": "REJECT_REQUEST" + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "trust-domain", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "partition", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "namespace", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "datacenter", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "service", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "mergeSlashes": true, + "pathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "public_listener", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "public_listener", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..92dfd7cc0c44 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,276 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db.default.default.dc1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "commonHttpProtocolOptions": { + "headersWithUnderscoresAction": "REJECT_REQUEST" + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "trust-domain", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "partition", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "namespace", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "datacenter", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "service", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "mergeSlashes": true, + "normalizePath": true, + "pathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "public_listener", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "public_listener", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/listeners/custom-trace-listener.latest.golden b/agent/xds/testdata/listeners/custom-trace-listener.latest.golden index 34b86e6ec73e..f6291296e70c 100644 --- a/agent/xds/testdata/listeners/custom-trace-listener.latest.golden +++ b/agent/xds/testdata/listeners/custom-trace-listener.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -254,4 +255,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/expose-paths-grpc-new-cluster-http1.latest.golden b/agent/xds/testdata/listeners/expose-paths-grpc-new-cluster-http1.latest.golden index 90cb383d20c4..530b60fb5094 100644 --- a/agent/xds/testdata/listeners/expose-paths-grpc-new-cluster-http1.latest.golden +++ b/agent/xds/testdata/listeners/expose-paths-grpc-new-cluster-http1.latest.golden @@ -106,6 +106,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -176,4 +177,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/grpc-public-listener.latest.golden b/agent/xds/testdata/listeners/grpc-public-listener.latest.golden index ac7d70ab1f27..be4df302b490 100644 --- a/agent/xds/testdata/listeners/grpc-public-listener.latest.golden +++ b/agent/xds/testdata/listeners/grpc-public-listener.latest.golden @@ -95,6 +95,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -165,4 +166,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/http-listener-with-timeouts.latest.golden b/agent/xds/testdata/listeners/http-listener-with-timeouts.latest.golden index 5fc6315f6b77..82b73697adf9 100644 --- a/agent/xds/testdata/listeners/http-listener-with-timeouts.latest.golden +++ b/agent/xds/testdata/listeners/http-listener-with-timeouts.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -233,4 +234,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/http-public-listener-no-xfcc.latest.golden b/agent/xds/testdata/listeners/http-public-listener-no-xfcc.latest.golden index 66401ec1169d..d3cd78c70b7c 100644 --- a/agent/xds/testdata/listeners/http-public-listener-no-xfcc.latest.golden +++ b/agent/xds/testdata/listeners/http-public-listener-no-xfcc.latest.golden @@ -81,6 +81,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -150,4 +151,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/http-public-listener.latest.golden b/agent/xds/testdata/listeners/http-public-listener.latest.golden index 575b07e5bf3f..b334e2c0337c 100644 --- a/agent/xds/testdata/listeners/http-public-listener.latest.golden +++ b/agent/xds/testdata/listeners/http-public-listener.latest.golden @@ -155,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -231,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/http2-public-listener.latest.golden b/agent/xds/testdata/listeners/http2-public-listener.latest.golden index c81bd0f97c6c..c659487acbf5 100644 --- a/agent/xds/testdata/listeners/http2-public-listener.latest.golden +++ b/agent/xds/testdata/listeners/http2-public-listener.latest.golden @@ -156,6 +156,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -233,4 +234,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms--httpfilter.golden index 77c138f184d0..b2c1d63a4459 100644 --- a/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms--httpfilter.golden @@ -114,6 +114,14 @@ } } }, + { + "header": { + "name": "x-baz", + "stringMatch": { + "contains": "qux" + } + } + }, { "header": { "name": "x-zim", @@ -124,6 +132,42 @@ } } }, + { + "header": { + "name": "y-bar", + "stringMatch": { + "exact": "xyz", + "ignoreCase": true + } + } + }, + { + "header": { + "name": "y-dib", + "stringMatch": { + "ignoreCase": true, + "prefix": "gaz" + } + } + }, + { + "header": { + "name": "y-gir", + "stringMatch": { + "ignoreCase": true, + "suffix": "zim" + } + } + }, + { + "header": { + "name": "y-baz", + "stringMatch": { + "contains": "qux", + "ignoreCase": true + } + } + }, { "header": { "invertMatch": true, @@ -158,6 +202,15 @@ } } }, + { + "header": { + "invertMatch": true, + "name": "z-baz", + "stringMatch": { + "contains": "qux" + } + } + }, { "header": { "invertMatch": true, @@ -236,4 +289,4 @@ } } } -} \ No newline at end of file +} diff --git a/agent/xds/testdata/rbac/default-deny-single-intention-with-kitchen-sink-perms--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-single-intention-with-kitchen-sink-perms--httpfilter.golden index d83d07ea7a44..7acd057dda6f 100644 --- a/agent/xds/testdata/rbac/default-deny-single-intention-with-kitchen-sink-perms--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-single-intention-with-kitchen-sink-perms--httpfilter.golden @@ -113,6 +113,14 @@ } } }, + { + "header": { + "name": "x-baz", + "stringMatch": { + "contains": "qux" + } + } + }, { "header": { "name": "x-zim", @@ -123,6 +131,42 @@ } } }, + { + "header": { + "name": "y-bar", + "stringMatch": { + "exact": "xyz", + "ignoreCase": true + } + } + }, + { + "header": { + "name": "y-dib", + "stringMatch": { + "ignoreCase": true, + "prefix": "gaz" + } + } + }, + { + "header": { + "name": "y-gir", + "stringMatch": { + "ignoreCase": true, + "suffix": "zim" + } + } + }, + { + "header": { + "name": "y-baz", + "stringMatch": { + "contains": "qux", + "ignoreCase": true + } + } + }, { "header": { "invertMatch": true, @@ -157,6 +201,15 @@ } } }, + { + "header": { + "invertMatch": true, + "name": "z-baz", + "stringMatch": { + "contains": "qux" + } + } + }, { "header": { "invertMatch": true, @@ -235,4 +288,4 @@ } } } -} \ No newline at end of file +} diff --git a/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..df1ae2ff9df7 --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..df1ae2ff9df7 --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..8b587d09eba8 --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..8b587d09eba8 --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} diff --git a/api/config_entry_intentions.go b/api/config_entry_intentions.go index 3f03b0875b9c..642479c1ba53 100644 --- a/api/config_entry_intentions.go +++ b/api/config_entry_intentions.go @@ -63,13 +63,15 @@ type IntentionHTTPPermission struct { } type IntentionHTTPHeaderPermission struct { - Name string - Present bool `json:",omitempty"` - Exact string `json:",omitempty"` - Prefix string `json:",omitempty"` - Suffix string `json:",omitempty"` - Regex string `json:",omitempty"` - Invert bool `json:",omitempty"` + Name string + Present bool `json:",omitempty"` + Exact string `json:",omitempty"` + Prefix string `json:",omitempty"` + Suffix string `json:",omitempty"` + Contains string `json:",omitempty"` + Regex string `json:",omitempty"` + Invert bool `json:",omitempty"` + IgnoreCase bool `json:",omitempty" alias:"ignore_case"` } type IntentionJWTRequirement struct { diff --git a/api/config_entry_mesh.go b/api/config_entry_mesh.go index e035d1596778..647b02b23800 100644 --- a/api/config_entry_mesh.go +++ b/api/config_entry_mesh.go @@ -69,12 +69,53 @@ type MeshDirectionalTLSConfig struct { type MeshHTTPConfig struct { SanitizeXForwardedClientCert bool `alias:"sanitize_x_forwarded_client_cert"` + // Incoming configures settings for incoming HTTP traffic to mesh proxies. + Incoming *MeshDirectionalHTTPConfig `json:",omitempty"` +} + +// MeshDirectionalHTTPConfig holds mesh configuration specific to HTTP +// requests for a given traffic direction. +type MeshDirectionalHTTPConfig struct { + RequestNormalization *RequestNormalizationMeshConfig `json:",omitempty" alias:"request_normalization"` } type PeeringMeshConfig struct { PeerThroughMeshGateways bool `json:",omitempty" alias:"peer_through_mesh_gateways"` } +// RequestNormalizationMeshConfig contains options pertaining to the +// normalization of HTTP requests processed by mesh proxies. +type RequestNormalizationMeshConfig struct { + // InsecureDisablePathNormalization sets the value of the \`normalize_path\` option in the Envoy listener's + // `HttpConnectionManager`. The default value is \`false\`. When set to \`true\` in Consul, \`normalize_path\` is + // set to \`false\` for the Envoy proxy. This parameter disables the normalization of request URL paths according to + // RFC 3986, conversion of \`\\\` to \`/\`, and decoding non-reserved %-encoded characters. When using L7 intentions + // with path match rules, we recommend enabling path normalization in order to avoid match rule circumvention with + // non-normalized path values. + InsecureDisablePathNormalization bool `json:",omitempty" alias:"insecure_disable_path_normalization"` + // MergeSlashes sets the value of the \`merge_slashes\` option in the Envoy listener's \`HttpConnectionManager\`. + // The default value is \`false\`. This option controls the normalization of request URL paths by merging + // consecutive \`/\` characters. This normalization is not part of RFC 3986. When using L7 intentions with path + // match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path + // values, unless legitimate service traffic depends on allowing for repeat \`/\` characters, or upstream services + // are configured to differentiate between single and multiple slashes. + MergeSlashes bool `json:",omitempty" alias:"merge_slashes"` + // PathWithEscapedSlashesAction sets the value of the \`path_with_escaped_slashes_action\` option in the Envoy + // listener's \`HttpConnectionManager\`. The default value of this option is empty, which is equivalent to + // \`IMPLEMENTATION_SPECIFIC_DEFAULT\`. This parameter controls the action taken in response to request URL paths + // with escaped slashes in the path. When using L7 intentions with path match rules, we recommend enabling this + // setting to avoid match rule circumvention through non-normalized path values, unless legitimate service traffic + // depends on allowing for escaped \`/\` or \`\\\` characters, or upstream services are configured to differentiate + // between escaped and unescaped slashes. Refer to the Envoy documentation for more information on available + // options. + PathWithEscapedSlashesAction string `json:",omitempty" alias:"path_with_escaped_slashes_action"` + // HeadersWithUnderscoresAction sets the value of the \`headers_with_underscores_action\` option in the Envoy + // listener's \`HttpConnectionManager\` under \`common_http_protocol_options\`. The default value of this option is + // empty, which is equivalent to \`ALLOW\`. Refer to the Envoy documentation for more information on available + // options. + HeadersWithUnderscoresAction string `json:",omitempty" alias:"headers_with_underscores_action"` +} + func (e *MeshConfigEntry) GetKind() string { return MeshConfig } func (e *MeshConfigEntry) GetName() string { return MeshConfigMesh } func (e *MeshConfigEntry) GetPartition() string { return e.Partition } diff --git a/command/helpers/helpers_test.go b/command/helpers/helpers_test.go index 6479386747ba..27ff1e01c145 100644 --- a/command/helpers/helpers_test.go +++ b/command/helpers/helpers_test.go @@ -2305,6 +2305,10 @@ func TestParseConfigEntry(t *testing.T) { name = "hdr-suffix" suffix = "suffix" }, + { + name = "hdr-contains" + contains = "contains" + }, { name = "hdr-regex" regex = "regex" @@ -2313,7 +2317,12 @@ func TestParseConfigEntry(t *testing.T) { name = "hdr-absent" present = true invert = true - } + }, + { + name = "hdr-ignore-case" + exact = "exact" + ignore_case = true + }, ] } }, @@ -2382,6 +2391,10 @@ func TestParseConfigEntry(t *testing.T) { Name = "hdr-suffix" Suffix = "suffix" }, + { + Name = "hdr-contains" + Contains = "contains" + }, { Name = "hdr-regex" Regex = "regex" @@ -2390,6 +2403,11 @@ func TestParseConfigEntry(t *testing.T) { Name = "hdr-absent" Present = true Invert = true + }, + { + Name = "hdr-ignore-case" + Exact = "exact" + IgnoreCase = true } ] } @@ -2460,6 +2478,10 @@ func TestParseConfigEntry(t *testing.T) { "name": "hdr-suffix", "suffix": "suffix" }, + { + "name": "hdr-contains", + "contains": "contains" + }, { "name": "hdr-regex", "regex": "regex" @@ -2468,6 +2490,11 @@ func TestParseConfigEntry(t *testing.T) { "name": "hdr-absent", "present": true, "invert": true + }, + { + "name": "hdr-ignore-case", + "exact": "exact", + "ignore_case": true } ] } @@ -2542,6 +2569,10 @@ func TestParseConfigEntry(t *testing.T) { "Name": "hdr-suffix", "Suffix": "suffix" }, + { + "Name": "hdr-contains", + "Contains": "contains" + }, { "Name": "hdr-regex", "Regex": "regex" @@ -2550,6 +2581,11 @@ func TestParseConfigEntry(t *testing.T) { "Name": "hdr-absent", "Present": true, "Invert": true + }, + { + "Name": "hdr-ignore-case", + "Exact": "exact", + "IgnoreCase": true } ] } @@ -2623,6 +2659,10 @@ func TestParseConfigEntry(t *testing.T) { Name: "hdr-suffix", Suffix: "suffix", }, + { + Name: "hdr-contains", + Contains: "contains", + }, { Name: "hdr-regex", Regex: "regex", @@ -2632,6 +2672,11 @@ func TestParseConfigEntry(t *testing.T) { Present: true, Invert: true, }, + { + Name: "hdr-ignore-case", + Exact: "exact", + IgnoreCase: true, + }, }, }, }, @@ -2719,7 +2764,7 @@ func TestParseConfigEntry(t *testing.T) { }, }, { - name: "mesh", + name: "mesh: kitchen sink", snake: ` kind = "mesh" meta { @@ -2729,6 +2774,8 @@ func TestParseConfigEntry(t *testing.T) { transparent_proxy { mesh_destinations_only = true } + allow_enabling_permissive_mutual_tls = true + validate_clusters = true tls { incoming { tls_min_version = "TLSv1_1" @@ -2747,6 +2794,20 @@ func TestParseConfigEntry(t *testing.T) { ] } } + http { + sanitize_x_forwarded_client_cert = true + incoming { + request_normalization { + insecure_disable_path_normalization = true + merge_slashes = true + path_with_escaped_slashes_action = "UNESCAPE_AND_FORWARD" + headers_with_underscores_action = "DROP_HEADER" + } + } + } + peering { + peer_through_mesh_gateways = true + } `, camel: ` Kind = "mesh" @@ -2757,6 +2818,8 @@ func TestParseConfigEntry(t *testing.T) { TransparentProxy { MeshDestinationsOnly = true } + AllowEnablingPermissiveMutualTLS = true + ValidateClusters = true TLS { Incoming { TLSMinVersion = "TLSv1_1" @@ -2775,6 +2838,20 @@ func TestParseConfigEntry(t *testing.T) { ] } } + HTTP { + SanitizeXForwardedClientCert = true + Incoming { + RequestNormalization { + InsecureDisablePathNormalization = true + MergeSlashes = true + PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD" + HeadersWithUnderscoresAction = "DROP_HEADER" + } + } + } + Peering { + PeerThroughMeshGateways = true + } `, snakeJSON: ` { @@ -2786,6 +2863,8 @@ func TestParseConfigEntry(t *testing.T) { "transparent_proxy": { "mesh_destinations_only": true }, + "allow_enabling_permissive_mutual_tls": true, + "validate_clusters": true, "tls": { "incoming": { "tls_min_version": "TLSv1_1", @@ -2803,6 +2882,20 @@ func TestParseConfigEntry(t *testing.T) { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" ] } + }, + "http": { + "sanitize_x_forwarded_client_cert": true, + "incoming": { + "request_normalization": { + "insecure_disable_path_normalization": true, + "merge_slashes": true, + "path_with_escaped_slashes_action": "UNESCAPE_AND_FORWARD", + "headers_with_underscores_action": "DROP_HEADER" + } + } + }, + "peering": { + "peer_through_mesh_gateways": true } } `, @@ -2816,6 +2909,8 @@ func TestParseConfigEntry(t *testing.T) { "TransparentProxy": { "MeshDestinationsOnly": true }, + "AllowEnablingPermissiveMutualTLS": true, + "ValidateClusters": true, "TLS": { "Incoming": { "TLSMinVersion": "TLSv1_1", @@ -2833,6 +2928,20 @@ func TestParseConfigEntry(t *testing.T) { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" ] } + }, + "HTTP": { + "SanitizeXForwardedClientCert": true, + "Incoming": { + "RequestNormalization": { + "InsecureDisablePathNormalization": true, + "MergeSlashes": true, + "PathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD", + "HeadersWithUnderscoresAction": "DROP_HEADER" + } + } + }, + "Peering": { + "PeerThroughMeshGateways": true } } `, @@ -2844,6 +2953,8 @@ func TestParseConfigEntry(t *testing.T) { TransparentProxy: api.TransparentProxyMeshConfig{ MeshDestinationsOnly: true, }, + AllowEnablingPermissiveMutualTLS: true, + ValidateClusters: true, TLS: &api.MeshTLSConfig{ Incoming: &api.MeshDirectionalTLSConfig{ TLSMinVersion: "TLSv1_1", @@ -2862,6 +2973,20 @@ func TestParseConfigEntry(t *testing.T) { }, }, }, + HTTP: &api.MeshHTTPConfig{ + SanitizeXForwardedClientCert: true, + Incoming: &api.MeshDirectionalHTTPConfig{ + RequestNormalization: &api.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: true, + MergeSlashes: true, + PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD", + HeadersWithUnderscoresAction: "DROP_HEADER", + }, + }, + }, + Peering: &api.PeeringMeshConfig{ + PeerThroughMeshGateways: true, + }, }, }, { diff --git a/proto/private/pbconfigentry/config_entry.gen.go b/proto/private/pbconfigentry/config_entry.gen.go index 0793a503d219..bfd258249b39 100644 --- a/proto/private/pbconfigentry/config_entry.gen.go +++ b/proto/private/pbconfigentry/config_entry.gen.go @@ -1153,8 +1153,10 @@ func IntentionHTTPHeaderPermissionToStructs(s *IntentionHTTPHeaderPermission, t t.Exact = s.Exact t.Prefix = s.Prefix t.Suffix = s.Suffix + t.Contains = s.Contains t.Regex = s.Regex t.Invert = s.Invert + t.IgnoreCase = s.IgnoreCase } func IntentionHTTPHeaderPermissionFromStructs(t *structs.IntentionHTTPHeaderPermission, s *IntentionHTTPHeaderPermission) { if s == nil { @@ -1165,8 +1167,10 @@ func IntentionHTTPHeaderPermissionFromStructs(t *structs.IntentionHTTPHeaderPerm s.Exact = t.Exact s.Prefix = t.Prefix s.Suffix = t.Suffix + s.Contains = t.Contains s.Regex = t.Regex s.Invert = t.Invert + s.IgnoreCase = t.IgnoreCase } func IntentionHTTPPermissionToStructs(s *IntentionHTTPPermission, t *structs.IntentionHTTPPermission) { if s == nil { @@ -1758,6 +1762,26 @@ func MeshConfigFromStructs(t *structs.MeshConfigEntry, s *MeshConfig) { s.Meta = t.Meta s.Hash = t.Hash } +func MeshDirectionalHTTPConfigToStructs(s *MeshDirectionalHTTPConfig, t *structs.MeshDirectionalHTTPConfig) { + if s == nil { + return + } + if s.RequestNormalization != nil { + var x structs.RequestNormalizationMeshConfig + RequestNormalizationMeshConfigToStructs(s.RequestNormalization, &x) + t.RequestNormalization = &x + } +} +func MeshDirectionalHTTPConfigFromStructs(t *structs.MeshDirectionalHTTPConfig, s *MeshDirectionalHTTPConfig) { + if s == nil { + return + } + if t.RequestNormalization != nil { + var x RequestNormalizationMeshConfig + RequestNormalizationMeshConfigFromStructs(t.RequestNormalization, &x) + s.RequestNormalization = &x + } +} func MeshDirectionalTLSConfigToStructs(s *MeshDirectionalTLSConfig, t *structs.MeshDirectionalTLSConfig) { if s == nil { return @@ -1791,12 +1815,22 @@ func MeshHTTPConfigToStructs(s *MeshHTTPConfig, t *structs.MeshHTTPConfig) { return } t.SanitizeXForwardedClientCert = s.SanitizeXForwardedClientCert + if s.Incoming != nil { + var x structs.MeshDirectionalHTTPConfig + MeshDirectionalHTTPConfigToStructs(s.Incoming, &x) + t.Incoming = &x + } } func MeshHTTPConfigFromStructs(t *structs.MeshHTTPConfig, s *MeshHTTPConfig) { if s == nil { return } s.SanitizeXForwardedClientCert = t.SanitizeXForwardedClientCert + if t.Incoming != nil { + var x MeshDirectionalHTTPConfig + MeshDirectionalHTTPConfigFromStructs(t.Incoming, &x) + s.Incoming = &x + } } func MeshTLSConfigToStructs(s *MeshTLSConfig, t *structs.MeshTLSConfig) { if s == nil { @@ -1916,6 +1950,24 @@ func RemoteJWKSFromStructs(t *structs.RemoteJWKS, s *RemoteJWKS) { s.JWKSCluster = &x } } +func RequestNormalizationMeshConfigToStructs(s *RequestNormalizationMeshConfig, t *structs.RequestNormalizationMeshConfig) { + if s == nil { + return + } + t.InsecureDisablePathNormalization = s.InsecureDisablePathNormalization + t.MergeSlashes = s.MergeSlashes + t.PathWithEscapedSlashesAction = pathWithEscapedSlashesActionToStructs(s.PathWithEscapedSlashesAction) + t.HeadersWithUnderscoresAction = headersWithUnderscoresActionToStructs(s.HeadersWithUnderscoresAction) +} +func RequestNormalizationMeshConfigFromStructs(t *structs.RequestNormalizationMeshConfig, s *RequestNormalizationMeshConfig) { + if s == nil { + return + } + s.InsecureDisablePathNormalization = t.InsecureDisablePathNormalization + s.MergeSlashes = t.MergeSlashes + s.PathWithEscapedSlashesAction = pathWithEscapedSlashesActionFromStructs(t.PathWithEscapedSlashesAction) + s.HeadersWithUnderscoresAction = headersWithUnderscoresActionFromStructs(t.HeadersWithUnderscoresAction) +} func ResourceReferenceToStructs(s *ResourceReference, t *structs.ResourceReference) { if s == nil { return diff --git a/proto/private/pbconfigentry/config_entry.go b/proto/private/pbconfigentry/config_entry.go index 37b26e34654d..1b62542d9fd5 100644 --- a/proto/private/pbconfigentry/config_entry.go +++ b/proto/private/pbconfigentry/config_entry.go @@ -291,6 +291,66 @@ func cipherSuitesFromStructs(cs []types.TLSCipherSuite) []string { return cipherSuites } +func pathWithEscapedSlashesActionFromStructs(a structs.PathWithEscapedSlashesAction) PathWithEscapedSlashesAction { + switch a { + case structs.PathWithEscapedSlashesActionDefault: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault + case structs.PathWithEscapedSlashesActionKeep: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionKeep + case structs.PathWithEscapedSlashesActionReject: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionReject + case structs.PathWithEscapedSlashesActionUnescapeAndRedirect: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndRedirect + case structs.PathWithEscapedSlashesActionUnescapeAndForward: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndForward + default: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault + } +} + +func pathWithEscapedSlashesActionToStructs(a PathWithEscapedSlashesAction) structs.PathWithEscapedSlashesAction { + switch a { + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault: + return structs.PathWithEscapedSlashesActionDefault + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionKeep: + return structs.PathWithEscapedSlashesActionKeep + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionReject: + return structs.PathWithEscapedSlashesActionReject + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndRedirect: + return structs.PathWithEscapedSlashesActionUnescapeAndRedirect + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndForward: + return structs.PathWithEscapedSlashesActionUnescapeAndForward + default: + return structs.PathWithEscapedSlashesActionDefault + } +} + +func headersWithUnderscoresActionFromStructs(a structs.HeadersWithUnderscoresAction) HeadersWithUnderscoresAction { + switch a { + case structs.HeadersWithUnderscoresActionAllow: + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow + case structs.HeadersWithUnderscoresActionRejectRequest: + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionRejectRequest + case structs.HeadersWithUnderscoresActionDropHeader: + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionDropHeader + default: + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow + } +} + +func headersWithUnderscoresActionToStructs(a HeadersWithUnderscoresAction) structs.HeadersWithUnderscoresAction { + switch a { + case HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow: + return structs.HeadersWithUnderscoresActionAllow + case HeadersWithUnderscoresAction_HeadersWithUnderscoresActionRejectRequest: + return structs.HeadersWithUnderscoresActionRejectRequest + case HeadersWithUnderscoresAction_HeadersWithUnderscoresActionDropHeader: + return structs.HeadersWithUnderscoresActionDropHeader + default: + return structs.HeadersWithUnderscoresActionAllow + } +} + func enterpriseMetaToStructs(m *pbcommon.EnterpriseMeta) acl.EnterpriseMeta { var entMeta acl.EnterpriseMeta pbcommon.EnterpriseMetaToStructs(m, &entMeta) diff --git a/proto/private/pbconfigentry/config_entry.pb.binary.go b/proto/private/pbconfigentry/config_entry.pb.binary.go index f131eed9e455..194d02a85eb3 100644 --- a/proto/private/pbconfigentry/config_entry.pb.binary.go +++ b/proto/private/pbconfigentry/config_entry.pb.binary.go @@ -107,6 +107,16 @@ func (msg *MeshHTTPConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *MeshDirectionalHTTPConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *MeshDirectionalHTTPConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *PeeringMeshConfig) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) @@ -117,6 +127,16 @@ func (msg *PeeringMeshConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *RequestNormalizationMeshConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *RequestNormalizationMeshConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *ServiceResolver) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) diff --git a/proto/private/pbconfigentry/config_entry.pb.go b/proto/private/pbconfigentry/config_entry.pb.go index 7bdb0c0303a0..508cdc7cfa3c 100644 --- a/proto/private/pbconfigentry/config_entry.pb.go +++ b/proto/private/pbconfigentry/config_entry.pb.go @@ -112,6 +112,110 @@ func (Kind) EnumDescriptor() ([]byte, []int) { return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{0} } +type PathWithEscapedSlashesAction int32 + +const ( + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault PathWithEscapedSlashesAction = 0 + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionKeep PathWithEscapedSlashesAction = 1 + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionReject PathWithEscapedSlashesAction = 2 + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndRedirect PathWithEscapedSlashesAction = 3 + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndForward PathWithEscapedSlashesAction = 4 +) + +// Enum value maps for PathWithEscapedSlashesAction. +var ( + PathWithEscapedSlashesAction_name = map[int32]string{ + 0: "PathWithEscapedSlashesActionDefault", + 1: "PathWithEscapedSlashesActionKeep", + 2: "PathWithEscapedSlashesActionReject", + 3: "PathWithEscapedSlashesActionUnescapeAndRedirect", + 4: "PathWithEscapedSlashesActionUnescapeAndForward", + } + PathWithEscapedSlashesAction_value = map[string]int32{ + "PathWithEscapedSlashesActionDefault": 0, + "PathWithEscapedSlashesActionKeep": 1, + "PathWithEscapedSlashesActionReject": 2, + "PathWithEscapedSlashesActionUnescapeAndRedirect": 3, + "PathWithEscapedSlashesActionUnescapeAndForward": 4, + } +) + +func (x PathWithEscapedSlashesAction) Enum() *PathWithEscapedSlashesAction { + p := new(PathWithEscapedSlashesAction) + *p = x + return p +} + +func (x PathWithEscapedSlashesAction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PathWithEscapedSlashesAction) Descriptor() protoreflect.EnumDescriptor { + return file_private_pbconfigentry_config_entry_proto_enumTypes[1].Descriptor() +} + +func (PathWithEscapedSlashesAction) Type() protoreflect.EnumType { + return &file_private_pbconfigentry_config_entry_proto_enumTypes[1] +} + +func (x PathWithEscapedSlashesAction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PathWithEscapedSlashesAction.Descriptor instead. +func (PathWithEscapedSlashesAction) EnumDescriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{1} +} + +type HeadersWithUnderscoresAction int32 + +const ( + HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow HeadersWithUnderscoresAction = 0 + HeadersWithUnderscoresAction_HeadersWithUnderscoresActionRejectRequest HeadersWithUnderscoresAction = 1 + HeadersWithUnderscoresAction_HeadersWithUnderscoresActionDropHeader HeadersWithUnderscoresAction = 2 +) + +// Enum value maps for HeadersWithUnderscoresAction. +var ( + HeadersWithUnderscoresAction_name = map[int32]string{ + 0: "HeadersWithUnderscoresActionAllow", + 1: "HeadersWithUnderscoresActionRejectRequest", + 2: "HeadersWithUnderscoresActionDropHeader", + } + HeadersWithUnderscoresAction_value = map[string]int32{ + "HeadersWithUnderscoresActionAllow": 0, + "HeadersWithUnderscoresActionRejectRequest": 1, + "HeadersWithUnderscoresActionDropHeader": 2, + } +) + +func (x HeadersWithUnderscoresAction) Enum() *HeadersWithUnderscoresAction { + p := new(HeadersWithUnderscoresAction) + *p = x + return p +} + +func (x HeadersWithUnderscoresAction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HeadersWithUnderscoresAction) Descriptor() protoreflect.EnumDescriptor { + return file_private_pbconfigentry_config_entry_proto_enumTypes[2].Descriptor() +} + +func (HeadersWithUnderscoresAction) Type() protoreflect.EnumType { + return &file_private_pbconfigentry_config_entry_proto_enumTypes[2] +} + +func (x HeadersWithUnderscoresAction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HeadersWithUnderscoresAction.Descriptor instead. +func (HeadersWithUnderscoresAction) EnumDescriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{2} +} + type IntentionAction int32 const ( @@ -142,11 +246,11 @@ func (x IntentionAction) String() string { } func (IntentionAction) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[1].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[3].Descriptor() } func (IntentionAction) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[1] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[3] } func (x IntentionAction) Number() protoreflect.EnumNumber { @@ -155,7 +259,7 @@ func (x IntentionAction) Number() protoreflect.EnumNumber { // Deprecated: Use IntentionAction.Descriptor instead. func (IntentionAction) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{1} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{3} } type IntentionSourceType int32 @@ -185,11 +289,11 @@ func (x IntentionSourceType) String() string { } func (IntentionSourceType) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[2].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[4].Descriptor() } func (IntentionSourceType) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[2] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[4] } func (x IntentionSourceType) Number() protoreflect.EnumNumber { @@ -198,7 +302,7 @@ func (x IntentionSourceType) Number() protoreflect.EnumNumber { // Deprecated: Use IntentionSourceType.Descriptor instead. func (IntentionSourceType) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{2} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{4} } type ProxyMode int32 @@ -234,11 +338,11 @@ func (x ProxyMode) String() string { } func (ProxyMode) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[3].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[5].Descriptor() } func (ProxyMode) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[3] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[5] } func (x ProxyMode) Number() protoreflect.EnumNumber { @@ -247,7 +351,7 @@ func (x ProxyMode) Number() protoreflect.EnumNumber { // Deprecated: Use ProxyMode.Descriptor instead. func (ProxyMode) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{3} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{5} } type MutualTLSMode int32 @@ -283,11 +387,11 @@ func (x MutualTLSMode) String() string { } func (MutualTLSMode) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[4].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[6].Descriptor() } func (MutualTLSMode) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[4] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[6] } func (x MutualTLSMode) Number() protoreflect.EnumNumber { @@ -296,7 +400,7 @@ func (x MutualTLSMode) Number() protoreflect.EnumNumber { // Deprecated: Use MutualTLSMode.Descriptor instead. func (MutualTLSMode) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{4} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{6} } type MeshGatewayMode int32 @@ -335,11 +439,11 @@ func (x MeshGatewayMode) String() string { } func (MeshGatewayMode) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[5].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[7].Descriptor() } func (MeshGatewayMode) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[5] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[7] } func (x MeshGatewayMode) Number() protoreflect.EnumNumber { @@ -348,7 +452,7 @@ func (x MeshGatewayMode) Number() protoreflect.EnumNumber { // Deprecated: Use MeshGatewayMode.Descriptor instead. func (MeshGatewayMode) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{5} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{7} } type APIGatewayListenerProtocol int32 @@ -381,11 +485,11 @@ func (x APIGatewayListenerProtocol) String() string { } func (APIGatewayListenerProtocol) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[6].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[8].Descriptor() } func (APIGatewayListenerProtocol) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[6] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[8] } func (x APIGatewayListenerProtocol) Number() protoreflect.EnumNumber { @@ -394,7 +498,7 @@ func (x APIGatewayListenerProtocol) Number() protoreflect.EnumNumber { // Deprecated: Use APIGatewayListenerProtocol.Descriptor instead. func (APIGatewayListenerProtocol) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{6} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{8} } type HTTPMatchMethod int32 @@ -451,11 +555,11 @@ func (x HTTPMatchMethod) String() string { } func (HTTPMatchMethod) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[7].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[9].Descriptor() } func (HTTPMatchMethod) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[7] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[9] } func (x HTTPMatchMethod) Number() protoreflect.EnumNumber { @@ -464,7 +568,7 @@ func (x HTTPMatchMethod) Number() protoreflect.EnumNumber { // Deprecated: Use HTTPMatchMethod.Descriptor instead. func (HTTPMatchMethod) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{7} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{9} } type HTTPHeaderMatchType int32 @@ -506,11 +610,11 @@ func (x HTTPHeaderMatchType) String() string { } func (HTTPHeaderMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[8].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[10].Descriptor() } func (HTTPHeaderMatchType) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[8] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[10] } func (x HTTPHeaderMatchType) Number() protoreflect.EnumNumber { @@ -519,7 +623,7 @@ func (x HTTPHeaderMatchType) Number() protoreflect.EnumNumber { // Deprecated: Use HTTPHeaderMatchType.Descriptor instead. func (HTTPHeaderMatchType) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{8} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{10} } type HTTPPathMatchType int32 @@ -555,11 +659,11 @@ func (x HTTPPathMatchType) String() string { } func (HTTPPathMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[9].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[11].Descriptor() } func (HTTPPathMatchType) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[9] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[11] } func (x HTTPPathMatchType) Number() protoreflect.EnumNumber { @@ -568,7 +672,7 @@ func (x HTTPPathMatchType) Number() protoreflect.EnumNumber { // Deprecated: Use HTTPPathMatchType.Descriptor instead. func (HTTPPathMatchType) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{9} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{11} } type HTTPQueryMatchType int32 @@ -604,11 +708,11 @@ func (x HTTPQueryMatchType) String() string { } func (HTTPQueryMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[10].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[12].Descriptor() } func (HTTPQueryMatchType) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[10] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[12] } func (x HTTPQueryMatchType) Number() protoreflect.EnumNumber { @@ -617,7 +721,7 @@ func (x HTTPQueryMatchType) Number() protoreflect.EnumNumber { // Deprecated: Use HTTPQueryMatchType.Descriptor instead. func (HTTPQueryMatchType) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{10} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{12} } type GetResolvedExportedServicesRequest struct { @@ -1415,7 +1519,8 @@ type MeshHTTPConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SanitizeXForwardedClientCert bool `protobuf:"varint,1,opt,name=SanitizeXForwardedClientCert,proto3" json:"SanitizeXForwardedClientCert,omitempty"` + SanitizeXForwardedClientCert bool `protobuf:"varint,1,opt,name=SanitizeXForwardedClientCert,proto3" json:"SanitizeXForwardedClientCert,omitempty"` + Incoming *MeshDirectionalHTTPConfig `protobuf:"bytes,2,opt,name=Incoming,proto3" json:"Incoming,omitempty"` } func (x *MeshHTTPConfig) Reset() { @@ -1457,6 +1562,65 @@ func (x *MeshHTTPConfig) GetSanitizeXForwardedClientCert() bool { return false } +func (x *MeshHTTPConfig) GetIncoming() *MeshDirectionalHTTPConfig { + if x != nil { + return x.Incoming + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.MeshDirectionalHTTPConfig +// output=config_entry.gen.go +// name=Structs +type MeshDirectionalHTTPConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestNormalization *RequestNormalizationMeshConfig `protobuf:"bytes,1,opt,name=RequestNormalization,proto3" json:"RequestNormalization,omitempty"` +} + +func (x *MeshDirectionalHTTPConfig) Reset() { + *x = MeshDirectionalHTTPConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MeshDirectionalHTTPConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MeshDirectionalHTTPConfig) ProtoMessage() {} + +func (x *MeshDirectionalHTTPConfig) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[10] + 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 MeshDirectionalHTTPConfig.ProtoReflect.Descriptor instead. +func (*MeshDirectionalHTTPConfig) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{10} +} + +func (x *MeshDirectionalHTTPConfig) GetRequestNormalization() *RequestNormalizationMeshConfig { + if x != nil { + return x.RequestNormalization + } + return nil +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.PeeringMeshConfig @@ -1473,7 +1637,7 @@ type PeeringMeshConfig struct { func (x *PeeringMeshConfig) Reset() { *x = PeeringMeshConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[10] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1486,7 +1650,7 @@ func (x *PeeringMeshConfig) String() string { func (*PeeringMeshConfig) ProtoMessage() {} func (x *PeeringMeshConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[10] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1499,7 +1663,7 @@ func (x *PeeringMeshConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use PeeringMeshConfig.ProtoReflect.Descriptor instead. func (*PeeringMeshConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{10} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{11} } func (x *PeeringMeshConfig) GetPeerThroughMeshGateways() bool { @@ -1509,6 +1673,84 @@ func (x *PeeringMeshConfig) GetPeerThroughMeshGateways() bool { return false } +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.RequestNormalizationMeshConfig +// output=config_entry.gen.go +// name=Structs +type RequestNormalizationMeshConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InsecureDisablePathNormalization bool `protobuf:"varint,1,opt,name=InsecureDisablePathNormalization,proto3" json:"InsecureDisablePathNormalization,omitempty"` + MergeSlashes bool `protobuf:"varint,2,opt,name=MergeSlashes,proto3" json:"MergeSlashes,omitempty"` + // mog: func-to=pathWithEscapedSlashesActionToStructs func-from=pathWithEscapedSlashesActionFromStructs + PathWithEscapedSlashesAction PathWithEscapedSlashesAction `protobuf:"varint,3,opt,name=PathWithEscapedSlashesAction,proto3,enum=hashicorp.consul.internal.configentry.PathWithEscapedSlashesAction" json:"PathWithEscapedSlashesAction,omitempty"` + // mog: func-to=headersWithUnderscoresActionToStructs func-from=headersWithUnderscoresActionFromStructs + HeadersWithUnderscoresAction HeadersWithUnderscoresAction `protobuf:"varint,4,opt,name=HeadersWithUnderscoresAction,proto3,enum=hashicorp.consul.internal.configentry.HeadersWithUnderscoresAction" json:"HeadersWithUnderscoresAction,omitempty"` +} + +func (x *RequestNormalizationMeshConfig) Reset() { + *x = RequestNormalizationMeshConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestNormalizationMeshConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestNormalizationMeshConfig) ProtoMessage() {} + +func (x *RequestNormalizationMeshConfig) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[12] + 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 RequestNormalizationMeshConfig.ProtoReflect.Descriptor instead. +func (*RequestNormalizationMeshConfig) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{12} +} + +func (x *RequestNormalizationMeshConfig) GetInsecureDisablePathNormalization() bool { + if x != nil { + return x.InsecureDisablePathNormalization + } + return false +} + +func (x *RequestNormalizationMeshConfig) GetMergeSlashes() bool { + if x != nil { + return x.MergeSlashes + } + return false +} + +func (x *RequestNormalizationMeshConfig) GetPathWithEscapedSlashesAction() PathWithEscapedSlashesAction { + if x != nil { + return x.PathWithEscapedSlashesAction + } + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault +} + +func (x *RequestNormalizationMeshConfig) GetHeadersWithUnderscoresAction() HeadersWithUnderscoresAction { + if x != nil { + return x.HeadersWithUnderscoresAction + } + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.ServiceResolverConfigEntry @@ -1537,7 +1779,7 @@ type ServiceResolver struct { func (x *ServiceResolver) Reset() { *x = ServiceResolver{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[11] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1550,7 +1792,7 @@ func (x *ServiceResolver) String() string { func (*ServiceResolver) ProtoMessage() {} func (x *ServiceResolver) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[11] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1563,7 +1805,7 @@ func (x *ServiceResolver) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolver.ProtoReflect.Descriptor instead. func (*ServiceResolver) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{11} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{13} } func (x *ServiceResolver) GetDefaultSubset() string { @@ -1653,7 +1895,7 @@ type ServiceResolverSubset struct { func (x *ServiceResolverSubset) Reset() { *x = ServiceResolverSubset{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[12] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1666,7 +1908,7 @@ func (x *ServiceResolverSubset) String() string { func (*ServiceResolverSubset) ProtoMessage() {} func (x *ServiceResolverSubset) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[12] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1679,7 +1921,7 @@ func (x *ServiceResolverSubset) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverSubset.ProtoReflect.Descriptor instead. func (*ServiceResolverSubset) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{12} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{14} } func (x *ServiceResolverSubset) GetFilter() string { @@ -1718,7 +1960,7 @@ type ServiceResolverRedirect struct { func (x *ServiceResolverRedirect) Reset() { *x = ServiceResolverRedirect{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[13] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1731,7 +1973,7 @@ func (x *ServiceResolverRedirect) String() string { func (*ServiceResolverRedirect) ProtoMessage() {} func (x *ServiceResolverRedirect) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[13] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1744,7 +1986,7 @@ func (x *ServiceResolverRedirect) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverRedirect.ProtoReflect.Descriptor instead. func (*ServiceResolverRedirect) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{13} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{15} } func (x *ServiceResolverRedirect) GetService() string { @@ -1818,7 +2060,7 @@ type ServiceResolverFailover struct { func (x *ServiceResolverFailover) Reset() { *x = ServiceResolverFailover{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[14] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1831,7 +2073,7 @@ func (x *ServiceResolverFailover) String() string { func (*ServiceResolverFailover) ProtoMessage() {} func (x *ServiceResolverFailover) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[14] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1844,7 +2086,7 @@ func (x *ServiceResolverFailover) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverFailover.ProtoReflect.Descriptor instead. func (*ServiceResolverFailover) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{14} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{16} } func (x *ServiceResolverFailover) GetService() string { @@ -1913,7 +2155,7 @@ type ServiceResolverFailoverPolicy struct { func (x *ServiceResolverFailoverPolicy) Reset() { *x = ServiceResolverFailoverPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[15] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1926,7 +2168,7 @@ func (x *ServiceResolverFailoverPolicy) String() string { func (*ServiceResolverFailoverPolicy) ProtoMessage() {} func (x *ServiceResolverFailoverPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[15] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1939,7 +2181,7 @@ func (x *ServiceResolverFailoverPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverFailoverPolicy.ProtoReflect.Descriptor instead. func (*ServiceResolverFailoverPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{15} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{17} } func (x *ServiceResolverFailoverPolicy) GetMode() string { @@ -1972,7 +2214,7 @@ type ServiceResolverPrioritizeByLocality struct { func (x *ServiceResolverPrioritizeByLocality) Reset() { *x = ServiceResolverPrioritizeByLocality{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[16] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1985,7 +2227,7 @@ func (x *ServiceResolverPrioritizeByLocality) String() string { func (*ServiceResolverPrioritizeByLocality) ProtoMessage() {} func (x *ServiceResolverPrioritizeByLocality) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[16] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1998,7 +2240,7 @@ func (x *ServiceResolverPrioritizeByLocality) ProtoReflect() protoreflect.Messag // Deprecated: Use ServiceResolverPrioritizeByLocality.ProtoReflect.Descriptor instead. func (*ServiceResolverPrioritizeByLocality) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{16} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{18} } func (x *ServiceResolverPrioritizeByLocality) GetMode() string { @@ -2029,7 +2271,7 @@ type ServiceResolverFailoverTarget struct { func (x *ServiceResolverFailoverTarget) Reset() { *x = ServiceResolverFailoverTarget{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[17] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2042,7 +2284,7 @@ func (x *ServiceResolverFailoverTarget) String() string { func (*ServiceResolverFailoverTarget) ProtoMessage() {} func (x *ServiceResolverFailoverTarget) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[17] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2055,7 +2297,7 @@ func (x *ServiceResolverFailoverTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverFailoverTarget.ProtoReflect.Descriptor instead. func (*ServiceResolverFailoverTarget) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{17} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{19} } func (x *ServiceResolverFailoverTarget) GetService() string { @@ -2119,7 +2361,7 @@ type LoadBalancer struct { func (x *LoadBalancer) Reset() { *x = LoadBalancer{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[18] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2132,7 +2374,7 @@ func (x *LoadBalancer) String() string { func (*LoadBalancer) ProtoMessage() {} func (x *LoadBalancer) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[18] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2145,7 +2387,7 @@ func (x *LoadBalancer) ProtoReflect() protoreflect.Message { // Deprecated: Use LoadBalancer.ProtoReflect.Descriptor instead. func (*LoadBalancer) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{18} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{20} } func (x *LoadBalancer) GetPolicy() string { @@ -2193,7 +2435,7 @@ type RingHashConfig struct { func (x *RingHashConfig) Reset() { *x = RingHashConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[19] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2206,7 +2448,7 @@ func (x *RingHashConfig) String() string { func (*RingHashConfig) ProtoMessage() {} func (x *RingHashConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[19] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2219,7 +2461,7 @@ func (x *RingHashConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RingHashConfig.ProtoReflect.Descriptor instead. func (*RingHashConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{19} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{21} } func (x *RingHashConfig) GetMinimumRingSize() uint64 { @@ -2252,7 +2494,7 @@ type LeastRequestConfig struct { func (x *LeastRequestConfig) Reset() { *x = LeastRequestConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[20] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2265,7 +2507,7 @@ func (x *LeastRequestConfig) String() string { func (*LeastRequestConfig) ProtoMessage() {} func (x *LeastRequestConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[20] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2278,7 +2520,7 @@ func (x *LeastRequestConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use LeastRequestConfig.ProtoReflect.Descriptor instead. func (*LeastRequestConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{20} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{22} } func (x *LeastRequestConfig) GetChoiceCount() uint32 { @@ -2308,7 +2550,7 @@ type HashPolicy struct { func (x *HashPolicy) Reset() { *x = HashPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[21] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2321,7 +2563,7 @@ func (x *HashPolicy) String() string { func (*HashPolicy) ProtoMessage() {} func (x *HashPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[21] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2334,7 +2576,7 @@ func (x *HashPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use HashPolicy.ProtoReflect.Descriptor instead. func (*HashPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{21} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{23} } func (x *HashPolicy) GetField() string { @@ -2391,7 +2633,7 @@ type CookieConfig struct { func (x *CookieConfig) Reset() { *x = CookieConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[22] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2404,7 +2646,7 @@ func (x *CookieConfig) String() string { func (*CookieConfig) ProtoMessage() {} func (x *CookieConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[22] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2417,7 +2659,7 @@ func (x *CookieConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use CookieConfig.ProtoReflect.Descriptor instead. func (*CookieConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{22} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{24} } func (x *CookieConfig) GetSession() bool { @@ -2462,7 +2704,7 @@ type IngressGateway struct { func (x *IngressGateway) Reset() { *x = IngressGateway{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[23] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2475,7 +2717,7 @@ func (x *IngressGateway) String() string { func (*IngressGateway) ProtoMessage() {} func (x *IngressGateway) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[23] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2488,7 +2730,7 @@ func (x *IngressGateway) ProtoReflect() protoreflect.Message { // Deprecated: Use IngressGateway.ProtoReflect.Descriptor instead. func (*IngressGateway) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{23} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{25} } func (x *IngressGateway) GetTLS() *GatewayTLSConfig { @@ -2545,7 +2787,7 @@ type IngressServiceConfig struct { func (x *IngressServiceConfig) Reset() { *x = IngressServiceConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[24] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2558,7 +2800,7 @@ func (x *IngressServiceConfig) String() string { func (*IngressServiceConfig) ProtoMessage() {} func (x *IngressServiceConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[24] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2571,7 +2813,7 @@ func (x *IngressServiceConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use IngressServiceConfig.ProtoReflect.Descriptor instead. func (*IngressServiceConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{24} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{26} } func (x *IngressServiceConfig) GetMaxConnections() uint32 { @@ -2625,7 +2867,7 @@ type GatewayTLSConfig struct { func (x *GatewayTLSConfig) Reset() { *x = GatewayTLSConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[25] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2638,7 +2880,7 @@ func (x *GatewayTLSConfig) String() string { func (*GatewayTLSConfig) ProtoMessage() {} func (x *GatewayTLSConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[25] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2651,7 +2893,7 @@ func (x *GatewayTLSConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayTLSConfig.ProtoReflect.Descriptor instead. func (*GatewayTLSConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{25} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{27} } func (x *GatewayTLSConfig) GetEnabled() bool { @@ -2706,7 +2948,7 @@ type GatewayTLSSDSConfig struct { func (x *GatewayTLSSDSConfig) Reset() { *x = GatewayTLSSDSConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[26] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2719,7 +2961,7 @@ func (x *GatewayTLSSDSConfig) String() string { func (*GatewayTLSSDSConfig) ProtoMessage() {} func (x *GatewayTLSSDSConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[26] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2732,7 +2974,7 @@ func (x *GatewayTLSSDSConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayTLSSDSConfig.ProtoReflect.Descriptor instead. func (*GatewayTLSSDSConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{26} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{28} } func (x *GatewayTLSSDSConfig) GetClusterName() string { @@ -2769,7 +3011,7 @@ type IngressListener struct { func (x *IngressListener) Reset() { *x = IngressListener{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[27] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2782,7 +3024,7 @@ func (x *IngressListener) String() string { func (*IngressListener) ProtoMessage() {} func (x *IngressListener) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[27] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2795,7 +3037,7 @@ func (x *IngressListener) ProtoReflect() protoreflect.Message { // Deprecated: Use IngressListener.ProtoReflect.Descriptor instead. func (*IngressListener) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{27} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{29} } func (x *IngressListener) GetPort() int32 { @@ -2853,7 +3095,7 @@ type IngressService struct { func (x *IngressService) Reset() { *x = IngressService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[28] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2866,7 +3108,7 @@ func (x *IngressService) String() string { func (*IngressService) ProtoMessage() {} func (x *IngressService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[28] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2879,7 +3121,7 @@ func (x *IngressService) ProtoReflect() protoreflect.Message { // Deprecated: Use IngressService.ProtoReflect.Descriptor instead. func (*IngressService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{28} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{30} } func (x *IngressService) GetName() string { @@ -2975,7 +3217,7 @@ type GatewayServiceTLSConfig struct { func (x *GatewayServiceTLSConfig) Reset() { *x = GatewayServiceTLSConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[29] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2988,7 +3230,7 @@ func (x *GatewayServiceTLSConfig) String() string { func (*GatewayServiceTLSConfig) ProtoMessage() {} func (x *GatewayServiceTLSConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[29] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3001,7 +3243,7 @@ func (x *GatewayServiceTLSConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayServiceTLSConfig.ProtoReflect.Descriptor instead. func (*GatewayServiceTLSConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{29} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{31} } func (x *GatewayServiceTLSConfig) GetSDS() *GatewayTLSSDSConfig { @@ -3029,7 +3271,7 @@ type HTTPHeaderModifiers struct { func (x *HTTPHeaderModifiers) Reset() { *x = HTTPHeaderModifiers{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[30] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3042,7 +3284,7 @@ func (x *HTTPHeaderModifiers) String() string { func (*HTTPHeaderModifiers) ProtoMessage() {} func (x *HTTPHeaderModifiers) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[30] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3055,7 +3297,7 @@ func (x *HTTPHeaderModifiers) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPHeaderModifiers.ProtoReflect.Descriptor instead. func (*HTTPHeaderModifiers) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{30} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{32} } func (x *HTTPHeaderModifiers) GetAdd() map[string]string { @@ -3099,7 +3341,7 @@ type ServiceIntentions struct { func (x *ServiceIntentions) Reset() { *x = ServiceIntentions{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[31] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3112,7 +3354,7 @@ func (x *ServiceIntentions) String() string { func (*ServiceIntentions) ProtoMessage() {} func (x *ServiceIntentions) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[31] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3125,7 +3367,7 @@ func (x *ServiceIntentions) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceIntentions.ProtoReflect.Descriptor instead. func (*ServiceIntentions) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{31} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{33} } func (x *ServiceIntentions) GetSources() []*SourceIntention { @@ -3172,7 +3414,7 @@ type IntentionJWTRequirement struct { func (x *IntentionJWTRequirement) Reset() { *x = IntentionJWTRequirement{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[32] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3185,7 +3427,7 @@ func (x *IntentionJWTRequirement) String() string { func (*IntentionJWTRequirement) ProtoMessage() {} func (x *IntentionJWTRequirement) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[32] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3198,7 +3440,7 @@ func (x *IntentionJWTRequirement) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionJWTRequirement.ProtoReflect.Descriptor instead. func (*IntentionJWTRequirement) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{32} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{34} } func (x *IntentionJWTRequirement) GetProviders() []*IntentionJWTProvider { @@ -3225,7 +3467,7 @@ type IntentionJWTProvider struct { func (x *IntentionJWTProvider) Reset() { *x = IntentionJWTProvider{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[33] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3238,7 +3480,7 @@ func (x *IntentionJWTProvider) String() string { func (*IntentionJWTProvider) ProtoMessage() {} func (x *IntentionJWTProvider) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[33] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3251,7 +3493,7 @@ func (x *IntentionJWTProvider) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionJWTProvider.ProtoReflect.Descriptor instead. func (*IntentionJWTProvider) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{33} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{35} } func (x *IntentionJWTProvider) GetName() string { @@ -3285,7 +3527,7 @@ type IntentionJWTClaimVerification struct { func (x *IntentionJWTClaimVerification) Reset() { *x = IntentionJWTClaimVerification{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[34] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3298,7 +3540,7 @@ func (x *IntentionJWTClaimVerification) String() string { func (*IntentionJWTClaimVerification) ProtoMessage() {} func (x *IntentionJWTClaimVerification) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[34] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3311,7 +3553,7 @@ func (x *IntentionJWTClaimVerification) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionJWTClaimVerification.ProtoReflect.Descriptor instead. func (*IntentionJWTClaimVerification) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{34} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{36} } func (x *IntentionJWTClaimVerification) GetPath() []string { @@ -3362,7 +3604,7 @@ type SourceIntention struct { func (x *SourceIntention) Reset() { *x = SourceIntention{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[35] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3375,7 +3617,7 @@ func (x *SourceIntention) String() string { func (*SourceIntention) ProtoMessage() {} func (x *SourceIntention) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[35] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3388,7 +3630,7 @@ func (x *SourceIntention) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceIntention.ProtoReflect.Descriptor instead. func (*SourceIntention) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{35} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{37} } func (x *SourceIntention) GetName() string { @@ -3501,7 +3743,7 @@ type IntentionPermission struct { func (x *IntentionPermission) Reset() { *x = IntentionPermission{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[36] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3514,7 +3756,7 @@ func (x *IntentionPermission) String() string { func (*IntentionPermission) ProtoMessage() {} func (x *IntentionPermission) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[36] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3527,7 +3769,7 @@ func (x *IntentionPermission) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionPermission.ProtoReflect.Descriptor instead. func (*IntentionPermission) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{36} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{38} } func (x *IntentionPermission) GetAction() IntentionAction { @@ -3571,7 +3813,7 @@ type IntentionHTTPPermission struct { func (x *IntentionHTTPPermission) Reset() { *x = IntentionHTTPPermission{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[37] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3584,7 +3826,7 @@ func (x *IntentionHTTPPermission) String() string { func (*IntentionHTTPPermission) ProtoMessage() {} func (x *IntentionHTTPPermission) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[37] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3597,7 +3839,7 @@ func (x *IntentionHTTPPermission) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionHTTPPermission.ProtoReflect.Descriptor instead. func (*IntentionHTTPPermission) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{37} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{39} } func (x *IntentionHTTPPermission) GetPathExact() string { @@ -3645,19 +3887,21 @@ type IntentionHTTPHeaderPermission struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` - Present bool `protobuf:"varint,2,opt,name=Present,proto3" json:"Present,omitempty"` - Exact string `protobuf:"bytes,3,opt,name=Exact,proto3" json:"Exact,omitempty"` - Prefix string `protobuf:"bytes,4,opt,name=Prefix,proto3" json:"Prefix,omitempty"` - Suffix string `protobuf:"bytes,5,opt,name=Suffix,proto3" json:"Suffix,omitempty"` - Regex string `protobuf:"bytes,6,opt,name=Regex,proto3" json:"Regex,omitempty"` - Invert bool `protobuf:"varint,7,opt,name=Invert,proto3" json:"Invert,omitempty"` + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Present bool `protobuf:"varint,2,opt,name=Present,proto3" json:"Present,omitempty"` + Exact string `protobuf:"bytes,3,opt,name=Exact,proto3" json:"Exact,omitempty"` + Prefix string `protobuf:"bytes,4,opt,name=Prefix,proto3" json:"Prefix,omitempty"` + Suffix string `protobuf:"bytes,5,opt,name=Suffix,proto3" json:"Suffix,omitempty"` + Regex string `protobuf:"bytes,6,opt,name=Regex,proto3" json:"Regex,omitempty"` + Invert bool `protobuf:"varint,7,opt,name=Invert,proto3" json:"Invert,omitempty"` + Contains string `protobuf:"bytes,8,opt,name=Contains,proto3" json:"Contains,omitempty"` + IgnoreCase bool `protobuf:"varint,9,opt,name=IgnoreCase,proto3" json:"IgnoreCase,omitempty"` } func (x *IntentionHTTPHeaderPermission) Reset() { *x = IntentionHTTPHeaderPermission{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[38] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3670,7 +3914,7 @@ func (x *IntentionHTTPHeaderPermission) String() string { func (*IntentionHTTPHeaderPermission) ProtoMessage() {} func (x *IntentionHTTPHeaderPermission) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[38] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3683,7 +3927,7 @@ func (x *IntentionHTTPHeaderPermission) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionHTTPHeaderPermission.ProtoReflect.Descriptor instead. func (*IntentionHTTPHeaderPermission) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{38} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{40} } func (x *IntentionHTTPHeaderPermission) GetName() string { @@ -3735,6 +3979,20 @@ func (x *IntentionHTTPHeaderPermission) GetInvert() bool { return false } +func (x *IntentionHTTPHeaderPermission) GetContains() string { + if x != nil { + return x.Contains + } + return "" +} + +func (x *IntentionHTTPHeaderPermission) GetIgnoreCase() bool { + if x != nil { + return x.IgnoreCase + } + return false +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.ServiceConfigEntry @@ -3774,7 +4032,7 @@ type ServiceDefaults struct { func (x *ServiceDefaults) Reset() { *x = ServiceDefaults{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[39] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3787,7 +4045,7 @@ func (x *ServiceDefaults) String() string { func (*ServiceDefaults) ProtoMessage() {} func (x *ServiceDefaults) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[39] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3800,7 +4058,7 @@ func (x *ServiceDefaults) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceDefaults.ProtoReflect.Descriptor instead. func (*ServiceDefaults) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{39} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{41} } func (x *ServiceDefaults) GetProtocol() string { @@ -3940,7 +4198,7 @@ type TransparentProxyConfig struct { func (x *TransparentProxyConfig) Reset() { *x = TransparentProxyConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[40] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3953,7 +4211,7 @@ func (x *TransparentProxyConfig) String() string { func (*TransparentProxyConfig) ProtoMessage() {} func (x *TransparentProxyConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[40] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3966,7 +4224,7 @@ func (x *TransparentProxyConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use TransparentProxyConfig.ProtoReflect.Descriptor instead. func (*TransparentProxyConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{40} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{42} } func (x *TransparentProxyConfig) GetOutboundListenerPort() int32 { @@ -4000,7 +4258,7 @@ type MeshGatewayConfig struct { func (x *MeshGatewayConfig) Reset() { *x = MeshGatewayConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[41] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4013,7 +4271,7 @@ func (x *MeshGatewayConfig) String() string { func (*MeshGatewayConfig) ProtoMessage() {} func (x *MeshGatewayConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[41] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4026,7 +4284,7 @@ func (x *MeshGatewayConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use MeshGatewayConfig.ProtoReflect.Descriptor instead. func (*MeshGatewayConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{41} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{43} } func (x *MeshGatewayConfig) GetMode() MeshGatewayMode { @@ -4053,7 +4311,7 @@ type ExposeConfig struct { func (x *ExposeConfig) Reset() { *x = ExposeConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[42] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4066,7 +4324,7 @@ func (x *ExposeConfig) String() string { func (*ExposeConfig) ProtoMessage() {} func (x *ExposeConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[42] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4079,7 +4337,7 @@ func (x *ExposeConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use ExposeConfig.ProtoReflect.Descriptor instead. func (*ExposeConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{42} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{44} } func (x *ExposeConfig) GetChecks() bool { @@ -4118,7 +4376,7 @@ type ExposePath struct { func (x *ExposePath) Reset() { *x = ExposePath{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[43] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4131,7 +4389,7 @@ func (x *ExposePath) String() string { func (*ExposePath) ProtoMessage() {} func (x *ExposePath) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[43] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4144,7 +4402,7 @@ func (x *ExposePath) ProtoReflect() protoreflect.Message { // Deprecated: Use ExposePath.ProtoReflect.Descriptor instead. func (*ExposePath) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{43} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{45} } func (x *ExposePath) GetListenerPort() int32 { @@ -4199,7 +4457,7 @@ type UpstreamConfiguration struct { func (x *UpstreamConfiguration) Reset() { *x = UpstreamConfiguration{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[44] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4212,7 +4470,7 @@ func (x *UpstreamConfiguration) String() string { func (*UpstreamConfiguration) ProtoMessage() {} func (x *UpstreamConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[44] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4225,7 +4483,7 @@ func (x *UpstreamConfiguration) ProtoReflect() protoreflect.Message { // Deprecated: Use UpstreamConfiguration.ProtoReflect.Descriptor instead. func (*UpstreamConfiguration) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{44} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{46} } func (x *UpstreamConfiguration) GetOverrides() []*UpstreamConfig { @@ -4270,7 +4528,7 @@ type UpstreamConfig struct { func (x *UpstreamConfig) Reset() { *x = UpstreamConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4283,7 +4541,7 @@ func (x *UpstreamConfig) String() string { func (*UpstreamConfig) ProtoMessage() {} func (x *UpstreamConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4296,7 +4554,7 @@ func (x *UpstreamConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use UpstreamConfig.ProtoReflect.Descriptor instead. func (*UpstreamConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{45} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{47} } func (x *UpstreamConfig) GetName() string { @@ -4397,7 +4655,7 @@ type UpstreamLimits struct { func (x *UpstreamLimits) Reset() { *x = UpstreamLimits{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4410,7 +4668,7 @@ func (x *UpstreamLimits) String() string { func (*UpstreamLimits) ProtoMessage() {} func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4423,7 +4681,7 @@ func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use UpstreamLimits.ProtoReflect.Descriptor instead. func (*UpstreamLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{46} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{48} } func (x *UpstreamLimits) GetMaxConnections() int32 { @@ -4471,7 +4729,7 @@ type PassiveHealthCheck struct { func (x *PassiveHealthCheck) Reset() { *x = PassiveHealthCheck{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4484,7 +4742,7 @@ func (x *PassiveHealthCheck) String() string { func (*PassiveHealthCheck) ProtoMessage() {} func (x *PassiveHealthCheck) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4497,7 +4755,7 @@ func (x *PassiveHealthCheck) ProtoReflect() protoreflect.Message { // Deprecated: Use PassiveHealthCheck.ProtoReflect.Descriptor instead. func (*PassiveHealthCheck) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{47} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{49} } func (x *PassiveHealthCheck) GetInterval() *durationpb.Duration { @@ -4553,7 +4811,7 @@ type DestinationConfig struct { func (x *DestinationConfig) Reset() { *x = DestinationConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4566,7 +4824,7 @@ func (x *DestinationConfig) String() string { func (*DestinationConfig) ProtoMessage() {} func (x *DestinationConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4579,7 +4837,7 @@ func (x *DestinationConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use DestinationConfig.ProtoReflect.Descriptor instead. func (*DestinationConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{48} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{50} } func (x *DestinationConfig) GetAddresses() []string { @@ -4612,7 +4870,7 @@ type RateLimits struct { func (x *RateLimits) Reset() { *x = RateLimits{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4625,7 +4883,7 @@ func (x *RateLimits) String() string { func (*RateLimits) ProtoMessage() {} func (x *RateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4638,7 +4896,7 @@ func (x *RateLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use RateLimits.ProtoReflect.Descriptor instead. func (*RateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{49} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{51} } func (x *RateLimits) GetInstanceLevel() *InstanceLevelRateLimits { @@ -4668,7 +4926,7 @@ type InstanceLevelRateLimits struct { func (x *InstanceLevelRateLimits) Reset() { *x = InstanceLevelRateLimits{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4681,7 +4939,7 @@ func (x *InstanceLevelRateLimits) String() string { func (*InstanceLevelRateLimits) ProtoMessage() {} func (x *InstanceLevelRateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4694,7 +4952,7 @@ func (x *InstanceLevelRateLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceLevelRateLimits.ProtoReflect.Descriptor instead. func (*InstanceLevelRateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{50} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{52} } func (x *InstanceLevelRateLimits) GetRequestsPerSecond() uint32 { @@ -4740,7 +4998,7 @@ type InstanceLevelRouteRateLimits struct { func (x *InstanceLevelRouteRateLimits) Reset() { *x = InstanceLevelRouteRateLimits{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4753,7 +5011,7 @@ func (x *InstanceLevelRouteRateLimits) String() string { func (*InstanceLevelRouteRateLimits) ProtoMessage() {} func (x *InstanceLevelRouteRateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4766,7 +5024,7 @@ func (x *InstanceLevelRouteRateLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceLevelRouteRateLimits.ProtoReflect.Descriptor instead. func (*InstanceLevelRouteRateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{51} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{53} } func (x *InstanceLevelRouteRateLimits) GetPathExact() string { @@ -4824,7 +5082,7 @@ type APIGateway struct { func (x *APIGateway) Reset() { *x = APIGateway{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4837,7 +5095,7 @@ func (x *APIGateway) String() string { func (*APIGateway) ProtoMessage() {} func (x *APIGateway) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4850,7 +5108,7 @@ func (x *APIGateway) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGateway.ProtoReflect.Descriptor instead. func (*APIGateway) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{52} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{54} } func (x *APIGateway) GetMeta() map[string]string { @@ -4897,7 +5155,7 @@ type Status struct { func (x *Status) Reset() { *x = Status{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4910,7 +5168,7 @@ func (x *Status) String() string { func (*Status) ProtoMessage() {} func (x *Status) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4923,7 +5181,7 @@ func (x *Status) ProtoReflect() protoreflect.Message { // Deprecated: Use Status.ProtoReflect.Descriptor instead. func (*Status) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{53} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{55} } func (x *Status) GetConditions() []*Condition { @@ -4955,7 +5213,7 @@ type Condition struct { func (x *Condition) Reset() { *x = Condition{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4968,7 +5226,7 @@ func (x *Condition) String() string { func (*Condition) ProtoMessage() {} func (x *Condition) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4981,7 +5239,7 @@ func (x *Condition) ProtoReflect() protoreflect.Message { // Deprecated: Use Condition.ProtoReflect.Descriptor instead. func (*Condition) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{54} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{56} } func (x *Condition) GetType() string { @@ -5050,7 +5308,7 @@ type APIGatewayListener struct { func (x *APIGatewayListener) Reset() { *x = APIGatewayListener{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5063,7 +5321,7 @@ func (x *APIGatewayListener) String() string { func (*APIGatewayListener) ProtoMessage() {} func (x *APIGatewayListener) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5076,7 +5334,7 @@ func (x *APIGatewayListener) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayListener.ProtoReflect.Descriptor instead. func (*APIGatewayListener) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{55} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{57} } func (x *APIGatewayListener) GetName() string { @@ -5150,7 +5408,7 @@ type APIGatewayTLSConfiguration struct { func (x *APIGatewayTLSConfiguration) Reset() { *x = APIGatewayTLSConfiguration{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5163,7 +5421,7 @@ func (x *APIGatewayTLSConfiguration) String() string { func (*APIGatewayTLSConfiguration) ProtoMessage() {} func (x *APIGatewayTLSConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5176,7 +5434,7 @@ func (x *APIGatewayTLSConfiguration) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayTLSConfiguration.ProtoReflect.Descriptor instead. func (*APIGatewayTLSConfiguration) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{56} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{58} } func (x *APIGatewayTLSConfiguration) GetCertificates() []*ResourceReference { @@ -5224,7 +5482,7 @@ type APIGatewayPolicy struct { func (x *APIGatewayPolicy) Reset() { *x = APIGatewayPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5237,7 +5495,7 @@ func (x *APIGatewayPolicy) String() string { func (*APIGatewayPolicy) ProtoMessage() {} func (x *APIGatewayPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5250,7 +5508,7 @@ func (x *APIGatewayPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayPolicy.ProtoReflect.Descriptor instead. func (*APIGatewayPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{57} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{59} } func (x *APIGatewayPolicy) GetJWT() *APIGatewayJWTRequirement { @@ -5271,7 +5529,7 @@ type APIGatewayJWTRequirement struct { func (x *APIGatewayJWTRequirement) Reset() { *x = APIGatewayJWTRequirement{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5284,7 +5542,7 @@ func (x *APIGatewayJWTRequirement) String() string { func (*APIGatewayJWTRequirement) ProtoMessage() {} func (x *APIGatewayJWTRequirement) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5297,7 +5555,7 @@ func (x *APIGatewayJWTRequirement) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayJWTRequirement.ProtoReflect.Descriptor instead. func (*APIGatewayJWTRequirement) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{58} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{60} } func (x *APIGatewayJWTRequirement) GetProviders() []*APIGatewayJWTProvider { @@ -5319,7 +5577,7 @@ type APIGatewayJWTProvider struct { func (x *APIGatewayJWTProvider) Reset() { *x = APIGatewayJWTProvider{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5332,7 +5590,7 @@ func (x *APIGatewayJWTProvider) String() string { func (*APIGatewayJWTProvider) ProtoMessage() {} func (x *APIGatewayJWTProvider) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5345,7 +5603,7 @@ func (x *APIGatewayJWTProvider) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayJWTProvider.ProtoReflect.Descriptor instead. func (*APIGatewayJWTProvider) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{59} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{61} } func (x *APIGatewayJWTProvider) GetName() string { @@ -5374,7 +5632,7 @@ type APIGatewayJWTClaimVerification struct { func (x *APIGatewayJWTClaimVerification) Reset() { *x = APIGatewayJWTClaimVerification{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5387,7 +5645,7 @@ func (x *APIGatewayJWTClaimVerification) String() string { func (*APIGatewayJWTClaimVerification) ProtoMessage() {} func (x *APIGatewayJWTClaimVerification) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5400,7 +5658,7 @@ func (x *APIGatewayJWTClaimVerification) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayJWTClaimVerification.ProtoReflect.Descriptor instead. func (*APIGatewayJWTClaimVerification) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{60} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{62} } func (x *APIGatewayJWTClaimVerification) GetPath() []string { @@ -5437,7 +5695,7 @@ type ResourceReference struct { func (x *ResourceReference) Reset() { *x = ResourceReference{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5450,7 +5708,7 @@ func (x *ResourceReference) String() string { func (*ResourceReference) ProtoMessage() {} func (x *ResourceReference) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5463,7 +5721,7 @@ func (x *ResourceReference) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceReference.ProtoReflect.Descriptor instead. func (*ResourceReference) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{61} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{63} } func (x *ResourceReference) GetKind() string { @@ -5515,7 +5773,7 @@ type BoundAPIGateway struct { func (x *BoundAPIGateway) Reset() { *x = BoundAPIGateway{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5528,7 +5786,7 @@ func (x *BoundAPIGateway) String() string { func (*BoundAPIGateway) ProtoMessage() {} func (x *BoundAPIGateway) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5541,7 +5799,7 @@ func (x *BoundAPIGateway) ProtoReflect() protoreflect.Message { // Deprecated: Use BoundAPIGateway.ProtoReflect.Descriptor instead. func (*BoundAPIGateway) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{62} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{64} } func (x *BoundAPIGateway) GetMeta() map[string]string { @@ -5583,7 +5841,7 @@ type ListOfResourceReference struct { func (x *ListOfResourceReference) Reset() { *x = ListOfResourceReference{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5596,7 +5854,7 @@ func (x *ListOfResourceReference) String() string { func (*ListOfResourceReference) ProtoMessage() {} func (x *ListOfResourceReference) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5609,7 +5867,7 @@ func (x *ListOfResourceReference) ProtoReflect() protoreflect.Message { // Deprecated: Use ListOfResourceReference.ProtoReflect.Descriptor instead. func (*ListOfResourceReference) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{63} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{65} } func (x *ListOfResourceReference) GetRef() []*ResourceReference { @@ -5637,7 +5895,7 @@ type BoundAPIGatewayListener struct { func (x *BoundAPIGatewayListener) Reset() { *x = BoundAPIGatewayListener{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5650,7 +5908,7 @@ func (x *BoundAPIGatewayListener) String() string { func (*BoundAPIGatewayListener) ProtoMessage() {} func (x *BoundAPIGatewayListener) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5663,7 +5921,7 @@ func (x *BoundAPIGatewayListener) ProtoReflect() protoreflect.Message { // Deprecated: Use BoundAPIGatewayListener.ProtoReflect.Descriptor instead. func (*BoundAPIGatewayListener) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{64} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{66} } func (x *BoundAPIGatewayListener) GetName() string { @@ -5707,7 +5965,7 @@ type FileSystemCertificate struct { func (x *FileSystemCertificate) Reset() { *x = FileSystemCertificate{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5720,7 +5978,7 @@ func (x *FileSystemCertificate) String() string { func (*FileSystemCertificate) ProtoMessage() {} func (x *FileSystemCertificate) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5733,7 +5991,7 @@ func (x *FileSystemCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use FileSystemCertificate.ProtoReflect.Descriptor instead. func (*FileSystemCertificate) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{65} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{67} } func (x *FileSystemCertificate) GetMeta() map[string]string { @@ -5784,7 +6042,7 @@ type InlineCertificate struct { func (x *InlineCertificate) Reset() { *x = InlineCertificate{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5797,7 +6055,7 @@ func (x *InlineCertificate) String() string { func (*InlineCertificate) ProtoMessage() {} func (x *InlineCertificate) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5810,7 +6068,7 @@ func (x *InlineCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use InlineCertificate.ProtoReflect.Descriptor instead. func (*InlineCertificate) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{66} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{68} } func (x *InlineCertificate) GetMeta() map[string]string { @@ -5863,7 +6121,7 @@ type HTTPRoute struct { func (x *HTTPRoute) Reset() { *x = HTTPRoute{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5876,7 +6134,7 @@ func (x *HTTPRoute) String() string { func (*HTTPRoute) ProtoMessage() {} func (x *HTTPRoute) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5889,7 +6147,7 @@ func (x *HTTPRoute) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPRoute.ProtoReflect.Descriptor instead. func (*HTTPRoute) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{67} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{69} } func (x *HTTPRoute) GetMeta() map[string]string { @@ -5953,7 +6211,7 @@ type HTTPRouteRule struct { func (x *HTTPRouteRule) Reset() { *x = HTTPRouteRule{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5966,7 +6224,7 @@ func (x *HTTPRouteRule) String() string { func (*HTTPRouteRule) ProtoMessage() {} func (x *HTTPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5979,7 +6237,7 @@ func (x *HTTPRouteRule) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPRouteRule.ProtoReflect.Descriptor instead. func (*HTTPRouteRule) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{68} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{70} } func (x *HTTPRouteRule) GetFilters() *HTTPFilters { @@ -6030,7 +6288,7 @@ type HTTPMatch struct { func (x *HTTPMatch) Reset() { *x = HTTPMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6043,7 +6301,7 @@ func (x *HTTPMatch) String() string { func (*HTTPMatch) ProtoMessage() {} func (x *HTTPMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6056,7 +6314,7 @@ func (x *HTTPMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPMatch.ProtoReflect.Descriptor instead. func (*HTTPMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{69} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{71} } func (x *HTTPMatch) GetHeaders() []*HTTPHeaderMatch { @@ -6106,7 +6364,7 @@ type HTTPHeaderMatch struct { func (x *HTTPHeaderMatch) Reset() { *x = HTTPHeaderMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6119,7 +6377,7 @@ func (x *HTTPHeaderMatch) String() string { func (*HTTPHeaderMatch) ProtoMessage() {} func (x *HTTPHeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6132,7 +6390,7 @@ func (x *HTTPHeaderMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPHeaderMatch.ProtoReflect.Descriptor instead. func (*HTTPHeaderMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{70} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{72} } func (x *HTTPHeaderMatch) GetMatch() HTTPHeaderMatchType { @@ -6174,7 +6432,7 @@ type HTTPPathMatch struct { func (x *HTTPPathMatch) Reset() { *x = HTTPPathMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6187,7 +6445,7 @@ func (x *HTTPPathMatch) String() string { func (*HTTPPathMatch) ProtoMessage() {} func (x *HTTPPathMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6200,7 +6458,7 @@ func (x *HTTPPathMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPPathMatch.ProtoReflect.Descriptor instead. func (*HTTPPathMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{71} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{73} } func (x *HTTPPathMatch) GetMatch() HTTPPathMatchType { @@ -6236,7 +6494,7 @@ type HTTPQueryMatch struct { func (x *HTTPQueryMatch) Reset() { *x = HTTPQueryMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6249,7 +6507,7 @@ func (x *HTTPQueryMatch) String() string { func (*HTTPQueryMatch) ProtoMessage() {} func (x *HTTPQueryMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6262,7 +6520,7 @@ func (x *HTTPQueryMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPQueryMatch.ProtoReflect.Descriptor instead. func (*HTTPQueryMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{72} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{74} } func (x *HTTPQueryMatch) GetMatch() HTTPQueryMatchType { @@ -6307,7 +6565,7 @@ type HTTPFilters struct { func (x *HTTPFilters) Reset() { *x = HTTPFilters{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6320,7 +6578,7 @@ func (x *HTTPFilters) String() string { func (*HTTPFilters) ProtoMessage() {} func (x *HTTPFilters) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6333,7 +6591,7 @@ func (x *HTTPFilters) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPFilters.ProtoReflect.Descriptor instead. func (*HTTPFilters) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{73} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{75} } func (x *HTTPFilters) GetHeaders() []*HTTPHeaderFilter { @@ -6387,7 +6645,7 @@ type HTTPResponseFilters struct { func (x *HTTPResponseFilters) Reset() { *x = HTTPResponseFilters{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6400,7 +6658,7 @@ func (x *HTTPResponseFilters) String() string { func (*HTTPResponseFilters) ProtoMessage() {} func (x *HTTPResponseFilters) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6413,7 +6671,7 @@ func (x *HTTPResponseFilters) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPResponseFilters.ProtoReflect.Descriptor instead. func (*HTTPResponseFilters) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{74} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{76} } func (x *HTTPResponseFilters) GetHeaders() []*HTTPHeaderFilter { @@ -6439,7 +6697,7 @@ type URLRewrite struct { func (x *URLRewrite) Reset() { *x = URLRewrite{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6452,7 +6710,7 @@ func (x *URLRewrite) String() string { func (*URLRewrite) ProtoMessage() {} func (x *URLRewrite) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6465,7 +6723,7 @@ func (x *URLRewrite) ProtoReflect() protoreflect.Message { // Deprecated: Use URLRewrite.ProtoReflect.Descriptor instead. func (*URLRewrite) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{75} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{77} } func (x *URLRewrite) GetPath() string { @@ -6494,7 +6752,7 @@ type RetryFilter struct { func (x *RetryFilter) Reset() { *x = RetryFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6507,7 +6765,7 @@ func (x *RetryFilter) String() string { func (*RetryFilter) ProtoMessage() {} func (x *RetryFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6520,7 +6778,7 @@ func (x *RetryFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryFilter.ProtoReflect.Descriptor instead. func (*RetryFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{76} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{78} } func (x *RetryFilter) GetNumRetries() uint32 { @@ -6570,7 +6828,7 @@ type TimeoutFilter struct { func (x *TimeoutFilter) Reset() { *x = TimeoutFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6583,7 +6841,7 @@ func (x *TimeoutFilter) String() string { func (*TimeoutFilter) ProtoMessage() {} func (x *TimeoutFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6596,7 +6854,7 @@ func (x *TimeoutFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use TimeoutFilter.ProtoReflect.Descriptor instead. func (*TimeoutFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{77} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{79} } func (x *TimeoutFilter) GetRequestTimeout() *durationpb.Duration { @@ -6624,7 +6882,7 @@ type JWTFilter struct { func (x *JWTFilter) Reset() { *x = JWTFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6637,7 +6895,7 @@ func (x *JWTFilter) String() string { func (*JWTFilter) ProtoMessage() {} func (x *JWTFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6650,7 +6908,7 @@ func (x *JWTFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTFilter.ProtoReflect.Descriptor instead. func (*JWTFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{78} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{80} } func (x *JWTFilter) GetProviders() []*APIGatewayJWTProvider { @@ -6678,7 +6936,7 @@ type HTTPHeaderFilter struct { func (x *HTTPHeaderFilter) Reset() { *x = HTTPHeaderFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6691,7 +6949,7 @@ func (x *HTTPHeaderFilter) String() string { func (*HTTPHeaderFilter) ProtoMessage() {} func (x *HTTPHeaderFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6704,7 +6962,7 @@ func (x *HTTPHeaderFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPHeaderFilter.ProtoReflect.Descriptor instead. func (*HTTPHeaderFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{79} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{81} } func (x *HTTPHeaderFilter) GetAdd() map[string]string { @@ -6750,7 +7008,7 @@ type HTTPService struct { func (x *HTTPService) Reset() { *x = HTTPService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6763,7 +7021,7 @@ func (x *HTTPService) String() string { func (*HTTPService) ProtoMessage() {} func (x *HTTPService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6776,7 +7034,7 @@ func (x *HTTPService) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPService.ProtoReflect.Descriptor instead. func (*HTTPService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{80} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{82} } func (x *HTTPService) GetName() string { @@ -6835,7 +7093,7 @@ type TCPRoute struct { func (x *TCPRoute) Reset() { *x = TCPRoute{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6848,7 +7106,7 @@ func (x *TCPRoute) String() string { func (*TCPRoute) ProtoMessage() {} func (x *TCPRoute) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6861,7 +7119,7 @@ func (x *TCPRoute) ProtoReflect() protoreflect.Message { // Deprecated: Use TCPRoute.ProtoReflect.Descriptor instead. func (*TCPRoute) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{81} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{83} } func (x *TCPRoute) GetMeta() map[string]string { @@ -6917,7 +7175,7 @@ type TCPService struct { func (x *TCPService) Reset() { *x = TCPService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6930,7 +7188,7 @@ func (x *TCPService) String() string { func (*TCPService) ProtoMessage() {} func (x *TCPService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6943,7 +7201,7 @@ func (x *TCPService) ProtoReflect() protoreflect.Message { // Deprecated: Use TCPService.ProtoReflect.Descriptor instead. func (*TCPService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{82} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{84} } func (x *TCPService) GetName() string { @@ -6984,7 +7242,7 @@ type SamenessGroup struct { func (x *SamenessGroup) Reset() { *x = SamenessGroup{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6997,7 +7255,7 @@ func (x *SamenessGroup) String() string { func (*SamenessGroup) ProtoMessage() {} func (x *SamenessGroup) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7010,7 +7268,7 @@ func (x *SamenessGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use SamenessGroup.ProtoReflect.Descriptor instead. func (*SamenessGroup) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{83} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{85} } func (x *SamenessGroup) GetName() string { @@ -7079,7 +7337,7 @@ type SamenessGroupMember struct { func (x *SamenessGroupMember) Reset() { *x = SamenessGroupMember{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7092,7 +7350,7 @@ func (x *SamenessGroupMember) String() string { func (*SamenessGroupMember) ProtoMessage() {} func (x *SamenessGroupMember) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7105,7 +7363,7 @@ func (x *SamenessGroupMember) ProtoReflect() protoreflect.Message { // Deprecated: Use SamenessGroupMember.ProtoReflect.Descriptor instead. func (*SamenessGroupMember) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{84} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{86} } func (x *SamenessGroupMember) GetPartition() string { @@ -7148,7 +7406,7 @@ type JWTProvider struct { func (x *JWTProvider) Reset() { *x = JWTProvider{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7161,7 +7419,7 @@ func (x *JWTProvider) String() string { func (*JWTProvider) ProtoMessage() {} func (x *JWTProvider) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7174,7 +7432,7 @@ func (x *JWTProvider) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTProvider.ProtoReflect.Descriptor instead. func (*JWTProvider) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{85} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{87} } func (x *JWTProvider) GetJSONWebKeySet() *JSONWebKeySet { @@ -7257,7 +7515,7 @@ type JSONWebKeySet struct { func (x *JSONWebKeySet) Reset() { *x = JSONWebKeySet{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7270,7 +7528,7 @@ func (x *JSONWebKeySet) String() string { func (*JSONWebKeySet) ProtoMessage() {} func (x *JSONWebKeySet) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7283,7 +7541,7 @@ func (x *JSONWebKeySet) ProtoReflect() protoreflect.Message { // Deprecated: Use JSONWebKeySet.ProtoReflect.Descriptor instead. func (*JSONWebKeySet) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{86} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{88} } func (x *JSONWebKeySet) GetLocal() *LocalJWKS { @@ -7317,7 +7575,7 @@ type LocalJWKS struct { func (x *LocalJWKS) Reset() { *x = LocalJWKS{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7330,7 +7588,7 @@ func (x *LocalJWKS) String() string { func (*LocalJWKS) ProtoMessage() {} func (x *LocalJWKS) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7343,7 +7601,7 @@ func (x *LocalJWKS) ProtoReflect() protoreflect.Message { // Deprecated: Use LocalJWKS.ProtoReflect.Descriptor instead. func (*LocalJWKS) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{87} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{89} } func (x *LocalJWKS) GetJWKS() string { @@ -7383,7 +7641,7 @@ type RemoteJWKS struct { func (x *RemoteJWKS) Reset() { *x = RemoteJWKS{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7396,7 +7654,7 @@ func (x *RemoteJWKS) String() string { func (*RemoteJWKS) ProtoMessage() {} func (x *RemoteJWKS) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7409,7 +7667,7 @@ func (x *RemoteJWKS) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoteJWKS.ProtoReflect.Descriptor instead. func (*RemoteJWKS) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{88} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{90} } func (x *RemoteJWKS) GetURI() string { @@ -7473,7 +7731,7 @@ type JWKSCluster struct { func (x *JWKSCluster) Reset() { *x = JWKSCluster{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7486,7 +7744,7 @@ func (x *JWKSCluster) String() string { func (*JWKSCluster) ProtoMessage() {} func (x *JWKSCluster) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7499,7 +7757,7 @@ func (x *JWKSCluster) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSCluster.ProtoReflect.Descriptor instead. func (*JWKSCluster) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{89} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{91} } func (x *JWKSCluster) GetDiscoveryType() string { @@ -7540,7 +7798,7 @@ type JWKSTLSCertificate struct { func (x *JWKSTLSCertificate) Reset() { *x = JWKSTLSCertificate{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7553,7 +7811,7 @@ func (x *JWKSTLSCertificate) String() string { func (*JWKSTLSCertificate) ProtoMessage() {} func (x *JWKSTLSCertificate) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7566,7 +7824,7 @@ func (x *JWKSTLSCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertificate.ProtoReflect.Descriptor instead. func (*JWKSTLSCertificate) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{90} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{92} } func (x *JWKSTLSCertificate) GetCaCertificateProviderInstance() *JWKSTLSCertProviderInstance { @@ -7600,7 +7858,7 @@ type JWKSTLSCertProviderInstance struct { func (x *JWKSTLSCertProviderInstance) Reset() { *x = JWKSTLSCertProviderInstance{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7613,7 +7871,7 @@ func (x *JWKSTLSCertProviderInstance) String() string { func (*JWKSTLSCertProviderInstance) ProtoMessage() {} func (x *JWKSTLSCertProviderInstance) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7626,7 +7884,7 @@ func (x *JWKSTLSCertProviderInstance) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertProviderInstance.ProtoReflect.Descriptor instead. func (*JWKSTLSCertProviderInstance) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{91} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{93} } func (x *JWKSTLSCertProviderInstance) GetInstanceName() string { @@ -7662,7 +7920,7 @@ type JWKSTLSCertTrustedCA struct { func (x *JWKSTLSCertTrustedCA) Reset() { *x = JWKSTLSCertTrustedCA{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7675,7 +7933,7 @@ func (x *JWKSTLSCertTrustedCA) String() string { func (*JWKSTLSCertTrustedCA) ProtoMessage() {} func (x *JWKSTLSCertTrustedCA) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[94] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7688,7 +7946,7 @@ func (x *JWKSTLSCertTrustedCA) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertTrustedCA.ProtoReflect.Descriptor instead. func (*JWKSTLSCertTrustedCA) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{92} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{94} } func (x *JWKSTLSCertTrustedCA) GetFilename() string { @@ -7737,7 +7995,7 @@ type JWKSRetryPolicy struct { func (x *JWKSRetryPolicy) Reset() { *x = JWKSRetryPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7750,7 +8008,7 @@ func (x *JWKSRetryPolicy) String() string { func (*JWKSRetryPolicy) ProtoMessage() {} func (x *JWKSRetryPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[95] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7763,7 +8021,7 @@ func (x *JWKSRetryPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSRetryPolicy.ProtoReflect.Descriptor instead. func (*JWKSRetryPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{93} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{95} } func (x *JWKSRetryPolicy) GetNumRetries() int32 { @@ -7799,7 +8057,7 @@ type RetryPolicyBackOff struct { func (x *RetryPolicyBackOff) Reset() { *x = RetryPolicyBackOff{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[94] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7812,7 +8070,7 @@ func (x *RetryPolicyBackOff) String() string { func (*RetryPolicyBackOff) ProtoMessage() {} func (x *RetryPolicyBackOff) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[94] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[96] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7825,7 +8083,7 @@ func (x *RetryPolicyBackOff) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryPolicyBackOff.ProtoReflect.Descriptor instead. func (*RetryPolicyBackOff) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{94} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{96} } func (x *RetryPolicyBackOff) GetBaseInterval() *durationpb.Duration { @@ -7860,7 +8118,7 @@ type JWTLocation struct { func (x *JWTLocation) Reset() { *x = JWTLocation{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[95] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7873,7 +8131,7 @@ func (x *JWTLocation) String() string { func (*JWTLocation) ProtoMessage() {} func (x *JWTLocation) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[95] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[97] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7886,7 +8144,7 @@ func (x *JWTLocation) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocation.ProtoReflect.Descriptor instead. func (*JWTLocation) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{95} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{97} } func (x *JWTLocation) GetHeader() *JWTLocationHeader { @@ -7928,7 +8186,7 @@ type JWTLocationHeader struct { func (x *JWTLocationHeader) Reset() { *x = JWTLocationHeader{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[96] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7941,7 +8199,7 @@ func (x *JWTLocationHeader) String() string { func (*JWTLocationHeader) ProtoMessage() {} func (x *JWTLocationHeader) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[96] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[98] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7954,7 +8212,7 @@ func (x *JWTLocationHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationHeader.ProtoReflect.Descriptor instead. func (*JWTLocationHeader) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{96} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{98} } func (x *JWTLocationHeader) GetName() string { @@ -7994,7 +8252,7 @@ type JWTLocationQueryParam struct { func (x *JWTLocationQueryParam) Reset() { *x = JWTLocationQueryParam{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[97] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8007,7 +8265,7 @@ func (x *JWTLocationQueryParam) String() string { func (*JWTLocationQueryParam) ProtoMessage() {} func (x *JWTLocationQueryParam) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[97] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[99] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8020,7 +8278,7 @@ func (x *JWTLocationQueryParam) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationQueryParam.ProtoReflect.Descriptor instead. func (*JWTLocationQueryParam) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{97} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{99} } func (x *JWTLocationQueryParam) GetName() string { @@ -8046,7 +8304,7 @@ type JWTLocationCookie struct { func (x *JWTLocationCookie) Reset() { *x = JWTLocationCookie{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[98] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8059,7 +8317,7 @@ func (x *JWTLocationCookie) String() string { func (*JWTLocationCookie) ProtoMessage() {} func (x *JWTLocationCookie) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[98] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[100] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8072,7 +8330,7 @@ func (x *JWTLocationCookie) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationCookie.ProtoReflect.Descriptor instead. func (*JWTLocationCookie) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{98} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{100} } func (x *JWTLocationCookie) GetName() string { @@ -8099,7 +8357,7 @@ type JWTForwardingConfig struct { func (x *JWTForwardingConfig) Reset() { *x = JWTForwardingConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[99] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8112,7 +8370,7 @@ func (x *JWTForwardingConfig) String() string { func (*JWTForwardingConfig) ProtoMessage() {} func (x *JWTForwardingConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[99] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[101] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8125,7 +8383,7 @@ func (x *JWTForwardingConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTForwardingConfig.ProtoReflect.Descriptor instead. func (*JWTForwardingConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{99} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{101} } func (x *JWTForwardingConfig) GetHeaderName() string { @@ -8159,7 +8417,7 @@ type JWTCacheConfig struct { func (x *JWTCacheConfig) Reset() { *x = JWTCacheConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[100] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8172,7 +8430,7 @@ func (x *JWTCacheConfig) String() string { func (*JWTCacheConfig) ProtoMessage() {} func (x *JWTCacheConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[100] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[102] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8185,7 +8443,7 @@ func (x *JWTCacheConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTCacheConfig.ProtoReflect.Descriptor instead. func (*JWTCacheConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{100} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{102} } func (x *JWTCacheConfig) GetSize() int32 { @@ -8217,7 +8475,7 @@ type ExportedServices struct { func (x *ExportedServices) Reset() { *x = ExportedServices{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[101] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8230,7 +8488,7 @@ func (x *ExportedServices) String() string { func (*ExportedServices) ProtoMessage() {} func (x *ExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[101] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[103] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8243,7 +8501,7 @@ func (x *ExportedServices) ProtoReflect() protoreflect.Message { // Deprecated: Use ExportedServices.ProtoReflect.Descriptor instead. func (*ExportedServices) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{101} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{103} } func (x *ExportedServices) GetName() string { @@ -8299,7 +8557,7 @@ type ExportedServicesService struct { func (x *ExportedServicesService) Reset() { *x = ExportedServicesService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[102] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8312,7 +8570,7 @@ func (x *ExportedServicesService) String() string { func (*ExportedServicesService) ProtoMessage() {} func (x *ExportedServicesService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[102] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[104] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8325,7 +8583,7 @@ func (x *ExportedServicesService) ProtoReflect() protoreflect.Message { // Deprecated: Use ExportedServicesService.ProtoReflect.Descriptor instead. func (*ExportedServicesService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{102} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{104} } func (x *ExportedServicesService) GetName() string { @@ -8367,7 +8625,7 @@ type ExportedServicesConsumer struct { func (x *ExportedServicesConsumer) Reset() { *x = ExportedServicesConsumer{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[103] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8380,7 +8638,7 @@ func (x *ExportedServicesConsumer) String() string { func (*ExportedServicesConsumer) ProtoMessage() {} func (x *ExportedServicesConsumer) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[103] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[105] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8393,7 +8651,7 @@ func (x *ExportedServicesConsumer) ProtoReflect() protoreflect.Message { // Deprecated: Use ExportedServicesConsumer.ProtoReflect.Descriptor instead. func (*ExportedServicesConsumer) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{103} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{105} } func (x *ExportedServicesConsumer) GetPartition() string { @@ -8631,1554 +8889,1626 @@ var file_private_pbconfigentry_config_entry_proto_rawDesc = []byte{ 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, - 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x0e, 0x4d, - 0x65, 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, - 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, - 0x64, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, 0x6f, - 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, - 0x74, 0x22, 0x4d, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x68, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x17, 0x50, 0x65, 0x65, 0x72, 0x54, 0x68, - 0x72, 0x6f, 0x75, 0x67, 0x68, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x50, 0x65, 0x65, 0x72, 0x54, 0x68, 0x72, - 0x6f, 0x75, 0x67, 0x68, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, - 0x22, 0xcd, 0x08, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, - 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x5d, 0x0a, 0x07, 0x53, 0x75, - 0x62, 0x73, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x72, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x07, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x12, 0x5a, 0x0a, 0x08, 0x52, 0x65, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x08, 0x52, 0x65, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x60, 0x0a, 0x08, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, - 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x46, - 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x57, 0x0a, 0x0c, 0x4c, 0x6f, - 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x72, 0x52, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x0e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x7e, 0x0a, 0x14, - 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4a, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x14, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, - 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, - 0x48, 0x61, 0x73, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, - 0x1a, 0x78, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 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, 0x52, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x7b, 0x0a, 0x0d, 0x46, 0x61, - 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x54, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, + 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0xb2, 0x01, 0x0a, 0x0e, + 0x4d, 0x65, 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, + 0x0a, 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, + 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, + 0x72, 0x74, 0x12, 0x5c, 0x0a, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, + 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x48, 0x54, 0x54, 0x50, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, + 0x22, 0x96, 0x01, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x79, + 0x0a, 0x14, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x51, 0x0a, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, - 0x69, 0x6e, 0x67, 0x22, 0xef, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, - 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, - 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, - 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, - 0x65, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, - 0x24, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xfd, 0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, - 0x72, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, - 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x73, 0x12, 0x5e, 0x0a, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x14, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x11, 0x50, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, + 0x0a, 0x17, 0x50, 0x65, 0x65, 0x72, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x4d, 0x65, 0x73, + 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x17, 0x50, 0x65, 0x65, 0x72, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x4d, 0x65, 0x73, 0x68, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x22, 0xa4, 0x03, 0x0a, 0x1e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4a, 0x0a, 0x20, 0x49, + 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, + 0x74, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x20, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x44, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x4d, 0x65, 0x72, 0x67, 0x65, + 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x4d, + 0x65, 0x72, 0x67, 0x65, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x1c, + 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, - 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x73, 0x12, 0x5c, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x57, + 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1c, 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, + 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x87, 0x01, 0x0a, 0x1c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x73, 0x57, 0x69, 0x74, 0x68, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x43, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, + 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x1c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, 0x55, 0x6e, + 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0xcd, 0x08, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, + 0x62, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x5d, 0x0a, 0x07, 0x53, 0x75, 0x62, + 0x73, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x07, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x12, 0x5a, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x08, 0x52, 0x65, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x12, 0x60, 0x0a, 0x08, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x46, + 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x46, 0x61, + 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x57, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, + 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x72, 0x52, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x72, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x7e, 0x0a, 0x14, 0x50, + 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4a, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x14, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, + 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x48, + 0x61, 0x73, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, + 0x78, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 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, 0x52, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x7b, 0x0a, 0x0d, 0x46, 0x61, 0x69, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x54, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, + 0x51, 0x0a, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, + 0x6e, 0x67, 0x22, 0xef, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x18, + 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x1c, + 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, + 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, + 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, + 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x22, 0xfd, 0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, + 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, + 0x12, 0x5e, 0x0a, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, - 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x24, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x4d, 0x0a, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, + 0x12, 0x5c, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x65, - 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x52, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x39, 0x0a, 0x23, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, - 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x4d, - 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x22, - 0xcf, 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, - 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x0a, - 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, - 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, - 0x72, 0x22, 0xc7, 0x02, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5d, 0x0a, 0x0e, 0x52, 0x69, - 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x48, - 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, - 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x69, 0x0a, 0x12, 0x4c, 0x65, 0x61, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x65, - 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x55, 0x0a, 0x0c, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x48, - 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0e, 0x52, - 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, - 0x0f, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, - 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x4d, 0x61, 0x78, 0x69, 0x6d, - 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0f, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, - 0x65, 0x22, 0x36, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x68, 0x6f, 0x69, 0x63, - 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x43, 0x68, - 0x6f, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x0a, 0x48, 0x61, - 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1e, - 0x0a, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x57, - 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x24, + 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x22, 0x4d, 0x0a, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x52, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x73, 0x22, 0x39, 0x0a, 0x23, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, + 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, + 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xcf, + 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, + 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x50, 0x65, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, + 0x22, 0xc7, 0x02, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x72, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5d, 0x0a, 0x0e, 0x52, 0x69, 0x6e, + 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, + 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, + 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x69, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6f, - 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x49, 0x50, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x49, 0x50, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, - 0x69, 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x18, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0xac, 0x03, 0x0a, 0x0e, 0x49, - 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x49, 0x0a, - 0x03, 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x65, 0x61, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x55, 0x0a, 0x0c, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x48, 0x61, + 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0e, 0x52, 0x69, + 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x0f, + 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, + 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, + 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0f, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, + 0x22, 0x36, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x43, 0x68, 0x6f, + 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x0a, 0x48, 0x61, 0x73, + 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1e, 0x0a, + 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x57, 0x0a, + 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, + 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x50, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x50, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x69, + 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, + 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0xac, 0x03, 0x0a, 0x0e, 0x49, 0x6e, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x49, 0x0a, 0x03, + 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x54, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x54, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, + 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x53, 0x0a, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x53, - 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x12, 0x57, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, - 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x48, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, - 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x8f, 0x02, 0x0a, 0x14, 0x49, 0x6e, - 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, - 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, - 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, - 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, - 0x12, 0x69, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xea, 0x01, 0x0a, 0x10, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x4c, 0x0a, 0x03, 0x53, 0x44, - 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, - 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, - 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, - 0x69, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x20, 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xdf, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, + 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x12, 0x57, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, + 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, + 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x8f, 0x02, 0x0a, 0x14, 0x49, 0x6e, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, + 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, + 0x69, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x03, - 0x54, 0x4c, 0x53, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x22, 0xb7, 0x06, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x48, - 0x6f, 0x73, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x62, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, - 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x12, 0x53, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, - 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, - 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, - 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x69, 0x0a, - 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, - 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, 0x67, 0x0a, 0x17, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x03, - 0x53, 0x44, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x22, 0xcb, 0x02, 0x0a, 0x13, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x73, 0x12, 0x55, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, 0x12, 0x55, 0x0a, 0x03, 0x53, 0x65, 0x74, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xea, 0x01, 0x0a, 0x10, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x4c, 0x0a, 0x03, 0x53, 0x44, 0x53, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, + 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, + 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, + 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, + 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, + 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x22, 0xdf, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x03, 0x54, + 0x4c, 0x53, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x22, 0xb7, 0x06, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x48, 0x6f, + 0x73, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x62, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x0f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, + 0x53, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x26, + 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, + 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, - 0x1a, 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, 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, 0xdc, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x50, - 0x0a, 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x12, 0x56, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, + 0x22, 0x67, 0x0a, 0x17, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x03, 0x53, + 0x44, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x22, 0xcb, 0x02, 0x0a, 0x13, 0x48, 0x54, + 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x73, 0x12, 0x55, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, 0x12, 0x55, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, - 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, - 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x73, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 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, 0x1a, + 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, 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, 0x74, 0x0a, 0x17, 0x49, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x12, 0x59, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x94, 0x01, - 0x0a, 0x14, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x68, 0x0a, 0x0c, 0x56, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, - 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, - 0x61, 0x69, 0x6d, 0x73, 0x22, 0x49, 0x0a, 0x1d, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, - 0x6e, 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0xcc, 0x06, 0x0a, 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, - 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, - 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, - 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, - 0x44, 0x12, 0x4e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x0a, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, - 0x61, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x0a, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x10, 0x4c, - 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, - 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, - 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x61, 0x6d, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x1a, - 0x3d, 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 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, 0x8b, - 0x02, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x02, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdc, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x50, 0x0a, + 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, + 0x56, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x50, 0x0a, 0x03, 0x4a, 0x57, - 0x54, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x22, 0xed, 0x01, 0x0a, - 0x17, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, - 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, - 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x74, 0x68, - 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, - 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x65, 0x67, 0x65, 0x78, 0x12, 0x5c, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, + 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, + 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x74, 0x0a, 0x17, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x59, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0xc1, 0x01, 0x0a, - 0x1d, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x78, 0x61, - 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x75, - 0x66, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x75, 0x66, 0x66, - 0x69, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x65, - 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, - 0x22, 0xf9, 0x09, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x12, 0x44, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x94, 0x01, 0x0a, + 0x14, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x68, 0x0a, 0x0c, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, + 0x6e, 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, + 0x69, 0x6d, 0x73, 0x22, 0x49, 0x0a, 0x1d, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xcc, + 0x06, 0x0a, 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, + 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, + 0x12, 0x4e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x12, 0x5a, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x0a, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4b, 0x0a, - 0x06, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x45, 0x78, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x4e, 0x49, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x4e, 0x49, 0x12, 0x64, 0x0a, 0x0e, - 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, - 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4d, - 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x4d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, - 0x12, 0x3c, 0x0a, 0x19, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x19, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x51, - 0x0a, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, + 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, + 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, + 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, + 0x6d, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x73, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x5a, 0x0a, 0x0f, 0x45, 0x6e, 0x76, 0x6f, 0x79, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x0f, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, - 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, - 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x74, 0x0a, 0x16, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x44, 0x69, - 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x6c, 0x79, 0x22, 0x5f, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4a, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, + 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x1a, 0x3d, + 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 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, 0x8b, 0x02, + 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, - 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4d, - 0x6f, 0x64, 0x65, 0x22, 0x6f, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x47, 0x0a, 0x05, 0x50, - 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x50, - 0x61, 0x74, 0x68, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, - 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, - 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x28, 0x0a, - 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, - 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x53, 0x0a, 0x09, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x8a, 0x05, 0x0a, 0x0e, 0x55, 0x70, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x11, 0x45, 0x6e, - 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x2a, 0x0a, 0x10, 0x45, 0x6e, 0x76, 0x6f, - 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x4d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x4d, 0x0a, 0x06, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x73, 0x52, 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x50, - 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x5a, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x12, 0x3e, 0x0a, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x22, 0x9e, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x4d, - 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x9e, 0x02, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, - 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x35, - 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, 0x6c, - 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x46, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, - 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, - 0x78, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, 0x63, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, - 0x78, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, - 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, - 0x74, 0x12, 0x45, 0x0a, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, - 0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, - 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, - 0x72, 0x0a, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x64, 0x0a, - 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x22, 0xd0, 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, - 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, - 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, - 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x06, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x1c, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x61, 0x74, - 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x50, 0x0a, 0x03, 0x4a, 0x57, 0x54, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x22, 0xed, 0x01, 0x0a, 0x17, + 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, - 0x67, 0x65, 0x78, 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, - 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, - 0x42, 0x75, 0x72, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x22, 0xca, 0x02, - 0x0a, 0x0a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4f, 0x0a, 0x04, - 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, 0x65, - 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x57, 0x0a, - 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, - 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x5a, 0x0a, 0x06, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x67, 0x65, 0x78, 0x12, 0x5c, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0xfd, 0x01, 0x0a, 0x1d, + 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x45, + 0x78, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x78, 0x61, 0x63, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x75, 0x66, + 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x75, 0x66, 0x66, 0x69, + 0x78, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, + 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x49, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x22, 0xf9, 0x09, 0x0a, 0x0f, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, + 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x44, 0x0a, 0x04, 0x4d, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x69, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x5a, 0x0a, 0x0b, + 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, + 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4b, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, + 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8b, 0x02, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x54, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x4c, 0x61, 0x73, 0x74, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x12, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x69, 0x6d, 0x65, 0x22, 0xb4, 0x03, 0x0a, 0x12, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, - 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, - 0x5d, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x53, - 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, + 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x45, + 0x78, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x53, 0x4e, 0x49, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x45, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x4e, 0x49, 0x12, 0x64, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x55, + 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5a, 0x0a, + 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x44, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x3c, 0x0a, 0x19, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, + 0x52, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x04, + 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x12, 0x5a, 0x0a, 0x0f, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, - 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, - 0x54, 0x4c, 0x53, 0x12, 0x53, 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, + 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x45, + 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, + 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, - 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x51, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x52, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0xde, 0x01, 0x0a, 0x1a, - 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x75, + 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0d, 0x4d, 0x75, 0x74, + 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, + 0x73, 0x68, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, + 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x74, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x32, 0x0a, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, + 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x44, + 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x22, 0x5f, 0x0a, + 0x11, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x4a, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x69, - 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61, 0x78, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x61, - 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, - 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x65, 0x0a, 0x10, - 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x51, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, - 0x4a, 0x57, 0x54, 0x22, 0x76, 0x0a, 0x18, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x5a, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, - 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x69, 0x0a, 0x0c, 0x56, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x45, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x6f, + 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, + 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x47, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, + 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, + 0xb0, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x22, + 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, + 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, + 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x28, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x73, + 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x09, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, - 0x61, 0x69, 0x6d, 0x73, 0x22, 0x4a, 0x0a, 0x1e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0xb7, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, - 0x0a, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xf1, 0x03, 0x0a, 0x0f, 0x42, - 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x54, - 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, - 0x4d, 0x65, 0x74, 0x61, 0x12, 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x12, 0x51, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x73, 0x22, 0x8a, 0x05, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, + 0x53, 0x4f, 0x4e, 0x12, 0x2a, 0x0a, 0x10, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x45, + 0x6e, 0x76, 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x12, + 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2a, 0x0a, 0x10, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x4d, 0x0a, 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, - 0x72, 0x73, 0x12, 0x60, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, + 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, + 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, + 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x12, 0x5a, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, + 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x3e, 0x0a, + 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, + 0x72, 0x22, 0x9e, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x4d, 0x61, + 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, + 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, + 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4d, 0x61, 0x78, + 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x22, 0x9e, 0x02, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, + 0x65, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, + 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x12, 0x2e, 0x0a, 0x12, + 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, + 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x10, + 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x69, 0x6d, 0x65, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x72, 0x0a, 0x0a, 0x52, 0x61, + 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x64, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, + 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xd0, + 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, + 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, + 0x75, 0x72, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, - 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, - 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, 0x1a, 0x7b, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x54, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, + 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x1c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, + 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x2c, + 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x10, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, + 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x22, 0xca, 0x02, 0x0a, 0x0a, 0x41, 0x50, 0x49, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4f, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, + 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x57, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, + 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, + 0x4d, 0x65, 0x74, 0x61, 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, 0x5a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4f, 0x66, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x65, - 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x66, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x03, 0x52, 0x65, 0x66, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x22, 0x8b, 0x02, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x52, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x54, 0x0a, + 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x4c, 0x61, 0x73, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, + 0xb4, 0x03, 0x0a, 0x12, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x48, 0x6f, + 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x48, 0x6f, + 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x08, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x41, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, + 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x53, 0x0a, 0x03, 0x54, 0x4c, 0x53, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x52, 0x03, 0x52, 0x65, 0x66, 0x22, 0xdd, 0x01, 0x0a, 0x17, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, - 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, - 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, + 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x53, + 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x12, 0x51, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x07, 0x44, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0xde, 0x01, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x06, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x82, 0x02, 0x0a, 0x15, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, - 0x5a, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, + 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, + 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, + 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x65, 0x0a, 0x10, 0x41, 0x50, 0x49, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x51, 0x0a, 0x03, 0x4a, + 0x57, 0x54, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x52, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x22, 0x76, + 0x0a, 0x18, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x52, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x5a, 0x0a, 0x09, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, - 0x0a, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, - 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, - 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0xfa, 0x01, 0x0a, 0x11, 0x49, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x12, 0x56, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x41, 0x50, 0x49, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x69, 0x0a, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, + 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x22, + 0x4a, 0x0a, 0x1e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, + 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x11, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xf1, 0x03, 0x0a, 0x0f, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, + 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, + 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, + 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x60, 0x0a, + 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, + 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x1a, 0x7b, 0x0a, 0x0d, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, + 0x54, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, - 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, - 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0xad, 0x03, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x66, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x65, 0x0a, 0x17, 0x4c, 0x69, 0x73, + 0x74, 0x4f, 0x66, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x03, 0x52, 0x65, 0x66, + 0x22, 0xdd, 0x01, 0x0a, 0x17, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x52, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x05, 0x52, 0x75, 0x6c, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x50, + 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, + 0x22, 0x82, 0x02, 0x0a, 0x15, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x5a, 0x0a, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, - 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, + 0x4d, 0x65, 0x74, 0x61, 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, 0xfa, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x56, 0x0a, 0x04, 0x4d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, + 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, + 0x61, 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, 0xad, 0x03, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x12, 0x4e, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x50, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, - 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, - 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0xdf, 0x02, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x73, 0x12, 0x4e, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x1c, 0x0a, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x45, + 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, + 0x61, 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, 0xdf, 0x02, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x52, 0x75, 0x6c, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, - 0x54, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xc4, 0x02, 0x0a, 0x09, 0x48, 0x54, - 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x50, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x06, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x48, 0x0a, 0x04, 0x50, 0x61, 0x74, - 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x4e, + 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x64, + 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x04, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x4b, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x22, 0x8d, 0x01, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x12, 0x50, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x73, 0x52, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x73, 0x22, 0xc4, 0x02, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x12, 0x50, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, + 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, 0x4d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x12, 0x48, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, + 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x4b, + 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x8d, 0x01, 0x0a, 0x0f, + 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, + 0x50, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x75, 0x0a, 0x0d, 0x48, + 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4e, 0x0a, 0x05, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x0e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4f, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, + 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x75, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x4e, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, - 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x0e, 0x48, 0x54, 0x54, 0x50, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4f, 0x0a, 0x05, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa9, 0x03, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, - 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, - 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x52, - 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0d, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x42, 0x0a, - 0x03, 0x4a, 0x57, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, + 0x22, 0xa9, 0x03, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, + 0x12, 0x51, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x0a, 0x55, 0x52, 0x4c, 0x52, + 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, + 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, + 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, + 0x54, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x22, 0x68, 0x0a, 0x13, + 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, + 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x20, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, + 0x72, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0xad, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x74, + 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, 0x52, + 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x4e, 0x75, + 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x65, 0x74, 0x72, + 0x79, 0x4f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x52, 0x65, 0x74, 0x72, 0x79, + 0x4f, 0x6e, 0x12, 0x2e, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x12, + 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, + 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x15, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x0d, 0x54, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3b, 0x0a, + 0x0b, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x49, + 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x67, 0x0a, 0x09, 0x4a, 0x57, + 0x54, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x03, 0x4a, 0x57, - 0x54, 0x22, 0x68, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x20, 0x0a, 0x0a, 0x55, - 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0xad, 0x01, - 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, - 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, - 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x12, 0x2e, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, - 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0d, 0x52, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x52, 0x65, 0x74, 0x72, 0x79, - 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x22, 0x8f, 0x01, - 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, - 0x41, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0b, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, - 0x67, 0x0a, 0x09, 0x4a, 0x57, 0x54, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x09, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xc2, 0x02, 0x0a, 0x10, 0x48, 0x54, 0x54, - 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x52, 0x0a, - 0x03, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, + 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x73, 0x22, 0xc2, 0x02, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x41, + 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x52, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, 0x74, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 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, + 0x1a, 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, 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, 0xc7, 0x02, 0x0a, 0x0b, 0x48, 0x54, 0x54, + 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x57, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x12, 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x73, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, - 0x64, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x52, 0x0a, 0x03, 0x53, 0x65, 0x74, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, - 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, 0x74, 0x1a, 0x36, 0x0a, - 0x08, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x64, 0x0a, 0x0f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x73, 0x52, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x73, 0x22, 0x90, 0x03, 0x0a, 0x08, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, + 0x4d, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x4d, + 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x52, + 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, + 0x4d, 0x65, 0x74, 0x61, 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, 0x1a, 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, 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, 0xc7, 0x02, - 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x06, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7a, 0x0a, 0x0a, 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, + 0x61, 0x22, 0xc8, 0x03, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, + 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x49, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x54, 0x0a, 0x07, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x12, 0x52, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, + 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, + 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, + 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x47, 0x0a, 0x13, + 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x50, 0x65, 0x65, 0x72, 0x22, 0xf1, 0x04, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, + 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, + 0x65, 0x74, 0x52, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x75, 0x64, + 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x41, 0x75, + 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0x90, 0x03, 0x0a, 0x08, 0x54, 0x43, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, - 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, - 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0x7a, 0x0a, 0x0a, 0x54, 0x43, - 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, - 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xc8, 0x03, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, - 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x12, - 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x46, 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, - 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x12, 0x54, 0x0a, 0x07, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, - 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x4d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x52, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, - 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, 0x47, 0x0a, 0x13, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x22, 0xf1, 0x04, 0x0a, 0x0b, 0x4a, - 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x4a, 0x53, - 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, - 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x52, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, - 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1c, - 0x0a, 0x09, 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x09, 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x09, - 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, - 0x0a, 0x0a, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0a, 0x46, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, + 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x46, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x57, 0x0a, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, + 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6c, 0x6f, 0x63, + 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x48, 0x61, 0x73, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, + 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0xa2, 0x01, 0x0a, 0x0d, 0x4a, 0x53, + 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x12, 0x46, 0x0a, 0x05, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x05, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x12, 0x49, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x3b, + 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x4a, + 0x57, 0x4b, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4a, 0x57, 0x4b, 0x53, 0x12, + 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xed, 0x02, 0x0a, 0x0a, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x52, + 0x49, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, 0x49, 0x12, 0x2a, 0x0a, 0x10, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x3f, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x13, 0x46, 0x65, 0x74, + 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x12, 0x58, 0x0a, 0x0b, 0x52, + 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, + 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x54, 0x0a, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x0b, + 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0xdb, 0x01, 0x0a, 0x0b, + 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x63, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xfa, 0x01, 0x0a, 0x12, 0x4a, 0x57, + 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x12, 0x88, 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x1d, 0x43, 0x61, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x09, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, + 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x52, 0x09, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x22, 0x6b, 0x0a, 0x1b, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, + 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x14, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, + 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x12, 0x1a, 0x0a, 0x08, + 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, + 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x20, + 0x0a, 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x22, 0x9c, 0x01, 0x0a, 0x0f, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x52, 0x12, 0x52, 0x65, 0x74, + 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x22, + 0x90, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, + 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x3d, 0x0a, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x22, 0x8f, 0x02, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x6f, - 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, - 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x57, 0x0a, 0x0b, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, - 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0xa2, - 0x01, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, - 0x12, 0x46, 0x0a, 0x05, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, - 0x53, 0x52, 0x05, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x49, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x5c, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x06, 0x52, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x22, 0x3b, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, - 0x12, 0x12, 0x0a, 0x04, 0x4a, 0x57, 0x4b, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x22, 0xed, 0x02, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x12, - 0x10, 0x0a, 0x03, 0x55, 0x52, 0x49, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, - 0x49, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x3f, 0x0a, - 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, - 0x0a, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, - 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x46, 0x65, 0x74, - 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, - 0x12, 0x58, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, - 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x52, - 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x54, 0x0a, 0x0b, 0x4a, 0x57, - 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x52, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x22, 0xdb, 0x01, 0x0a, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x63, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x54, 0x4c, 0x53, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xfa, - 0x01, 0x0a, 0x12, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, - 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x52, 0x1d, 0x43, 0x61, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x12, 0x59, 0x0a, 0x09, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, - 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, - 0x52, 0x09, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x22, 0x6b, 0x0a, 0x1b, 0x4a, - 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, - 0x0a, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x14, 0x4a, 0x57, 0x4b, - 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, - 0x41, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, - 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, - 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x45, 0x6e, 0x76, 0x69, - 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, - 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x0f, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, - 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, - 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x4e, - 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x52, 0x65, 0x74, - 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, - 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, - 0x52, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, - 0x6b, 0x4f, 0x66, 0x66, 0x22, 0x90, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x3d, 0x0a, 0x0c, 0x42, - 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x42, 0x61, - 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0b, 0x4d, 0x61, - 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0x8f, 0x02, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x12, 0x50, 0x0a, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, 0x06, 0x43, 0x6f, + 0x6f, 0x6b, 0x69, 0x65, 0x22, 0x63, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, + 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, + 0x18, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x22, 0x2b, 0x0a, 0x15, 0x4a, 0x57, 0x54, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x27, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, + 0x6f, 0x0a, 0x13, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x22, 0x24, 0x0a, 0x0e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x80, 0x03, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5c, 0x0a, 0x0a, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x0a, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x50, 0x0a, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x55, 0x0a, 0x04, 0x4d, 0x65, 0x74, + 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, - 0x65, 0x52, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x22, 0x63, 0x0a, 0x11, 0x4a, 0x57, 0x54, - 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, - 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x22, 0x2b, - 0x0a, 0x15, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x27, 0x0a, 0x11, 0x4a, - 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x6f, 0x0a, 0x13, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x50, - 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x50, 0x61, - 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x24, 0x0a, 0x0e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x80, 0x03, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, - 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x55, - 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x12, 0x5a, 0x0a, 0x08, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0xaa, - 0x01, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x09, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, - 0x52, 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x22, 0x72, 0x0a, 0x18, 0x45, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x61, 0x6d, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2a, - 0xe2, 0x02, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x69, 0x6e, 0x64, - 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, - 0x64, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01, 0x12, 0x17, 0x0a, - 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, - 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x03, 0x12, 0x19, - 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, - 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x06, 0x12, 0x12, 0x0a, - 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, - 0x07, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, - 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x4b, 0x69, - 0x6e, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x09, 0x12, 0x10, 0x0a, - 0x0c, 0x4b, 0x69, 0x6e, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x0a, 0x12, - 0x15, 0x0a, 0x11, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x10, 0x0b, 0x12, 0x13, 0x0a, 0x0f, 0x4b, 0x69, 0x6e, 0x64, 0x4a, 0x57, - 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x10, 0x0c, 0x12, 0x18, 0x0a, 0x14, 0x4b, - 0x69, 0x6e, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x10, 0x0d, 0x12, 0x1d, 0x0a, 0x19, 0x4b, 0x69, 0x6e, 0x64, 0x46, 0x69, 0x6c, - 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x10, 0x0e, 0x2a, 0x26, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, - 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, - 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x2a, - 0x50, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, - 0x02, 0x2a, 0x5f, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, - 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, - 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, - 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, - 0x69, 0x63, 0x74, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, - 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, - 0x10, 0x02, 0x2a, 0x7b, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, - 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x65, - 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x10, 0x03, 0x2a, - 0x4f, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, - 0x14, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x54, 0x43, 0x50, 0x10, 0x01, - 0x2a, 0x92, 0x02, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, - 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x47, 0x65, 0x74, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x48, - 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x48, 0x65, - 0x61, 0x64, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x05, - 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x50, 0x61, 0x74, 0x63, 0x68, 0x10, 0x06, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, - 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x6f, 0x73, - 0x74, 0x10, 0x07, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x75, 0x74, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x48, - 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x54, 0x72, - 0x61, 0x63, 0x65, 0x10, 0x09, 0x2a, 0xa7, 0x01, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, - 0x14, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x24, - 0x0a, 0x20, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x10, 0x04, 0x2a, - 0x68, 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, - 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, - 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, - 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x2a, 0x6d, 0x0a, 0x12, 0x48, 0x54, 0x54, - 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x74, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x32, 0xd5, 0x01, 0x0a, 0x12, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0xbe, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, - 0x49, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x4a, 0x2e, 0x68, 0x61, 0x73, + 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, + 0x48, 0x61, 0x73, 0x68, 0x12, 0x5a, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x45, + 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 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, 0xaa, 0x01, 0x0a, 0x17, 0x45, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6d, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x0c, - 0x42, 0xae, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x10, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x04, 0x48, 0x43, - 0x49, 0x43, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x22, 0x72, 0x0a, 0x18, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, + 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2a, 0xe2, 0x02, 0x0a, 0x04, 0x4b, + 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x10, + 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x10, 0x05, 0x12, 0x19, 0x0a, + 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x06, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, + 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, + 0x4b, 0x69, 0x6e, 0x64, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x4b, 0x69, 0x6e, 0x64, 0x48, 0x54, 0x54, + 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x09, 0x12, 0x10, 0x0a, 0x0c, 0x4b, 0x69, 0x6e, 0x64, + 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x0a, 0x12, 0x15, 0x0a, 0x11, 0x4b, 0x69, + 0x6e, 0x64, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x10, + 0x0b, 0x12, 0x13, 0x0a, 0x0f, 0x4b, 0x69, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x10, 0x0c, 0x12, 0x18, 0x0a, 0x14, 0x4b, 0x69, 0x6e, 0x64, 0x45, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x10, 0x0d, + 0x12, 0x1d, 0x0a, 0x19, 0x4b, 0x69, 0x6e, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x0e, 0x2a, + 0xfe, 0x01, 0x0a, 0x1c, 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, + 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x27, 0x0a, 0x23, 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, + 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x50, 0x61, 0x74, + 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x65, 0x70, 0x10, 0x01, 0x12, + 0x26, 0x0a, 0x22, 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, + 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x6a, 0x65, 0x63, 0x74, 0x10, 0x02, 0x12, 0x33, 0x0a, 0x2f, 0x50, 0x61, 0x74, 0x68, 0x57, + 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x41, + 0x6e, 0x64, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x03, 0x12, 0x32, 0x0a, 0x2e, + 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x65, 0x73, + 0x63, 0x61, 0x70, 0x65, 0x41, 0x6e, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x10, 0x04, + 0x2a, 0xa0, 0x01, 0x0a, 0x1c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, + 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x25, 0x0a, 0x21, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, + 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0x00, 0x12, 0x2d, 0x0a, 0x29, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x2a, 0x0a, 0x26, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x72, 0x6f, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x10, 0x02, 0x2a, 0x26, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, + 0x12, 0x09, 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x2a, 0x50, + 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, + 0x00, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, + 0x2a, 0x5f, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, + 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, + 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, + 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x10, + 0x02, 0x2a, 0x7b, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, + 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, + 0x6f, 0x64, 0x65, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x65, 0x73, + 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x10, 0x03, 0x2a, 0x4f, + 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x14, + 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x54, 0x43, 0x50, 0x10, 0x01, 0x2a, + 0x92, 0x02, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x48, + 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x47, 0x65, 0x74, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, + 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x48, 0x65, 0x61, + 0x64, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x05, 0x12, + 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x50, 0x61, 0x74, 0x63, 0x68, 0x10, 0x06, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, + 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x6f, 0x73, 0x74, + 0x10, 0x07, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x75, 0x74, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, + 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x54, 0x72, 0x61, + 0x63, 0x65, 0x10, 0x09, 0x2a, 0xa7, 0x01, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, + 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, + 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x10, + 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x24, 0x0a, + 0x20, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x10, 0x04, 0x2a, 0x68, + 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x48, + 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x2a, 0x6d, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, + 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, + 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x32, 0xd5, 0x01, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xbe, + 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x49, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x4a, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x0c, 0x42, + 0xae, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x10, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, + 0x43, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -10193,345 +10523,353 @@ func file_private_pbconfigentry_config_entry_proto_rawDescGZIP() []byte { return file_private_pbconfigentry_config_entry_proto_rawDescData } -var file_private_pbconfigentry_config_entry_proto_enumTypes = make([]protoimpl.EnumInfo, 11) -var file_private_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 127) +var file_private_pbconfigentry_config_entry_proto_enumTypes = make([]protoimpl.EnumInfo, 13) +var file_private_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 129) var file_private_pbconfigentry_config_entry_proto_goTypes = []interface{}{ (Kind)(0), // 0: hashicorp.consul.internal.configentry.Kind - (IntentionAction)(0), // 1: hashicorp.consul.internal.configentry.IntentionAction - (IntentionSourceType)(0), // 2: hashicorp.consul.internal.configentry.IntentionSourceType - (ProxyMode)(0), // 3: hashicorp.consul.internal.configentry.ProxyMode - (MutualTLSMode)(0), // 4: hashicorp.consul.internal.configentry.MutualTLSMode - (MeshGatewayMode)(0), // 5: hashicorp.consul.internal.configentry.MeshGatewayMode - (APIGatewayListenerProtocol)(0), // 6: hashicorp.consul.internal.configentry.APIGatewayListenerProtocol - (HTTPMatchMethod)(0), // 7: hashicorp.consul.internal.configentry.HTTPMatchMethod - (HTTPHeaderMatchType)(0), // 8: hashicorp.consul.internal.configentry.HTTPHeaderMatchType - (HTTPPathMatchType)(0), // 9: hashicorp.consul.internal.configentry.HTTPPathMatchType - (HTTPQueryMatchType)(0), // 10: hashicorp.consul.internal.configentry.HTTPQueryMatchType - (*GetResolvedExportedServicesRequest)(nil), // 11: hashicorp.consul.internal.configentry.GetResolvedExportedServicesRequest - (*GetResolvedExportedServicesResponse)(nil), // 12: hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse - (*ResolvedExportedService)(nil), // 13: hashicorp.consul.internal.configentry.ResolvedExportedService - (*Consumers)(nil), // 14: hashicorp.consul.internal.configentry.Consumers - (*ConfigEntry)(nil), // 15: hashicorp.consul.internal.configentry.ConfigEntry - (*MeshConfig)(nil), // 16: hashicorp.consul.internal.configentry.MeshConfig - (*TransparentProxyMeshConfig)(nil), // 17: hashicorp.consul.internal.configentry.TransparentProxyMeshConfig - (*MeshTLSConfig)(nil), // 18: hashicorp.consul.internal.configentry.MeshTLSConfig - (*MeshDirectionalTLSConfig)(nil), // 19: hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - (*MeshHTTPConfig)(nil), // 20: hashicorp.consul.internal.configentry.MeshHTTPConfig - (*PeeringMeshConfig)(nil), // 21: hashicorp.consul.internal.configentry.PeeringMeshConfig - (*ServiceResolver)(nil), // 22: hashicorp.consul.internal.configentry.ServiceResolver - (*ServiceResolverSubset)(nil), // 23: hashicorp.consul.internal.configentry.ServiceResolverSubset - (*ServiceResolverRedirect)(nil), // 24: hashicorp.consul.internal.configentry.ServiceResolverRedirect - (*ServiceResolverFailover)(nil), // 25: hashicorp.consul.internal.configentry.ServiceResolverFailover - (*ServiceResolverFailoverPolicy)(nil), // 26: hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy - (*ServiceResolverPrioritizeByLocality)(nil), // 27: hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality - (*ServiceResolverFailoverTarget)(nil), // 28: hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget - (*LoadBalancer)(nil), // 29: hashicorp.consul.internal.configentry.LoadBalancer - (*RingHashConfig)(nil), // 30: hashicorp.consul.internal.configentry.RingHashConfig - (*LeastRequestConfig)(nil), // 31: hashicorp.consul.internal.configentry.LeastRequestConfig - (*HashPolicy)(nil), // 32: hashicorp.consul.internal.configentry.HashPolicy - (*CookieConfig)(nil), // 33: hashicorp.consul.internal.configentry.CookieConfig - (*IngressGateway)(nil), // 34: hashicorp.consul.internal.configentry.IngressGateway - (*IngressServiceConfig)(nil), // 35: hashicorp.consul.internal.configentry.IngressServiceConfig - (*GatewayTLSConfig)(nil), // 36: hashicorp.consul.internal.configentry.GatewayTLSConfig - (*GatewayTLSSDSConfig)(nil), // 37: hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - (*IngressListener)(nil), // 38: hashicorp.consul.internal.configentry.IngressListener - (*IngressService)(nil), // 39: hashicorp.consul.internal.configentry.IngressService - (*GatewayServiceTLSConfig)(nil), // 40: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig - (*HTTPHeaderModifiers)(nil), // 41: hashicorp.consul.internal.configentry.HTTPHeaderModifiers - (*ServiceIntentions)(nil), // 42: hashicorp.consul.internal.configentry.ServiceIntentions - (*IntentionJWTRequirement)(nil), // 43: hashicorp.consul.internal.configentry.IntentionJWTRequirement - (*IntentionJWTProvider)(nil), // 44: hashicorp.consul.internal.configentry.IntentionJWTProvider - (*IntentionJWTClaimVerification)(nil), // 45: hashicorp.consul.internal.configentry.IntentionJWTClaimVerification - (*SourceIntention)(nil), // 46: hashicorp.consul.internal.configentry.SourceIntention - (*IntentionPermission)(nil), // 47: hashicorp.consul.internal.configentry.IntentionPermission - (*IntentionHTTPPermission)(nil), // 48: hashicorp.consul.internal.configentry.IntentionHTTPPermission - (*IntentionHTTPHeaderPermission)(nil), // 49: hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission - (*ServiceDefaults)(nil), // 50: hashicorp.consul.internal.configentry.ServiceDefaults - (*TransparentProxyConfig)(nil), // 51: hashicorp.consul.internal.configentry.TransparentProxyConfig - (*MeshGatewayConfig)(nil), // 52: hashicorp.consul.internal.configentry.MeshGatewayConfig - (*ExposeConfig)(nil), // 53: hashicorp.consul.internal.configentry.ExposeConfig - (*ExposePath)(nil), // 54: hashicorp.consul.internal.configentry.ExposePath - (*UpstreamConfiguration)(nil), // 55: hashicorp.consul.internal.configentry.UpstreamConfiguration - (*UpstreamConfig)(nil), // 56: hashicorp.consul.internal.configentry.UpstreamConfig - (*UpstreamLimits)(nil), // 57: hashicorp.consul.internal.configentry.UpstreamLimits - (*PassiveHealthCheck)(nil), // 58: hashicorp.consul.internal.configentry.PassiveHealthCheck - (*DestinationConfig)(nil), // 59: hashicorp.consul.internal.configentry.DestinationConfig - (*RateLimits)(nil), // 60: hashicorp.consul.internal.configentry.RateLimits - (*InstanceLevelRateLimits)(nil), // 61: hashicorp.consul.internal.configentry.InstanceLevelRateLimits - (*InstanceLevelRouteRateLimits)(nil), // 62: hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits - (*APIGateway)(nil), // 63: hashicorp.consul.internal.configentry.APIGateway - (*Status)(nil), // 64: hashicorp.consul.internal.configentry.Status - (*Condition)(nil), // 65: hashicorp.consul.internal.configentry.Condition - (*APIGatewayListener)(nil), // 66: hashicorp.consul.internal.configentry.APIGatewayListener - (*APIGatewayTLSConfiguration)(nil), // 67: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration - (*APIGatewayPolicy)(nil), // 68: hashicorp.consul.internal.configentry.APIGatewayPolicy - (*APIGatewayJWTRequirement)(nil), // 69: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement - (*APIGatewayJWTProvider)(nil), // 70: hashicorp.consul.internal.configentry.APIGatewayJWTProvider - (*APIGatewayJWTClaimVerification)(nil), // 71: hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification - (*ResourceReference)(nil), // 72: hashicorp.consul.internal.configentry.ResourceReference - (*BoundAPIGateway)(nil), // 73: hashicorp.consul.internal.configentry.BoundAPIGateway - (*ListOfResourceReference)(nil), // 74: hashicorp.consul.internal.configentry.ListOfResourceReference - (*BoundAPIGatewayListener)(nil), // 75: hashicorp.consul.internal.configentry.BoundAPIGatewayListener - (*FileSystemCertificate)(nil), // 76: hashicorp.consul.internal.configentry.FileSystemCertificate - (*InlineCertificate)(nil), // 77: hashicorp.consul.internal.configentry.InlineCertificate - (*HTTPRoute)(nil), // 78: hashicorp.consul.internal.configentry.HTTPRoute - (*HTTPRouteRule)(nil), // 79: hashicorp.consul.internal.configentry.HTTPRouteRule - (*HTTPMatch)(nil), // 80: hashicorp.consul.internal.configentry.HTTPMatch - (*HTTPHeaderMatch)(nil), // 81: hashicorp.consul.internal.configentry.HTTPHeaderMatch - (*HTTPPathMatch)(nil), // 82: hashicorp.consul.internal.configentry.HTTPPathMatch - (*HTTPQueryMatch)(nil), // 83: hashicorp.consul.internal.configentry.HTTPQueryMatch - (*HTTPFilters)(nil), // 84: hashicorp.consul.internal.configentry.HTTPFilters - (*HTTPResponseFilters)(nil), // 85: hashicorp.consul.internal.configentry.HTTPResponseFilters - (*URLRewrite)(nil), // 86: hashicorp.consul.internal.configentry.URLRewrite - (*RetryFilter)(nil), // 87: hashicorp.consul.internal.configentry.RetryFilter - (*TimeoutFilter)(nil), // 88: hashicorp.consul.internal.configentry.TimeoutFilter - (*JWTFilter)(nil), // 89: hashicorp.consul.internal.configentry.JWTFilter - (*HTTPHeaderFilter)(nil), // 90: hashicorp.consul.internal.configentry.HTTPHeaderFilter - (*HTTPService)(nil), // 91: hashicorp.consul.internal.configentry.HTTPService - (*TCPRoute)(nil), // 92: hashicorp.consul.internal.configentry.TCPRoute - (*TCPService)(nil), // 93: hashicorp.consul.internal.configentry.TCPService - (*SamenessGroup)(nil), // 94: hashicorp.consul.internal.configentry.SamenessGroup - (*SamenessGroupMember)(nil), // 95: hashicorp.consul.internal.configentry.SamenessGroupMember - (*JWTProvider)(nil), // 96: hashicorp.consul.internal.configentry.JWTProvider - (*JSONWebKeySet)(nil), // 97: hashicorp.consul.internal.configentry.JSONWebKeySet - (*LocalJWKS)(nil), // 98: hashicorp.consul.internal.configentry.LocalJWKS - (*RemoteJWKS)(nil), // 99: hashicorp.consul.internal.configentry.RemoteJWKS - (*JWKSCluster)(nil), // 100: hashicorp.consul.internal.configentry.JWKSCluster - (*JWKSTLSCertificate)(nil), // 101: hashicorp.consul.internal.configentry.JWKSTLSCertificate - (*JWKSTLSCertProviderInstance)(nil), // 102: hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance - (*JWKSTLSCertTrustedCA)(nil), // 103: hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA - (*JWKSRetryPolicy)(nil), // 104: hashicorp.consul.internal.configentry.JWKSRetryPolicy - (*RetryPolicyBackOff)(nil), // 105: hashicorp.consul.internal.configentry.RetryPolicyBackOff - (*JWTLocation)(nil), // 106: hashicorp.consul.internal.configentry.JWTLocation - (*JWTLocationHeader)(nil), // 107: hashicorp.consul.internal.configentry.JWTLocationHeader - (*JWTLocationQueryParam)(nil), // 108: hashicorp.consul.internal.configentry.JWTLocationQueryParam - (*JWTLocationCookie)(nil), // 109: hashicorp.consul.internal.configentry.JWTLocationCookie - (*JWTForwardingConfig)(nil), // 110: hashicorp.consul.internal.configentry.JWTForwardingConfig - (*JWTCacheConfig)(nil), // 111: hashicorp.consul.internal.configentry.JWTCacheConfig - (*ExportedServices)(nil), // 112: hashicorp.consul.internal.configentry.ExportedServices - (*ExportedServicesService)(nil), // 113: hashicorp.consul.internal.configentry.ExportedServicesService - (*ExportedServicesConsumer)(nil), // 114: hashicorp.consul.internal.configentry.ExportedServicesConsumer - nil, // 115: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry - nil, // 116: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry - nil, // 117: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry - nil, // 118: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry - nil, // 119: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry - nil, // 120: hashicorp.consul.internal.configentry.IngressService.MetaEntry - nil, // 121: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry - nil, // 122: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry - nil, // 123: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry - nil, // 124: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry - nil, // 125: hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry - nil, // 126: hashicorp.consul.internal.configentry.APIGateway.MetaEntry - nil, // 127: hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry - nil, // 128: hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry - nil, // 129: hashicorp.consul.internal.configentry.FileSystemCertificate.MetaEntry - nil, // 130: hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry - nil, // 131: hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry - nil, // 132: hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry - nil, // 133: hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry - nil, // 134: hashicorp.consul.internal.configentry.TCPRoute.MetaEntry - nil, // 135: hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry - nil, // 136: hashicorp.consul.internal.configentry.JWTProvider.MetaEntry - nil, // 137: hashicorp.consul.internal.configentry.ExportedServices.MetaEntry - (*pbcommon.EnterpriseMeta)(nil), // 138: hashicorp.consul.internal.common.EnterpriseMeta - (*pbcommon.RaftIndex)(nil), // 139: hashicorp.consul.internal.common.RaftIndex - (*durationpb.Duration)(nil), // 140: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 141: google.protobuf.Timestamp - (*pbcommon.EnvoyExtension)(nil), // 142: hashicorp.consul.internal.common.EnvoyExtension + (PathWithEscapedSlashesAction)(0), // 1: hashicorp.consul.internal.configentry.PathWithEscapedSlashesAction + (HeadersWithUnderscoresAction)(0), // 2: hashicorp.consul.internal.configentry.HeadersWithUnderscoresAction + (IntentionAction)(0), // 3: hashicorp.consul.internal.configentry.IntentionAction + (IntentionSourceType)(0), // 4: hashicorp.consul.internal.configentry.IntentionSourceType + (ProxyMode)(0), // 5: hashicorp.consul.internal.configentry.ProxyMode + (MutualTLSMode)(0), // 6: hashicorp.consul.internal.configentry.MutualTLSMode + (MeshGatewayMode)(0), // 7: hashicorp.consul.internal.configentry.MeshGatewayMode + (APIGatewayListenerProtocol)(0), // 8: hashicorp.consul.internal.configentry.APIGatewayListenerProtocol + (HTTPMatchMethod)(0), // 9: hashicorp.consul.internal.configentry.HTTPMatchMethod + (HTTPHeaderMatchType)(0), // 10: hashicorp.consul.internal.configentry.HTTPHeaderMatchType + (HTTPPathMatchType)(0), // 11: hashicorp.consul.internal.configentry.HTTPPathMatchType + (HTTPQueryMatchType)(0), // 12: hashicorp.consul.internal.configentry.HTTPQueryMatchType + (*GetResolvedExportedServicesRequest)(nil), // 13: hashicorp.consul.internal.configentry.GetResolvedExportedServicesRequest + (*GetResolvedExportedServicesResponse)(nil), // 14: hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse + (*ResolvedExportedService)(nil), // 15: hashicorp.consul.internal.configentry.ResolvedExportedService + (*Consumers)(nil), // 16: hashicorp.consul.internal.configentry.Consumers + (*ConfigEntry)(nil), // 17: hashicorp.consul.internal.configentry.ConfigEntry + (*MeshConfig)(nil), // 18: hashicorp.consul.internal.configentry.MeshConfig + (*TransparentProxyMeshConfig)(nil), // 19: hashicorp.consul.internal.configentry.TransparentProxyMeshConfig + (*MeshTLSConfig)(nil), // 20: hashicorp.consul.internal.configentry.MeshTLSConfig + (*MeshDirectionalTLSConfig)(nil), // 21: hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + (*MeshHTTPConfig)(nil), // 22: hashicorp.consul.internal.configentry.MeshHTTPConfig + (*MeshDirectionalHTTPConfig)(nil), // 23: hashicorp.consul.internal.configentry.MeshDirectionalHTTPConfig + (*PeeringMeshConfig)(nil), // 24: hashicorp.consul.internal.configentry.PeeringMeshConfig + (*RequestNormalizationMeshConfig)(nil), // 25: hashicorp.consul.internal.configentry.RequestNormalizationMeshConfig + (*ServiceResolver)(nil), // 26: hashicorp.consul.internal.configentry.ServiceResolver + (*ServiceResolverSubset)(nil), // 27: hashicorp.consul.internal.configentry.ServiceResolverSubset + (*ServiceResolverRedirect)(nil), // 28: hashicorp.consul.internal.configentry.ServiceResolverRedirect + (*ServiceResolverFailover)(nil), // 29: hashicorp.consul.internal.configentry.ServiceResolverFailover + (*ServiceResolverFailoverPolicy)(nil), // 30: hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy + (*ServiceResolverPrioritizeByLocality)(nil), // 31: hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality + (*ServiceResolverFailoverTarget)(nil), // 32: hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget + (*LoadBalancer)(nil), // 33: hashicorp.consul.internal.configentry.LoadBalancer + (*RingHashConfig)(nil), // 34: hashicorp.consul.internal.configentry.RingHashConfig + (*LeastRequestConfig)(nil), // 35: hashicorp.consul.internal.configentry.LeastRequestConfig + (*HashPolicy)(nil), // 36: hashicorp.consul.internal.configentry.HashPolicy + (*CookieConfig)(nil), // 37: hashicorp.consul.internal.configentry.CookieConfig + (*IngressGateway)(nil), // 38: hashicorp.consul.internal.configentry.IngressGateway + (*IngressServiceConfig)(nil), // 39: hashicorp.consul.internal.configentry.IngressServiceConfig + (*GatewayTLSConfig)(nil), // 40: hashicorp.consul.internal.configentry.GatewayTLSConfig + (*GatewayTLSSDSConfig)(nil), // 41: hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + (*IngressListener)(nil), // 42: hashicorp.consul.internal.configentry.IngressListener + (*IngressService)(nil), // 43: hashicorp.consul.internal.configentry.IngressService + (*GatewayServiceTLSConfig)(nil), // 44: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig + (*HTTPHeaderModifiers)(nil), // 45: hashicorp.consul.internal.configentry.HTTPHeaderModifiers + (*ServiceIntentions)(nil), // 46: hashicorp.consul.internal.configentry.ServiceIntentions + (*IntentionJWTRequirement)(nil), // 47: hashicorp.consul.internal.configentry.IntentionJWTRequirement + (*IntentionJWTProvider)(nil), // 48: hashicorp.consul.internal.configentry.IntentionJWTProvider + (*IntentionJWTClaimVerification)(nil), // 49: hashicorp.consul.internal.configentry.IntentionJWTClaimVerification + (*SourceIntention)(nil), // 50: hashicorp.consul.internal.configentry.SourceIntention + (*IntentionPermission)(nil), // 51: hashicorp.consul.internal.configentry.IntentionPermission + (*IntentionHTTPPermission)(nil), // 52: hashicorp.consul.internal.configentry.IntentionHTTPPermission + (*IntentionHTTPHeaderPermission)(nil), // 53: hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission + (*ServiceDefaults)(nil), // 54: hashicorp.consul.internal.configentry.ServiceDefaults + (*TransparentProxyConfig)(nil), // 55: hashicorp.consul.internal.configentry.TransparentProxyConfig + (*MeshGatewayConfig)(nil), // 56: hashicorp.consul.internal.configentry.MeshGatewayConfig + (*ExposeConfig)(nil), // 57: hashicorp.consul.internal.configentry.ExposeConfig + (*ExposePath)(nil), // 58: hashicorp.consul.internal.configentry.ExposePath + (*UpstreamConfiguration)(nil), // 59: hashicorp.consul.internal.configentry.UpstreamConfiguration + (*UpstreamConfig)(nil), // 60: hashicorp.consul.internal.configentry.UpstreamConfig + (*UpstreamLimits)(nil), // 61: hashicorp.consul.internal.configentry.UpstreamLimits + (*PassiveHealthCheck)(nil), // 62: hashicorp.consul.internal.configentry.PassiveHealthCheck + (*DestinationConfig)(nil), // 63: hashicorp.consul.internal.configentry.DestinationConfig + (*RateLimits)(nil), // 64: hashicorp.consul.internal.configentry.RateLimits + (*InstanceLevelRateLimits)(nil), // 65: hashicorp.consul.internal.configentry.InstanceLevelRateLimits + (*InstanceLevelRouteRateLimits)(nil), // 66: hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits + (*APIGateway)(nil), // 67: hashicorp.consul.internal.configentry.APIGateway + (*Status)(nil), // 68: hashicorp.consul.internal.configentry.Status + (*Condition)(nil), // 69: hashicorp.consul.internal.configentry.Condition + (*APIGatewayListener)(nil), // 70: hashicorp.consul.internal.configentry.APIGatewayListener + (*APIGatewayTLSConfiguration)(nil), // 71: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration + (*APIGatewayPolicy)(nil), // 72: hashicorp.consul.internal.configentry.APIGatewayPolicy + (*APIGatewayJWTRequirement)(nil), // 73: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement + (*APIGatewayJWTProvider)(nil), // 74: hashicorp.consul.internal.configentry.APIGatewayJWTProvider + (*APIGatewayJWTClaimVerification)(nil), // 75: hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification + (*ResourceReference)(nil), // 76: hashicorp.consul.internal.configentry.ResourceReference + (*BoundAPIGateway)(nil), // 77: hashicorp.consul.internal.configentry.BoundAPIGateway + (*ListOfResourceReference)(nil), // 78: hashicorp.consul.internal.configentry.ListOfResourceReference + (*BoundAPIGatewayListener)(nil), // 79: hashicorp.consul.internal.configentry.BoundAPIGatewayListener + (*FileSystemCertificate)(nil), // 80: hashicorp.consul.internal.configentry.FileSystemCertificate + (*InlineCertificate)(nil), // 81: hashicorp.consul.internal.configentry.InlineCertificate + (*HTTPRoute)(nil), // 82: hashicorp.consul.internal.configentry.HTTPRoute + (*HTTPRouteRule)(nil), // 83: hashicorp.consul.internal.configentry.HTTPRouteRule + (*HTTPMatch)(nil), // 84: hashicorp.consul.internal.configentry.HTTPMatch + (*HTTPHeaderMatch)(nil), // 85: hashicorp.consul.internal.configentry.HTTPHeaderMatch + (*HTTPPathMatch)(nil), // 86: hashicorp.consul.internal.configentry.HTTPPathMatch + (*HTTPQueryMatch)(nil), // 87: hashicorp.consul.internal.configentry.HTTPQueryMatch + (*HTTPFilters)(nil), // 88: hashicorp.consul.internal.configentry.HTTPFilters + (*HTTPResponseFilters)(nil), // 89: hashicorp.consul.internal.configentry.HTTPResponseFilters + (*URLRewrite)(nil), // 90: hashicorp.consul.internal.configentry.URLRewrite + (*RetryFilter)(nil), // 91: hashicorp.consul.internal.configentry.RetryFilter + (*TimeoutFilter)(nil), // 92: hashicorp.consul.internal.configentry.TimeoutFilter + (*JWTFilter)(nil), // 93: hashicorp.consul.internal.configentry.JWTFilter + (*HTTPHeaderFilter)(nil), // 94: hashicorp.consul.internal.configentry.HTTPHeaderFilter + (*HTTPService)(nil), // 95: hashicorp.consul.internal.configentry.HTTPService + (*TCPRoute)(nil), // 96: hashicorp.consul.internal.configentry.TCPRoute + (*TCPService)(nil), // 97: hashicorp.consul.internal.configentry.TCPService + (*SamenessGroup)(nil), // 98: hashicorp.consul.internal.configentry.SamenessGroup + (*SamenessGroupMember)(nil), // 99: hashicorp.consul.internal.configentry.SamenessGroupMember + (*JWTProvider)(nil), // 100: hashicorp.consul.internal.configentry.JWTProvider + (*JSONWebKeySet)(nil), // 101: hashicorp.consul.internal.configentry.JSONWebKeySet + (*LocalJWKS)(nil), // 102: hashicorp.consul.internal.configentry.LocalJWKS + (*RemoteJWKS)(nil), // 103: hashicorp.consul.internal.configentry.RemoteJWKS + (*JWKSCluster)(nil), // 104: hashicorp.consul.internal.configentry.JWKSCluster + (*JWKSTLSCertificate)(nil), // 105: hashicorp.consul.internal.configentry.JWKSTLSCertificate + (*JWKSTLSCertProviderInstance)(nil), // 106: hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance + (*JWKSTLSCertTrustedCA)(nil), // 107: hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA + (*JWKSRetryPolicy)(nil), // 108: hashicorp.consul.internal.configentry.JWKSRetryPolicy + (*RetryPolicyBackOff)(nil), // 109: hashicorp.consul.internal.configentry.RetryPolicyBackOff + (*JWTLocation)(nil), // 110: hashicorp.consul.internal.configentry.JWTLocation + (*JWTLocationHeader)(nil), // 111: hashicorp.consul.internal.configentry.JWTLocationHeader + (*JWTLocationQueryParam)(nil), // 112: hashicorp.consul.internal.configentry.JWTLocationQueryParam + (*JWTLocationCookie)(nil), // 113: hashicorp.consul.internal.configentry.JWTLocationCookie + (*JWTForwardingConfig)(nil), // 114: hashicorp.consul.internal.configentry.JWTForwardingConfig + (*JWTCacheConfig)(nil), // 115: hashicorp.consul.internal.configentry.JWTCacheConfig + (*ExportedServices)(nil), // 116: hashicorp.consul.internal.configentry.ExportedServices + (*ExportedServicesService)(nil), // 117: hashicorp.consul.internal.configentry.ExportedServicesService + (*ExportedServicesConsumer)(nil), // 118: hashicorp.consul.internal.configentry.ExportedServicesConsumer + nil, // 119: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + nil, // 120: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + nil, // 121: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + nil, // 122: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + nil, // 123: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + nil, // 124: hashicorp.consul.internal.configentry.IngressService.MetaEntry + nil, // 125: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + nil, // 126: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + nil, // 127: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + nil, // 128: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + nil, // 129: hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry + nil, // 130: hashicorp.consul.internal.configentry.APIGateway.MetaEntry + nil, // 131: hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry + nil, // 132: hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry + nil, // 133: hashicorp.consul.internal.configentry.FileSystemCertificate.MetaEntry + nil, // 134: hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry + nil, // 135: hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry + nil, // 136: hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry + nil, // 137: hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry + nil, // 138: hashicorp.consul.internal.configentry.TCPRoute.MetaEntry + nil, // 139: hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry + nil, // 140: hashicorp.consul.internal.configentry.JWTProvider.MetaEntry + nil, // 141: hashicorp.consul.internal.configentry.ExportedServices.MetaEntry + (*pbcommon.EnterpriseMeta)(nil), // 142: hashicorp.consul.internal.common.EnterpriseMeta + (*pbcommon.RaftIndex)(nil), // 143: hashicorp.consul.internal.common.RaftIndex + (*durationpb.Duration)(nil), // 144: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 145: google.protobuf.Timestamp + (*pbcommon.EnvoyExtension)(nil), // 146: hashicorp.consul.internal.common.EnvoyExtension } var file_private_pbconfigentry_config_entry_proto_depIdxs = []int32{ - 13, // 0: hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse.services:type_name -> hashicorp.consul.internal.configentry.ResolvedExportedService - 138, // 1: hashicorp.consul.internal.configentry.ResolvedExportedService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 14, // 2: hashicorp.consul.internal.configentry.ResolvedExportedService.Consumers:type_name -> hashicorp.consul.internal.configentry.Consumers + 15, // 0: hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse.services:type_name -> hashicorp.consul.internal.configentry.ResolvedExportedService + 142, // 1: hashicorp.consul.internal.configentry.ResolvedExportedService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 16, // 2: hashicorp.consul.internal.configentry.ResolvedExportedService.Consumers:type_name -> hashicorp.consul.internal.configentry.Consumers 0, // 3: hashicorp.consul.internal.configentry.ConfigEntry.Kind:type_name -> hashicorp.consul.internal.configentry.Kind - 138, // 4: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 139, // 5: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex - 16, // 6: hashicorp.consul.internal.configentry.ConfigEntry.MeshConfig:type_name -> hashicorp.consul.internal.configentry.MeshConfig - 22, // 7: hashicorp.consul.internal.configentry.ConfigEntry.ServiceResolver:type_name -> hashicorp.consul.internal.configentry.ServiceResolver - 34, // 8: hashicorp.consul.internal.configentry.ConfigEntry.IngressGateway:type_name -> hashicorp.consul.internal.configentry.IngressGateway - 42, // 9: hashicorp.consul.internal.configentry.ConfigEntry.ServiceIntentions:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions - 50, // 10: hashicorp.consul.internal.configentry.ConfigEntry.ServiceDefaults:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults - 63, // 11: hashicorp.consul.internal.configentry.ConfigEntry.APIGateway:type_name -> hashicorp.consul.internal.configentry.APIGateway - 73, // 12: hashicorp.consul.internal.configentry.ConfigEntry.BoundAPIGateway:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway - 92, // 13: hashicorp.consul.internal.configentry.ConfigEntry.TCPRoute:type_name -> hashicorp.consul.internal.configentry.TCPRoute - 78, // 14: hashicorp.consul.internal.configentry.ConfigEntry.HTTPRoute:type_name -> hashicorp.consul.internal.configentry.HTTPRoute - 77, // 15: hashicorp.consul.internal.configentry.ConfigEntry.InlineCertificate:type_name -> hashicorp.consul.internal.configentry.InlineCertificate - 94, // 16: hashicorp.consul.internal.configentry.ConfigEntry.SamenessGroup:type_name -> hashicorp.consul.internal.configentry.SamenessGroup - 96, // 17: hashicorp.consul.internal.configentry.ConfigEntry.JWTProvider:type_name -> hashicorp.consul.internal.configentry.JWTProvider - 112, // 18: hashicorp.consul.internal.configentry.ConfigEntry.ExportedServices:type_name -> hashicorp.consul.internal.configentry.ExportedServices - 76, // 19: hashicorp.consul.internal.configentry.ConfigEntry.FileSystemCertificate:type_name -> hashicorp.consul.internal.configentry.FileSystemCertificate - 17, // 20: hashicorp.consul.internal.configentry.MeshConfig.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyMeshConfig - 18, // 21: hashicorp.consul.internal.configentry.MeshConfig.TLS:type_name -> hashicorp.consul.internal.configentry.MeshTLSConfig - 20, // 22: hashicorp.consul.internal.configentry.MeshConfig.HTTP:type_name -> hashicorp.consul.internal.configentry.MeshHTTPConfig - 115, // 23: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry - 21, // 24: hashicorp.consul.internal.configentry.MeshConfig.Peering:type_name -> hashicorp.consul.internal.configentry.PeeringMeshConfig - 19, // 25: hashicorp.consul.internal.configentry.MeshTLSConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - 19, // 26: hashicorp.consul.internal.configentry.MeshTLSConfig.Outgoing:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - 116, // 27: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry - 24, // 28: hashicorp.consul.internal.configentry.ServiceResolver.Redirect:type_name -> hashicorp.consul.internal.configentry.ServiceResolverRedirect - 117, // 29: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry - 140, // 30: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration - 29, // 31: hashicorp.consul.internal.configentry.ServiceResolver.LoadBalancer:type_name -> hashicorp.consul.internal.configentry.LoadBalancer - 118, // 32: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry - 140, // 33: hashicorp.consul.internal.configentry.ServiceResolver.RequestTimeout:type_name -> google.protobuf.Duration - 27, // 34: hashicorp.consul.internal.configentry.ServiceResolver.PrioritizeByLocality:type_name -> hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality - 28, // 35: hashicorp.consul.internal.configentry.ServiceResolverFailover.Targets:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget - 26, // 36: hashicorp.consul.internal.configentry.ServiceResolverFailover.Policy:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy - 30, // 37: hashicorp.consul.internal.configentry.LoadBalancer.RingHashConfig:type_name -> hashicorp.consul.internal.configentry.RingHashConfig - 31, // 38: hashicorp.consul.internal.configentry.LoadBalancer.LeastRequestConfig:type_name -> hashicorp.consul.internal.configentry.LeastRequestConfig - 32, // 39: hashicorp.consul.internal.configentry.LoadBalancer.HashPolicies:type_name -> hashicorp.consul.internal.configentry.HashPolicy - 33, // 40: hashicorp.consul.internal.configentry.HashPolicy.CookieConfig:type_name -> hashicorp.consul.internal.configentry.CookieConfig - 140, // 41: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration - 36, // 42: hashicorp.consul.internal.configentry.IngressGateway.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig - 38, // 43: hashicorp.consul.internal.configentry.IngressGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.IngressListener - 119, // 44: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry - 35, // 45: hashicorp.consul.internal.configentry.IngressGateway.Defaults:type_name -> hashicorp.consul.internal.configentry.IngressServiceConfig - 58, // 46: hashicorp.consul.internal.configentry.IngressServiceConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 37, // 47: hashicorp.consul.internal.configentry.GatewayTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - 39, // 48: hashicorp.consul.internal.configentry.IngressListener.Services:type_name -> hashicorp.consul.internal.configentry.IngressService - 36, // 49: hashicorp.consul.internal.configentry.IngressListener.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig - 40, // 50: hashicorp.consul.internal.configentry.IngressService.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayServiceTLSConfig - 41, // 51: hashicorp.consul.internal.configentry.IngressService.RequestHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers - 41, // 52: hashicorp.consul.internal.configentry.IngressService.ResponseHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers - 120, // 53: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry - 138, // 54: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 58, // 55: hashicorp.consul.internal.configentry.IngressService.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 37, // 56: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - 121, // 57: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry - 122, // 58: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry - 46, // 59: hashicorp.consul.internal.configentry.ServiceIntentions.Sources:type_name -> hashicorp.consul.internal.configentry.SourceIntention - 123, // 60: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry - 43, // 61: hashicorp.consul.internal.configentry.ServiceIntentions.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement - 44, // 62: hashicorp.consul.internal.configentry.IntentionJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.IntentionJWTProvider - 45, // 63: hashicorp.consul.internal.configentry.IntentionJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.IntentionJWTClaimVerification - 1, // 64: hashicorp.consul.internal.configentry.SourceIntention.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction - 47, // 65: hashicorp.consul.internal.configentry.SourceIntention.Permissions:type_name -> hashicorp.consul.internal.configentry.IntentionPermission - 2, // 66: hashicorp.consul.internal.configentry.SourceIntention.Type:type_name -> hashicorp.consul.internal.configentry.IntentionSourceType - 124, // 67: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry - 141, // 68: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp - 141, // 69: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp - 138, // 70: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 1, // 71: hashicorp.consul.internal.configentry.IntentionPermission.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction - 48, // 72: hashicorp.consul.internal.configentry.IntentionPermission.HTTP:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPPermission - 43, // 73: hashicorp.consul.internal.configentry.IntentionPermission.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement - 49, // 74: hashicorp.consul.internal.configentry.IntentionHTTPPermission.Header:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission - 3, // 75: hashicorp.consul.internal.configentry.ServiceDefaults.Mode:type_name -> hashicorp.consul.internal.configentry.ProxyMode - 51, // 76: hashicorp.consul.internal.configentry.ServiceDefaults.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyConfig - 52, // 77: hashicorp.consul.internal.configentry.ServiceDefaults.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig - 53, // 78: hashicorp.consul.internal.configentry.ServiceDefaults.Expose:type_name -> hashicorp.consul.internal.configentry.ExposeConfig - 55, // 79: hashicorp.consul.internal.configentry.ServiceDefaults.UpstreamConfig:type_name -> hashicorp.consul.internal.configentry.UpstreamConfiguration - 59, // 80: hashicorp.consul.internal.configentry.ServiceDefaults.Destination:type_name -> hashicorp.consul.internal.configentry.DestinationConfig - 60, // 81: hashicorp.consul.internal.configentry.ServiceDefaults.RateLimits:type_name -> hashicorp.consul.internal.configentry.RateLimits - 125, // 82: hashicorp.consul.internal.configentry.ServiceDefaults.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry - 142, // 83: hashicorp.consul.internal.configentry.ServiceDefaults.EnvoyExtensions:type_name -> hashicorp.consul.internal.common.EnvoyExtension - 4, // 84: hashicorp.consul.internal.configentry.ServiceDefaults.MutualTLSMode:type_name -> hashicorp.consul.internal.configentry.MutualTLSMode - 5, // 85: hashicorp.consul.internal.configentry.MeshGatewayConfig.Mode:type_name -> hashicorp.consul.internal.configentry.MeshGatewayMode - 54, // 86: hashicorp.consul.internal.configentry.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.configentry.ExposePath - 56, // 87: hashicorp.consul.internal.configentry.UpstreamConfiguration.Overrides:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig - 56, // 88: hashicorp.consul.internal.configentry.UpstreamConfiguration.Defaults:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig - 138, // 89: hashicorp.consul.internal.configentry.UpstreamConfig.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 57, // 90: hashicorp.consul.internal.configentry.UpstreamConfig.Limits:type_name -> hashicorp.consul.internal.configentry.UpstreamLimits - 58, // 91: hashicorp.consul.internal.configentry.UpstreamConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 52, // 92: hashicorp.consul.internal.configentry.UpstreamConfig.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig - 140, // 93: hashicorp.consul.internal.configentry.PassiveHealthCheck.Interval:type_name -> google.protobuf.Duration - 140, // 94: hashicorp.consul.internal.configentry.PassiveHealthCheck.BaseEjectionTime:type_name -> google.protobuf.Duration - 61, // 95: hashicorp.consul.internal.configentry.RateLimits.InstanceLevel:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRateLimits - 62, // 96: hashicorp.consul.internal.configentry.InstanceLevelRateLimits.Routes:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits - 126, // 97: hashicorp.consul.internal.configentry.APIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.APIGateway.MetaEntry - 66, // 98: hashicorp.consul.internal.configentry.APIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.APIGatewayListener - 64, // 99: hashicorp.consul.internal.configentry.APIGateway.Status:type_name -> hashicorp.consul.internal.configentry.Status - 65, // 100: hashicorp.consul.internal.configentry.Status.Conditions:type_name -> hashicorp.consul.internal.configentry.Condition - 72, // 101: hashicorp.consul.internal.configentry.Condition.Resource:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 141, // 102: hashicorp.consul.internal.configentry.Condition.LastTransitionTime:type_name -> google.protobuf.Timestamp - 6, // 103: hashicorp.consul.internal.configentry.APIGatewayListener.Protocol:type_name -> hashicorp.consul.internal.configentry.APIGatewayListenerProtocol - 67, // 104: hashicorp.consul.internal.configentry.APIGatewayListener.TLS:type_name -> hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration - 68, // 105: hashicorp.consul.internal.configentry.APIGatewayListener.Override:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy - 68, // 106: hashicorp.consul.internal.configentry.APIGatewayListener.Default:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy - 72, // 107: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 69, // 108: hashicorp.consul.internal.configentry.APIGatewayPolicy.JWT:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTRequirement - 70, // 109: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider - 71, // 110: hashicorp.consul.internal.configentry.APIGatewayJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification - 138, // 111: hashicorp.consul.internal.configentry.ResourceReference.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 127, // 112: hashicorp.consul.internal.configentry.BoundAPIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry - 75, // 113: hashicorp.consul.internal.configentry.BoundAPIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.BoundAPIGatewayListener - 128, // 114: hashicorp.consul.internal.configentry.BoundAPIGateway.Services:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry - 72, // 115: hashicorp.consul.internal.configentry.ListOfResourceReference.Ref:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 72, // 116: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 72, // 117: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Routes:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 129, // 118: hashicorp.consul.internal.configentry.FileSystemCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.FileSystemCertificate.MetaEntry - 130, // 119: hashicorp.consul.internal.configentry.InlineCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry - 131, // 120: hashicorp.consul.internal.configentry.HTTPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry - 72, // 121: hashicorp.consul.internal.configentry.HTTPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 79, // 122: hashicorp.consul.internal.configentry.HTTPRoute.Rules:type_name -> hashicorp.consul.internal.configentry.HTTPRouteRule - 64, // 123: hashicorp.consul.internal.configentry.HTTPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status - 84, // 124: hashicorp.consul.internal.configentry.HTTPRouteRule.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters - 80, // 125: hashicorp.consul.internal.configentry.HTTPRouteRule.Matches:type_name -> hashicorp.consul.internal.configentry.HTTPMatch - 91, // 126: hashicorp.consul.internal.configentry.HTTPRouteRule.Services:type_name -> hashicorp.consul.internal.configentry.HTTPService - 85, // 127: hashicorp.consul.internal.configentry.HTTPRouteRule.ResponseFilters:type_name -> hashicorp.consul.internal.configentry.HTTPResponseFilters - 81, // 128: hashicorp.consul.internal.configentry.HTTPMatch.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatch - 7, // 129: hashicorp.consul.internal.configentry.HTTPMatch.Method:type_name -> hashicorp.consul.internal.configentry.HTTPMatchMethod - 82, // 130: hashicorp.consul.internal.configentry.HTTPMatch.Path:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatch - 83, // 131: hashicorp.consul.internal.configentry.HTTPMatch.Query:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatch - 8, // 132: hashicorp.consul.internal.configentry.HTTPHeaderMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatchType - 9, // 133: hashicorp.consul.internal.configentry.HTTPPathMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatchType - 10, // 134: hashicorp.consul.internal.configentry.HTTPQueryMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatchType - 90, // 135: hashicorp.consul.internal.configentry.HTTPFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter - 86, // 136: hashicorp.consul.internal.configentry.HTTPFilters.URLRewrite:type_name -> hashicorp.consul.internal.configentry.URLRewrite - 87, // 137: hashicorp.consul.internal.configentry.HTTPFilters.RetryFilter:type_name -> hashicorp.consul.internal.configentry.RetryFilter - 88, // 138: hashicorp.consul.internal.configentry.HTTPFilters.TimeoutFilter:type_name -> hashicorp.consul.internal.configentry.TimeoutFilter - 89, // 139: hashicorp.consul.internal.configentry.HTTPFilters.JWT:type_name -> hashicorp.consul.internal.configentry.JWTFilter - 90, // 140: hashicorp.consul.internal.configentry.HTTPResponseFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter - 140, // 141: hashicorp.consul.internal.configentry.TimeoutFilter.RequestTimeout:type_name -> google.protobuf.Duration - 140, // 142: hashicorp.consul.internal.configentry.TimeoutFilter.IdleTimeout:type_name -> google.protobuf.Duration - 70, // 143: hashicorp.consul.internal.configentry.JWTFilter.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider - 132, // 144: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry - 133, // 145: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry - 84, // 146: hashicorp.consul.internal.configentry.HTTPService.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters - 138, // 147: hashicorp.consul.internal.configentry.HTTPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 85, // 148: hashicorp.consul.internal.configentry.HTTPService.ResponseFilters:type_name -> hashicorp.consul.internal.configentry.HTTPResponseFilters - 134, // 149: hashicorp.consul.internal.configentry.TCPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.TCPRoute.MetaEntry - 72, // 150: hashicorp.consul.internal.configentry.TCPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 93, // 151: hashicorp.consul.internal.configentry.TCPRoute.Services:type_name -> hashicorp.consul.internal.configentry.TCPService - 64, // 152: hashicorp.consul.internal.configentry.TCPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status - 138, // 153: hashicorp.consul.internal.configentry.TCPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 95, // 154: hashicorp.consul.internal.configentry.SamenessGroup.Members:type_name -> hashicorp.consul.internal.configentry.SamenessGroupMember - 135, // 155: hashicorp.consul.internal.configentry.SamenessGroup.Meta:type_name -> hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry - 138, // 156: hashicorp.consul.internal.configentry.SamenessGroup.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 97, // 157: hashicorp.consul.internal.configentry.JWTProvider.JSONWebKeySet:type_name -> hashicorp.consul.internal.configentry.JSONWebKeySet - 106, // 158: hashicorp.consul.internal.configentry.JWTProvider.Locations:type_name -> hashicorp.consul.internal.configentry.JWTLocation - 110, // 159: hashicorp.consul.internal.configentry.JWTProvider.Forwarding:type_name -> hashicorp.consul.internal.configentry.JWTForwardingConfig - 111, // 160: hashicorp.consul.internal.configentry.JWTProvider.CacheConfig:type_name -> hashicorp.consul.internal.configentry.JWTCacheConfig - 136, // 161: hashicorp.consul.internal.configentry.JWTProvider.Meta:type_name -> hashicorp.consul.internal.configentry.JWTProvider.MetaEntry - 98, // 162: hashicorp.consul.internal.configentry.JSONWebKeySet.Local:type_name -> hashicorp.consul.internal.configentry.LocalJWKS - 99, // 163: hashicorp.consul.internal.configentry.JSONWebKeySet.Remote:type_name -> hashicorp.consul.internal.configentry.RemoteJWKS - 140, // 164: hashicorp.consul.internal.configentry.RemoteJWKS.CacheDuration:type_name -> google.protobuf.Duration - 104, // 165: hashicorp.consul.internal.configentry.RemoteJWKS.RetryPolicy:type_name -> hashicorp.consul.internal.configentry.JWKSRetryPolicy - 100, // 166: hashicorp.consul.internal.configentry.RemoteJWKS.JWKSCluster:type_name -> hashicorp.consul.internal.configentry.JWKSCluster - 101, // 167: hashicorp.consul.internal.configentry.JWKSCluster.TLSCertificates:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertificate - 140, // 168: hashicorp.consul.internal.configentry.JWKSCluster.ConnectTimeout:type_name -> google.protobuf.Duration - 102, // 169: hashicorp.consul.internal.configentry.JWKSTLSCertificate.CaCertificateProviderInstance:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance - 103, // 170: hashicorp.consul.internal.configentry.JWKSTLSCertificate.TrustedCA:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA - 105, // 171: hashicorp.consul.internal.configentry.JWKSRetryPolicy.RetryPolicyBackOff:type_name -> hashicorp.consul.internal.configentry.RetryPolicyBackOff - 140, // 172: hashicorp.consul.internal.configentry.RetryPolicyBackOff.BaseInterval:type_name -> google.protobuf.Duration - 140, // 173: hashicorp.consul.internal.configentry.RetryPolicyBackOff.MaxInterval:type_name -> google.protobuf.Duration - 107, // 174: hashicorp.consul.internal.configentry.JWTLocation.Header:type_name -> hashicorp.consul.internal.configentry.JWTLocationHeader - 108, // 175: hashicorp.consul.internal.configentry.JWTLocation.QueryParam:type_name -> hashicorp.consul.internal.configentry.JWTLocationQueryParam - 109, // 176: hashicorp.consul.internal.configentry.JWTLocation.Cookie:type_name -> hashicorp.consul.internal.configentry.JWTLocationCookie - 138, // 177: hashicorp.consul.internal.configentry.ExportedServices.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 137, // 178: hashicorp.consul.internal.configentry.ExportedServices.Meta:type_name -> hashicorp.consul.internal.configentry.ExportedServices.MetaEntry - 113, // 179: hashicorp.consul.internal.configentry.ExportedServices.Services:type_name -> hashicorp.consul.internal.configentry.ExportedServicesService - 114, // 180: hashicorp.consul.internal.configentry.ExportedServicesService.Consumers:type_name -> hashicorp.consul.internal.configentry.ExportedServicesConsumer - 23, // 181: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset - 25, // 182: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover - 74, // 183: hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry.value:type_name -> hashicorp.consul.internal.configentry.ListOfResourceReference - 11, // 184: hashicorp.consul.internal.configentry.ConfigEntryService.GetResolvedExportedServices:input_type -> hashicorp.consul.internal.configentry.GetResolvedExportedServicesRequest - 12, // 185: hashicorp.consul.internal.configentry.ConfigEntryService.GetResolvedExportedServices:output_type -> hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse - 185, // [185:186] is the sub-list for method output_type - 184, // [184:185] is the sub-list for method input_type - 184, // [184:184] is the sub-list for extension type_name - 184, // [184:184] is the sub-list for extension extendee - 0, // [0:184] is the sub-list for field type_name + 142, // 4: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 143, // 5: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 18, // 6: hashicorp.consul.internal.configentry.ConfigEntry.MeshConfig:type_name -> hashicorp.consul.internal.configentry.MeshConfig + 26, // 7: hashicorp.consul.internal.configentry.ConfigEntry.ServiceResolver:type_name -> hashicorp.consul.internal.configentry.ServiceResolver + 38, // 8: hashicorp.consul.internal.configentry.ConfigEntry.IngressGateway:type_name -> hashicorp.consul.internal.configentry.IngressGateway + 46, // 9: hashicorp.consul.internal.configentry.ConfigEntry.ServiceIntentions:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions + 54, // 10: hashicorp.consul.internal.configentry.ConfigEntry.ServiceDefaults:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults + 67, // 11: hashicorp.consul.internal.configentry.ConfigEntry.APIGateway:type_name -> hashicorp.consul.internal.configentry.APIGateway + 77, // 12: hashicorp.consul.internal.configentry.ConfigEntry.BoundAPIGateway:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway + 96, // 13: hashicorp.consul.internal.configentry.ConfigEntry.TCPRoute:type_name -> hashicorp.consul.internal.configentry.TCPRoute + 82, // 14: hashicorp.consul.internal.configentry.ConfigEntry.HTTPRoute:type_name -> hashicorp.consul.internal.configentry.HTTPRoute + 81, // 15: hashicorp.consul.internal.configentry.ConfigEntry.InlineCertificate:type_name -> hashicorp.consul.internal.configentry.InlineCertificate + 98, // 16: hashicorp.consul.internal.configentry.ConfigEntry.SamenessGroup:type_name -> hashicorp.consul.internal.configentry.SamenessGroup + 100, // 17: hashicorp.consul.internal.configentry.ConfigEntry.JWTProvider:type_name -> hashicorp.consul.internal.configentry.JWTProvider + 116, // 18: hashicorp.consul.internal.configentry.ConfigEntry.ExportedServices:type_name -> hashicorp.consul.internal.configentry.ExportedServices + 80, // 19: hashicorp.consul.internal.configentry.ConfigEntry.FileSystemCertificate:type_name -> hashicorp.consul.internal.configentry.FileSystemCertificate + 19, // 20: hashicorp.consul.internal.configentry.MeshConfig.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyMeshConfig + 20, // 21: hashicorp.consul.internal.configentry.MeshConfig.TLS:type_name -> hashicorp.consul.internal.configentry.MeshTLSConfig + 22, // 22: hashicorp.consul.internal.configentry.MeshConfig.HTTP:type_name -> hashicorp.consul.internal.configentry.MeshHTTPConfig + 119, // 23: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + 24, // 24: hashicorp.consul.internal.configentry.MeshConfig.Peering:type_name -> hashicorp.consul.internal.configentry.PeeringMeshConfig + 21, // 25: hashicorp.consul.internal.configentry.MeshTLSConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + 21, // 26: hashicorp.consul.internal.configentry.MeshTLSConfig.Outgoing:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + 23, // 27: hashicorp.consul.internal.configentry.MeshHTTPConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalHTTPConfig + 25, // 28: hashicorp.consul.internal.configentry.MeshDirectionalHTTPConfig.RequestNormalization:type_name -> hashicorp.consul.internal.configentry.RequestNormalizationMeshConfig + 1, // 29: hashicorp.consul.internal.configentry.RequestNormalizationMeshConfig.PathWithEscapedSlashesAction:type_name -> hashicorp.consul.internal.configentry.PathWithEscapedSlashesAction + 2, // 30: hashicorp.consul.internal.configentry.RequestNormalizationMeshConfig.HeadersWithUnderscoresAction:type_name -> hashicorp.consul.internal.configentry.HeadersWithUnderscoresAction + 120, // 31: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + 28, // 32: hashicorp.consul.internal.configentry.ServiceResolver.Redirect:type_name -> hashicorp.consul.internal.configentry.ServiceResolverRedirect + 121, // 33: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + 144, // 34: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration + 33, // 35: hashicorp.consul.internal.configentry.ServiceResolver.LoadBalancer:type_name -> hashicorp.consul.internal.configentry.LoadBalancer + 122, // 36: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + 144, // 37: hashicorp.consul.internal.configentry.ServiceResolver.RequestTimeout:type_name -> google.protobuf.Duration + 31, // 38: hashicorp.consul.internal.configentry.ServiceResolver.PrioritizeByLocality:type_name -> hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality + 32, // 39: hashicorp.consul.internal.configentry.ServiceResolverFailover.Targets:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget + 30, // 40: hashicorp.consul.internal.configentry.ServiceResolverFailover.Policy:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy + 34, // 41: hashicorp.consul.internal.configentry.LoadBalancer.RingHashConfig:type_name -> hashicorp.consul.internal.configentry.RingHashConfig + 35, // 42: hashicorp.consul.internal.configentry.LoadBalancer.LeastRequestConfig:type_name -> hashicorp.consul.internal.configentry.LeastRequestConfig + 36, // 43: hashicorp.consul.internal.configentry.LoadBalancer.HashPolicies:type_name -> hashicorp.consul.internal.configentry.HashPolicy + 37, // 44: hashicorp.consul.internal.configentry.HashPolicy.CookieConfig:type_name -> hashicorp.consul.internal.configentry.CookieConfig + 144, // 45: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration + 40, // 46: hashicorp.consul.internal.configentry.IngressGateway.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig + 42, // 47: hashicorp.consul.internal.configentry.IngressGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.IngressListener + 123, // 48: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + 39, // 49: hashicorp.consul.internal.configentry.IngressGateway.Defaults:type_name -> hashicorp.consul.internal.configentry.IngressServiceConfig + 62, // 50: hashicorp.consul.internal.configentry.IngressServiceConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 41, // 51: hashicorp.consul.internal.configentry.GatewayTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + 43, // 52: hashicorp.consul.internal.configentry.IngressListener.Services:type_name -> hashicorp.consul.internal.configentry.IngressService + 40, // 53: hashicorp.consul.internal.configentry.IngressListener.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig + 44, // 54: hashicorp.consul.internal.configentry.IngressService.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayServiceTLSConfig + 45, // 55: hashicorp.consul.internal.configentry.IngressService.RequestHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers + 45, // 56: hashicorp.consul.internal.configentry.IngressService.ResponseHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers + 124, // 57: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry + 142, // 58: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 62, // 59: hashicorp.consul.internal.configentry.IngressService.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 41, // 60: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + 125, // 61: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + 126, // 62: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + 50, // 63: hashicorp.consul.internal.configentry.ServiceIntentions.Sources:type_name -> hashicorp.consul.internal.configentry.SourceIntention + 127, // 64: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + 47, // 65: hashicorp.consul.internal.configentry.ServiceIntentions.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement + 48, // 66: hashicorp.consul.internal.configentry.IntentionJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.IntentionJWTProvider + 49, // 67: hashicorp.consul.internal.configentry.IntentionJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.IntentionJWTClaimVerification + 3, // 68: hashicorp.consul.internal.configentry.SourceIntention.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction + 51, // 69: hashicorp.consul.internal.configentry.SourceIntention.Permissions:type_name -> hashicorp.consul.internal.configentry.IntentionPermission + 4, // 70: hashicorp.consul.internal.configentry.SourceIntention.Type:type_name -> hashicorp.consul.internal.configentry.IntentionSourceType + 128, // 71: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + 145, // 72: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp + 145, // 73: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp + 142, // 74: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 3, // 75: hashicorp.consul.internal.configentry.IntentionPermission.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction + 52, // 76: hashicorp.consul.internal.configentry.IntentionPermission.HTTP:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPPermission + 47, // 77: hashicorp.consul.internal.configentry.IntentionPermission.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement + 53, // 78: hashicorp.consul.internal.configentry.IntentionHTTPPermission.Header:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission + 5, // 79: hashicorp.consul.internal.configentry.ServiceDefaults.Mode:type_name -> hashicorp.consul.internal.configentry.ProxyMode + 55, // 80: hashicorp.consul.internal.configentry.ServiceDefaults.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyConfig + 56, // 81: hashicorp.consul.internal.configentry.ServiceDefaults.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig + 57, // 82: hashicorp.consul.internal.configentry.ServiceDefaults.Expose:type_name -> hashicorp.consul.internal.configentry.ExposeConfig + 59, // 83: hashicorp.consul.internal.configentry.ServiceDefaults.UpstreamConfig:type_name -> hashicorp.consul.internal.configentry.UpstreamConfiguration + 63, // 84: hashicorp.consul.internal.configentry.ServiceDefaults.Destination:type_name -> hashicorp.consul.internal.configentry.DestinationConfig + 64, // 85: hashicorp.consul.internal.configentry.ServiceDefaults.RateLimits:type_name -> hashicorp.consul.internal.configentry.RateLimits + 129, // 86: hashicorp.consul.internal.configentry.ServiceDefaults.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry + 146, // 87: hashicorp.consul.internal.configentry.ServiceDefaults.EnvoyExtensions:type_name -> hashicorp.consul.internal.common.EnvoyExtension + 6, // 88: hashicorp.consul.internal.configentry.ServiceDefaults.MutualTLSMode:type_name -> hashicorp.consul.internal.configentry.MutualTLSMode + 7, // 89: hashicorp.consul.internal.configentry.MeshGatewayConfig.Mode:type_name -> hashicorp.consul.internal.configentry.MeshGatewayMode + 58, // 90: hashicorp.consul.internal.configentry.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.configentry.ExposePath + 60, // 91: hashicorp.consul.internal.configentry.UpstreamConfiguration.Overrides:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig + 60, // 92: hashicorp.consul.internal.configentry.UpstreamConfiguration.Defaults:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig + 142, // 93: hashicorp.consul.internal.configentry.UpstreamConfig.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 61, // 94: hashicorp.consul.internal.configentry.UpstreamConfig.Limits:type_name -> hashicorp.consul.internal.configentry.UpstreamLimits + 62, // 95: hashicorp.consul.internal.configentry.UpstreamConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 56, // 96: hashicorp.consul.internal.configentry.UpstreamConfig.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig + 144, // 97: hashicorp.consul.internal.configentry.PassiveHealthCheck.Interval:type_name -> google.protobuf.Duration + 144, // 98: hashicorp.consul.internal.configentry.PassiveHealthCheck.BaseEjectionTime:type_name -> google.protobuf.Duration + 65, // 99: hashicorp.consul.internal.configentry.RateLimits.InstanceLevel:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRateLimits + 66, // 100: hashicorp.consul.internal.configentry.InstanceLevelRateLimits.Routes:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits + 130, // 101: hashicorp.consul.internal.configentry.APIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.APIGateway.MetaEntry + 70, // 102: hashicorp.consul.internal.configentry.APIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.APIGatewayListener + 68, // 103: hashicorp.consul.internal.configentry.APIGateway.Status:type_name -> hashicorp.consul.internal.configentry.Status + 69, // 104: hashicorp.consul.internal.configentry.Status.Conditions:type_name -> hashicorp.consul.internal.configentry.Condition + 76, // 105: hashicorp.consul.internal.configentry.Condition.Resource:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 145, // 106: hashicorp.consul.internal.configentry.Condition.LastTransitionTime:type_name -> google.protobuf.Timestamp + 8, // 107: hashicorp.consul.internal.configentry.APIGatewayListener.Protocol:type_name -> hashicorp.consul.internal.configentry.APIGatewayListenerProtocol + 71, // 108: hashicorp.consul.internal.configentry.APIGatewayListener.TLS:type_name -> hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration + 72, // 109: hashicorp.consul.internal.configentry.APIGatewayListener.Override:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy + 72, // 110: hashicorp.consul.internal.configentry.APIGatewayListener.Default:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy + 76, // 111: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 73, // 112: hashicorp.consul.internal.configentry.APIGatewayPolicy.JWT:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTRequirement + 74, // 113: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider + 75, // 114: hashicorp.consul.internal.configentry.APIGatewayJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification + 142, // 115: hashicorp.consul.internal.configentry.ResourceReference.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 131, // 116: hashicorp.consul.internal.configentry.BoundAPIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry + 79, // 117: hashicorp.consul.internal.configentry.BoundAPIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.BoundAPIGatewayListener + 132, // 118: hashicorp.consul.internal.configentry.BoundAPIGateway.Services:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry + 76, // 119: hashicorp.consul.internal.configentry.ListOfResourceReference.Ref:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 76, // 120: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 76, // 121: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Routes:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 133, // 122: hashicorp.consul.internal.configentry.FileSystemCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.FileSystemCertificate.MetaEntry + 134, // 123: hashicorp.consul.internal.configentry.InlineCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry + 135, // 124: hashicorp.consul.internal.configentry.HTTPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry + 76, // 125: hashicorp.consul.internal.configentry.HTTPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 83, // 126: hashicorp.consul.internal.configentry.HTTPRoute.Rules:type_name -> hashicorp.consul.internal.configentry.HTTPRouteRule + 68, // 127: hashicorp.consul.internal.configentry.HTTPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status + 88, // 128: hashicorp.consul.internal.configentry.HTTPRouteRule.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters + 84, // 129: hashicorp.consul.internal.configentry.HTTPRouteRule.Matches:type_name -> hashicorp.consul.internal.configentry.HTTPMatch + 95, // 130: hashicorp.consul.internal.configentry.HTTPRouteRule.Services:type_name -> hashicorp.consul.internal.configentry.HTTPService + 89, // 131: hashicorp.consul.internal.configentry.HTTPRouteRule.ResponseFilters:type_name -> hashicorp.consul.internal.configentry.HTTPResponseFilters + 85, // 132: hashicorp.consul.internal.configentry.HTTPMatch.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatch + 9, // 133: hashicorp.consul.internal.configentry.HTTPMatch.Method:type_name -> hashicorp.consul.internal.configentry.HTTPMatchMethod + 86, // 134: hashicorp.consul.internal.configentry.HTTPMatch.Path:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatch + 87, // 135: hashicorp.consul.internal.configentry.HTTPMatch.Query:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatch + 10, // 136: hashicorp.consul.internal.configentry.HTTPHeaderMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatchType + 11, // 137: hashicorp.consul.internal.configentry.HTTPPathMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatchType + 12, // 138: hashicorp.consul.internal.configentry.HTTPQueryMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatchType + 94, // 139: hashicorp.consul.internal.configentry.HTTPFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter + 90, // 140: hashicorp.consul.internal.configentry.HTTPFilters.URLRewrite:type_name -> hashicorp.consul.internal.configentry.URLRewrite + 91, // 141: hashicorp.consul.internal.configentry.HTTPFilters.RetryFilter:type_name -> hashicorp.consul.internal.configentry.RetryFilter + 92, // 142: hashicorp.consul.internal.configentry.HTTPFilters.TimeoutFilter:type_name -> hashicorp.consul.internal.configentry.TimeoutFilter + 93, // 143: hashicorp.consul.internal.configentry.HTTPFilters.JWT:type_name -> hashicorp.consul.internal.configentry.JWTFilter + 94, // 144: hashicorp.consul.internal.configentry.HTTPResponseFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter + 144, // 145: hashicorp.consul.internal.configentry.TimeoutFilter.RequestTimeout:type_name -> google.protobuf.Duration + 144, // 146: hashicorp.consul.internal.configentry.TimeoutFilter.IdleTimeout:type_name -> google.protobuf.Duration + 74, // 147: hashicorp.consul.internal.configentry.JWTFilter.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider + 136, // 148: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry + 137, // 149: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry + 88, // 150: hashicorp.consul.internal.configentry.HTTPService.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters + 142, // 151: hashicorp.consul.internal.configentry.HTTPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 89, // 152: hashicorp.consul.internal.configentry.HTTPService.ResponseFilters:type_name -> hashicorp.consul.internal.configentry.HTTPResponseFilters + 138, // 153: hashicorp.consul.internal.configentry.TCPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.TCPRoute.MetaEntry + 76, // 154: hashicorp.consul.internal.configentry.TCPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 97, // 155: hashicorp.consul.internal.configentry.TCPRoute.Services:type_name -> hashicorp.consul.internal.configentry.TCPService + 68, // 156: hashicorp.consul.internal.configentry.TCPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status + 142, // 157: hashicorp.consul.internal.configentry.TCPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 99, // 158: hashicorp.consul.internal.configentry.SamenessGroup.Members:type_name -> hashicorp.consul.internal.configentry.SamenessGroupMember + 139, // 159: hashicorp.consul.internal.configentry.SamenessGroup.Meta:type_name -> hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry + 142, // 160: hashicorp.consul.internal.configentry.SamenessGroup.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 101, // 161: hashicorp.consul.internal.configentry.JWTProvider.JSONWebKeySet:type_name -> hashicorp.consul.internal.configentry.JSONWebKeySet + 110, // 162: hashicorp.consul.internal.configentry.JWTProvider.Locations:type_name -> hashicorp.consul.internal.configentry.JWTLocation + 114, // 163: hashicorp.consul.internal.configentry.JWTProvider.Forwarding:type_name -> hashicorp.consul.internal.configentry.JWTForwardingConfig + 115, // 164: hashicorp.consul.internal.configentry.JWTProvider.CacheConfig:type_name -> hashicorp.consul.internal.configentry.JWTCacheConfig + 140, // 165: hashicorp.consul.internal.configentry.JWTProvider.Meta:type_name -> hashicorp.consul.internal.configentry.JWTProvider.MetaEntry + 102, // 166: hashicorp.consul.internal.configentry.JSONWebKeySet.Local:type_name -> hashicorp.consul.internal.configentry.LocalJWKS + 103, // 167: hashicorp.consul.internal.configentry.JSONWebKeySet.Remote:type_name -> hashicorp.consul.internal.configentry.RemoteJWKS + 144, // 168: hashicorp.consul.internal.configentry.RemoteJWKS.CacheDuration:type_name -> google.protobuf.Duration + 108, // 169: hashicorp.consul.internal.configentry.RemoteJWKS.RetryPolicy:type_name -> hashicorp.consul.internal.configentry.JWKSRetryPolicy + 104, // 170: hashicorp.consul.internal.configentry.RemoteJWKS.JWKSCluster:type_name -> hashicorp.consul.internal.configentry.JWKSCluster + 105, // 171: hashicorp.consul.internal.configentry.JWKSCluster.TLSCertificates:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertificate + 144, // 172: hashicorp.consul.internal.configentry.JWKSCluster.ConnectTimeout:type_name -> google.protobuf.Duration + 106, // 173: hashicorp.consul.internal.configentry.JWKSTLSCertificate.CaCertificateProviderInstance:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance + 107, // 174: hashicorp.consul.internal.configentry.JWKSTLSCertificate.TrustedCA:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA + 109, // 175: hashicorp.consul.internal.configentry.JWKSRetryPolicy.RetryPolicyBackOff:type_name -> hashicorp.consul.internal.configentry.RetryPolicyBackOff + 144, // 176: hashicorp.consul.internal.configentry.RetryPolicyBackOff.BaseInterval:type_name -> google.protobuf.Duration + 144, // 177: hashicorp.consul.internal.configentry.RetryPolicyBackOff.MaxInterval:type_name -> google.protobuf.Duration + 111, // 178: hashicorp.consul.internal.configentry.JWTLocation.Header:type_name -> hashicorp.consul.internal.configentry.JWTLocationHeader + 112, // 179: hashicorp.consul.internal.configentry.JWTLocation.QueryParam:type_name -> hashicorp.consul.internal.configentry.JWTLocationQueryParam + 113, // 180: hashicorp.consul.internal.configentry.JWTLocation.Cookie:type_name -> hashicorp.consul.internal.configentry.JWTLocationCookie + 142, // 181: hashicorp.consul.internal.configentry.ExportedServices.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 141, // 182: hashicorp.consul.internal.configentry.ExportedServices.Meta:type_name -> hashicorp.consul.internal.configentry.ExportedServices.MetaEntry + 117, // 183: hashicorp.consul.internal.configentry.ExportedServices.Services:type_name -> hashicorp.consul.internal.configentry.ExportedServicesService + 118, // 184: hashicorp.consul.internal.configentry.ExportedServicesService.Consumers:type_name -> hashicorp.consul.internal.configentry.ExportedServicesConsumer + 27, // 185: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset + 29, // 186: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover + 78, // 187: hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry.value:type_name -> hashicorp.consul.internal.configentry.ListOfResourceReference + 13, // 188: hashicorp.consul.internal.configentry.ConfigEntryService.GetResolvedExportedServices:input_type -> hashicorp.consul.internal.configentry.GetResolvedExportedServicesRequest + 14, // 189: hashicorp.consul.internal.configentry.ConfigEntryService.GetResolvedExportedServices:output_type -> hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse + 189, // [189:190] is the sub-list for method output_type + 188, // [188:189] is the sub-list for method input_type + 188, // [188:188] is the sub-list for extension type_name + 188, // [188:188] is the sub-list for extension extendee + 0, // [0:188] is the sub-list for field type_name } func init() { file_private_pbconfigentry_config_entry_proto_init() } @@ -10661,7 +10999,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeeringMeshConfig); i { + switch v := v.(*MeshDirectionalHTTPConfig); i { case 0: return &v.state case 1: @@ -10673,7 +11011,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceResolver); i { + switch v := v.(*PeeringMeshConfig); i { case 0: return &v.state case 1: @@ -10685,7 +11023,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceResolverSubset); i { + switch v := v.(*RequestNormalizationMeshConfig); i { case 0: return &v.state case 1: @@ -10697,7 +11035,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceResolverRedirect); i { + switch v := v.(*ServiceResolver); i { case 0: return &v.state case 1: @@ -10709,7 +11047,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceResolverFailover); i { + switch v := v.(*ServiceResolverSubset); i { case 0: return &v.state case 1: @@ -10721,7 +11059,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceResolverFailoverPolicy); i { + switch v := v.(*ServiceResolverRedirect); i { case 0: return &v.state case 1: @@ -10733,7 +11071,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceResolverPrioritizeByLocality); i { + switch v := v.(*ServiceResolverFailover); i { case 0: return &v.state case 1: @@ -10745,7 +11083,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceResolverFailoverTarget); i { + switch v := v.(*ServiceResolverFailoverPolicy); i { case 0: return &v.state case 1: @@ -10757,7 +11095,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoadBalancer); i { + switch v := v.(*ServiceResolverPrioritizeByLocality); i { case 0: return &v.state case 1: @@ -10769,7 +11107,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RingHashConfig); i { + switch v := v.(*ServiceResolverFailoverTarget); i { case 0: return &v.state case 1: @@ -10781,7 +11119,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeastRequestConfig); i { + switch v := v.(*LoadBalancer); i { case 0: return &v.state case 1: @@ -10793,7 +11131,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HashPolicy); i { + switch v := v.(*RingHashConfig); i { case 0: return &v.state case 1: @@ -10805,7 +11143,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CookieConfig); i { + switch v := v.(*LeastRequestConfig); i { case 0: return &v.state case 1: @@ -10817,7 +11155,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IngressGateway); i { + switch v := v.(*HashPolicy); i { case 0: return &v.state case 1: @@ -10829,7 +11167,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IngressServiceConfig); i { + switch v := v.(*CookieConfig); i { case 0: return &v.state case 1: @@ -10841,7 +11179,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GatewayTLSConfig); i { + switch v := v.(*IngressGateway); i { case 0: return &v.state case 1: @@ -10853,7 +11191,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GatewayTLSSDSConfig); i { + switch v := v.(*IngressServiceConfig); i { case 0: return &v.state case 1: @@ -10865,7 +11203,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IngressListener); i { + switch v := v.(*GatewayTLSConfig); i { case 0: return &v.state case 1: @@ -10877,7 +11215,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IngressService); i { + switch v := v.(*GatewayTLSSDSConfig); i { case 0: return &v.state case 1: @@ -10889,7 +11227,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GatewayServiceTLSConfig); i { + switch v := v.(*IngressListener); i { case 0: return &v.state case 1: @@ -10901,7 +11239,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeaderModifiers); i { + switch v := v.(*IngressService); i { case 0: return &v.state case 1: @@ -10913,7 +11251,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceIntentions); i { + switch v := v.(*GatewayServiceTLSConfig); i { case 0: return &v.state case 1: @@ -10925,7 +11263,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntentionJWTRequirement); i { + switch v := v.(*HTTPHeaderModifiers); i { case 0: return &v.state case 1: @@ -10937,7 +11275,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntentionJWTProvider); i { + switch v := v.(*ServiceIntentions); i { case 0: return &v.state case 1: @@ -10949,7 +11287,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntentionJWTClaimVerification); i { + switch v := v.(*IntentionJWTRequirement); i { case 0: return &v.state case 1: @@ -10961,7 +11299,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SourceIntention); i { + switch v := v.(*IntentionJWTProvider); i { case 0: return &v.state case 1: @@ -10973,7 +11311,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntentionPermission); i { + switch v := v.(*IntentionJWTClaimVerification); i { case 0: return &v.state case 1: @@ -10985,7 +11323,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntentionHTTPPermission); i { + switch v := v.(*SourceIntention); i { case 0: return &v.state case 1: @@ -10997,7 +11335,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntentionHTTPHeaderPermission); i { + switch v := v.(*IntentionPermission); i { case 0: return &v.state case 1: @@ -11009,7 +11347,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceDefaults); i { + switch v := v.(*IntentionHTTPPermission); i { case 0: return &v.state case 1: @@ -11021,7 +11359,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransparentProxyConfig); i { + switch v := v.(*IntentionHTTPHeaderPermission); i { case 0: return &v.state case 1: @@ -11033,7 +11371,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MeshGatewayConfig); i { + switch v := v.(*ServiceDefaults); i { case 0: return &v.state case 1: @@ -11045,7 +11383,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExposeConfig); i { + switch v := v.(*TransparentProxyConfig); i { case 0: return &v.state case 1: @@ -11057,7 +11395,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExposePath); i { + switch v := v.(*MeshGatewayConfig); i { case 0: return &v.state case 1: @@ -11069,7 +11407,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamConfiguration); i { + switch v := v.(*ExposeConfig); i { case 0: return &v.state case 1: @@ -11081,7 +11419,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamConfig); i { + switch v := v.(*ExposePath); i { case 0: return &v.state case 1: @@ -11093,7 +11431,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamLimits); i { + switch v := v.(*UpstreamConfiguration); i { case 0: return &v.state case 1: @@ -11105,7 +11443,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PassiveHealthCheck); i { + switch v := v.(*UpstreamConfig); i { case 0: return &v.state case 1: @@ -11117,7 +11455,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationConfig); i { + switch v := v.(*UpstreamLimits); i { case 0: return &v.state case 1: @@ -11129,7 +11467,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RateLimits); i { + switch v := v.(*PassiveHealthCheck); i { case 0: return &v.state case 1: @@ -11141,7 +11479,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InstanceLevelRateLimits); i { + switch v := v.(*DestinationConfig); i { case 0: return &v.state case 1: @@ -11153,7 +11491,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InstanceLevelRouteRateLimits); i { + switch v := v.(*RateLimits); i { case 0: return &v.state case 1: @@ -11165,7 +11503,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGateway); i { + switch v := v.(*InstanceLevelRateLimits); i { case 0: return &v.state case 1: @@ -11177,7 +11515,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Status); i { + switch v := v.(*InstanceLevelRouteRateLimits); i { case 0: return &v.state case 1: @@ -11189,7 +11527,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Condition); i { + switch v := v.(*APIGateway); i { case 0: return &v.state case 1: @@ -11201,7 +11539,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayListener); i { + switch v := v.(*Status); i { case 0: return &v.state case 1: @@ -11213,7 +11551,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayTLSConfiguration); i { + switch v := v.(*Condition); i { case 0: return &v.state case 1: @@ -11225,7 +11563,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayPolicy); i { + switch v := v.(*APIGatewayListener); i { case 0: return &v.state case 1: @@ -11237,7 +11575,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayJWTRequirement); i { + switch v := v.(*APIGatewayTLSConfiguration); i { case 0: return &v.state case 1: @@ -11249,7 +11587,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayJWTProvider); i { + switch v := v.(*APIGatewayPolicy); i { case 0: return &v.state case 1: @@ -11261,7 +11599,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*APIGatewayJWTClaimVerification); i { + switch v := v.(*APIGatewayJWTRequirement); i { case 0: return &v.state case 1: @@ -11273,7 +11611,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResourceReference); i { + switch v := v.(*APIGatewayJWTProvider); i { case 0: return &v.state case 1: @@ -11285,7 +11623,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BoundAPIGateway); i { + switch v := v.(*APIGatewayJWTClaimVerification); i { case 0: return &v.state case 1: @@ -11297,7 +11635,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListOfResourceReference); i { + switch v := v.(*ResourceReference); i { case 0: return &v.state case 1: @@ -11309,7 +11647,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BoundAPIGatewayListener); i { + switch v := v.(*BoundAPIGateway); i { case 0: return &v.state case 1: @@ -11321,7 +11659,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileSystemCertificate); i { + switch v := v.(*ListOfResourceReference); i { case 0: return &v.state case 1: @@ -11333,7 +11671,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InlineCertificate); i { + switch v := v.(*BoundAPIGatewayListener); i { case 0: return &v.state case 1: @@ -11345,7 +11683,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRoute); i { + switch v := v.(*FileSystemCertificate); i { case 0: return &v.state case 1: @@ -11357,7 +11695,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteRule); i { + switch v := v.(*InlineCertificate); i { case 0: return &v.state case 1: @@ -11369,7 +11707,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPMatch); i { + switch v := v.(*HTTPRoute); i { case 0: return &v.state case 1: @@ -11381,7 +11719,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeaderMatch); i { + switch v := v.(*HTTPRouteRule); i { case 0: return &v.state case 1: @@ -11393,7 +11731,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPPathMatch); i { + switch v := v.(*HTTPMatch); i { case 0: return &v.state case 1: @@ -11405,7 +11743,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPQueryMatch); i { + switch v := v.(*HTTPHeaderMatch); i { case 0: return &v.state case 1: @@ -11417,7 +11755,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPFilters); i { + switch v := v.(*HTTPPathMatch); i { case 0: return &v.state case 1: @@ -11429,7 +11767,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPResponseFilters); i { + switch v := v.(*HTTPQueryMatch); i { case 0: return &v.state case 1: @@ -11441,7 +11779,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*URLRewrite); i { + switch v := v.(*HTTPFilters); i { case 0: return &v.state case 1: @@ -11453,7 +11791,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RetryFilter); i { + switch v := v.(*HTTPResponseFilters); i { case 0: return &v.state case 1: @@ -11465,7 +11803,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TimeoutFilter); i { + switch v := v.(*URLRewrite); i { case 0: return &v.state case 1: @@ -11477,7 +11815,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTFilter); i { + switch v := v.(*RetryFilter); i { case 0: return &v.state case 1: @@ -11489,7 +11827,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeaderFilter); i { + switch v := v.(*TimeoutFilter); i { case 0: return &v.state case 1: @@ -11501,7 +11839,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPService); i { + switch v := v.(*JWTFilter); i { case 0: return &v.state case 1: @@ -11513,7 +11851,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPRoute); i { + switch v := v.(*HTTPHeaderFilter); i { case 0: return &v.state case 1: @@ -11525,7 +11863,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPService); i { + switch v := v.(*HTTPService); i { case 0: return &v.state case 1: @@ -11537,7 +11875,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SamenessGroup); i { + switch v := v.(*TCPRoute); i { case 0: return &v.state case 1: @@ -11549,7 +11887,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SamenessGroupMember); i { + switch v := v.(*TCPService); i { case 0: return &v.state case 1: @@ -11561,7 +11899,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTProvider); i { + switch v := v.(*SamenessGroup); i { case 0: return &v.state case 1: @@ -11573,7 +11911,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JSONWebKeySet); i { + switch v := v.(*SamenessGroupMember); i { case 0: return &v.state case 1: @@ -11585,7 +11923,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LocalJWKS); i { + switch v := v.(*JWTProvider); i { case 0: return &v.state case 1: @@ -11597,7 +11935,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoteJWKS); i { + switch v := v.(*JSONWebKeySet); i { case 0: return &v.state case 1: @@ -11609,7 +11947,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWKSCluster); i { + switch v := v.(*LocalJWKS); i { case 0: return &v.state case 1: @@ -11621,7 +11959,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWKSTLSCertificate); i { + switch v := v.(*RemoteJWKS); i { case 0: return &v.state case 1: @@ -11633,7 +11971,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWKSTLSCertProviderInstance); i { + switch v := v.(*JWKSCluster); i { case 0: return &v.state case 1: @@ -11645,7 +11983,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWKSTLSCertTrustedCA); i { + switch v := v.(*JWKSTLSCertificate); i { case 0: return &v.state case 1: @@ -11657,7 +11995,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWKSRetryPolicy); i { + switch v := v.(*JWKSTLSCertProviderInstance); i { case 0: return &v.state case 1: @@ -11669,7 +12007,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RetryPolicyBackOff); i { + switch v := v.(*JWKSTLSCertTrustedCA); i { case 0: return &v.state case 1: @@ -11681,7 +12019,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[95].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTLocation); i { + switch v := v.(*JWKSRetryPolicy); i { case 0: return &v.state case 1: @@ -11693,7 +12031,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[96].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTLocationHeader); i { + switch v := v.(*RetryPolicyBackOff); i { case 0: return &v.state case 1: @@ -11705,7 +12043,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[97].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTLocationQueryParam); i { + switch v := v.(*JWTLocation); i { case 0: return &v.state case 1: @@ -11717,7 +12055,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[98].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTLocationCookie); i { + switch v := v.(*JWTLocationHeader); i { case 0: return &v.state case 1: @@ -11729,7 +12067,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[99].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTForwardingConfig); i { + switch v := v.(*JWTLocationQueryParam); i { case 0: return &v.state case 1: @@ -11741,7 +12079,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[100].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JWTCacheConfig); i { + switch v := v.(*JWTLocationCookie); i { case 0: return &v.state case 1: @@ -11753,7 +12091,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[101].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExportedServices); i { + switch v := v.(*JWTForwardingConfig); i { case 0: return &v.state case 1: @@ -11765,7 +12103,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[102].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExportedServicesService); i { + switch v := v.(*JWTCacheConfig); i { case 0: return &v.state case 1: @@ -11777,6 +12115,30 @@ func file_private_pbconfigentry_config_entry_proto_init() { } } file_private_pbconfigentry_config_entry_proto_msgTypes[103].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExportedServices); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[104].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExportedServicesService); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[105].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExportedServicesConsumer); i { case 0: return &v.state @@ -11810,8 +12172,8 @@ func file_private_pbconfigentry_config_entry_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_private_pbconfigentry_config_entry_proto_rawDesc, - NumEnums: 11, - NumMessages: 127, + NumEnums: 13, + NumMessages: 129, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/private/pbconfigentry/config_entry.proto b/proto/private/pbconfigentry/config_entry.proto index 00350fb9430a..39e37909b992 100644 --- a/proto/private/pbconfigentry/config_entry.proto +++ b/proto/private/pbconfigentry/config_entry.proto @@ -139,6 +139,16 @@ message MeshDirectionalTLSConfig { // name=Structs message MeshHTTPConfig { bool SanitizeXForwardedClientCert = 1; + MeshDirectionalHTTPConfig Incoming = 2; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.MeshDirectionalHTTPConfig +// output=config_entry.gen.go +// name=Structs +message MeshDirectionalHTTPConfig { + RequestNormalizationMeshConfig RequestNormalization = 1; } // mog annotation: @@ -150,6 +160,34 @@ message PeeringMeshConfig { bool PeerThroughMeshGateways = 1; } +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.RequestNormalizationMeshConfig +// output=config_entry.gen.go +// name=Structs +message RequestNormalizationMeshConfig { + bool InsecureDisablePathNormalization = 1; + bool MergeSlashes = 2; + // mog: func-to=pathWithEscapedSlashesActionToStructs func-from=pathWithEscapedSlashesActionFromStructs + PathWithEscapedSlashesAction PathWithEscapedSlashesAction = 3; + // mog: func-to=headersWithUnderscoresActionToStructs func-from=headersWithUnderscoresActionFromStructs + HeadersWithUnderscoresAction HeadersWithUnderscoresAction = 4; +} + +enum PathWithEscapedSlashesAction { + PathWithEscapedSlashesActionDefault = 0; + PathWithEscapedSlashesActionKeep = 1; + PathWithEscapedSlashesActionReject = 2; + PathWithEscapedSlashesActionUnescapeAndRedirect = 3; + PathWithEscapedSlashesActionUnescapeAndForward = 4; +} + +enum HeadersWithUnderscoresAction { + HeadersWithUnderscoresActionAllow = 0; + HeadersWithUnderscoresActionRejectRequest = 1; + HeadersWithUnderscoresActionDropHeader = 2; +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.ServiceResolverConfigEntry @@ -521,6 +559,8 @@ message IntentionHTTPHeaderPermission { string Suffix = 5; string Regex = 6; bool Invert = 7; + string Contains = 8; + bool IgnoreCase = 9; } // mog annotation: diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/acl.hcl b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/acl.hcl new file mode 100644 index 000000000000..22aeaa7c11ae --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/acl.hcl @@ -0,0 +1,5 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +// Use default-allow policy so that we can test specific deny rules +default_intention_policy = "allow" diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/capture.sh b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/capture.sh new file mode 100644 index 000000000000..d588be9381ea --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/capture.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + + +snapshot_envoy_admin localhost:19000 s1 primary || true +snapshot_envoy_admin localhost:19001 s2 || true diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/setup.sh b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/setup.sh new file mode 100644 index 000000000000..fcd422ece08e --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/setup.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + + +set -euo pipefail + +upsert_config_entry primary ' +kind = "service-defaults" +name = "s2" +protocol = "http" +' + +upsert_config_entry primary ' +kind = "mesh" +http { + incoming { + request_normalization { + insecure_disable_path_normalization = true + merge_slashes = false // explicitly set to the default for clarity + path_with_escaped_slashes_action = "" // explicitly set to the default for clarity + headers_with_underscores_action = "" // explicitly set to the default for clarity + } + } +} +' + +upsert_config_entry primary ' +kind = "service-intentions" +name = "s2" +sources { + name = "s1" + permissions = [ + // paths + { + action = "deny" + http { + path_exact = "/value/supersecret" + } + }, + // headers + { + action = "deny" + http { + header = [{ + name = "x-check" + contains = "bad" + ignore_case = true + }] + } + }, + { + action = "deny" + http { + header = [{ + name = "x-check" + exact = "exactbad" + ignore_case = true + }] + } + }, + { + action = "deny" + http { + header = [{ + name = "x-check" + prefix = "prebad-" + ignore_case = true + }] + } + }, + { + action = "deny" + http { + header = [{ + name = "x-check" + suffix = "-sufbad" + ignore_case = true + }] + } + }, + // redundant with above case, but included for real-world example + // and to cover values containing ".". + { + action = "deny" + http { + header = [{ + name = "Host" + suffix = "bad.com" + ignore_case = true + }] + } + } + ] +} +' + +register_services primary + +gen_envoy_bootstrap s1 19000 +gen_envoy_bootstrap s2 19001 diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/vars.sh b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/vars.sh new file mode 100644 index 000000000000..9f9c9bdf0ee8 --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/vars.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +# Allow for non-normalized path testing by using alternative container. +export SERVICE_CONTAINER="echo" diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/verify.bats b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/verify.bats new file mode 100644 index 000000000000..9abf19275ec5 --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization-disabled/verify.bats @@ -0,0 +1,99 @@ +#!/usr/bin/env bats + +load helpers + +@test "s1 proxy admin is up on :19000" { + retry_default curl -f -s localhost:19000/stats -o /dev/null +} + +@test "s2 proxy admin is up on :19001" { + retry_default curl -f -s localhost:19001/stats -o /dev/null +} + +@test "s1 proxy listener should be up and have right cert" { + assert_proxy_presents_cert_uri localhost:21000 s1 +} + +@test "s2 proxy listener should be up and have right cert" { + assert_proxy_presents_cert_uri localhost:21001 s2 +} + +@test "s2 proxies should be healthy" { + assert_service_has_healthy_instances s2 1 +} + +@test "s1 upstream should have healthy endpoints for s2" { + assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary HEALTHY 1 +} + +@test "s2 should have http rbac rules loaded from xDS" { + retry_default assert_envoy_http_rbac_policy_count localhost:19001 1 +} + +# The following tests exercise the same cases in "case-l7-intentions-request-normalization" +# but with all normalization disabled, including default path normalization. Note that +# disabling normalization is not recommended in production environments unless specifically +# required. + +@test "test allowed path" { + retry_default must_pass_http_request GET localhost:5000/foo + retry_default must_pass_http_request GET localhost:5000/value/foo + retry_default must_pass_http_request GET localhost:5000/foo/supersecret +} + +@test "test disallowed path" { + retry_default must_fail_http_request 403 GET 'localhost:5000/value/supersecret' + retry_default must_fail_http_request 403 GET 'localhost:5000/value/supersecret#foo' + retry_default must_fail_http_request 403 GET 'localhost:5000/value/supersecret?' +} + +@test "test ignored disallowed path with repeat slashes" { + retry_default must_pass_http_request GET 'localhost:5000/value//supersecret' + get_echo_request_path | grep -Fx '/value//supersecret' + retry_default must_pass_http_request GET 'localhost:5000/value///supersecret' + get_echo_request_path | grep -Fx '/value///supersecret' +} + +@test "test ignored disallowed path with escaped characters" { + # escaped '/' (HTTP reserved) + retry_default must_pass_http_request GET 'localhost:5000/value%2Fsupersecret' + get_echo_request_path | grep -Fx '/value%2Fsupersecret' + # escaped 'v' (not HTTP reserved) + retry_default must_pass_http_request GET 'localhost:5000/value/%73upersecret' + get_echo_request_path | grep -Fx '/value/%73upersecret' +} + +@test "test ignored disallowed path with backward slashes" { + # URLs must be quoted due to backslashes, otherwise shell erases them + retry_default must_pass_http_request GET 'localhost:5000/value\supersecret' + get_echo_request_path | grep -Fx '/value\supersecret' + retry_default must_pass_http_request GET 'localhost:5000/value\\supersecret' + get_echo_request_path | grep -Fx '/value\\supersecret' + retry_default must_pass_http_request GET 'localhost:5000/value\/supersecret' + get_echo_request_path | grep -Fx '/value\/supersecret' + retry_default must_pass_http_request GET 'localhost:5000/value/\/supersecret' + get_echo_request_path | grep -Fx '/value/\/supersecret' +} + +@test "test ignored underscore in header key" { + retry_default must_pass_http_request GET localhost:5000/foo x_poison:anything + get_echo_request_header_value "x_poison" | grep -Fx 'anything' + retry_default must_pass_http_request GET localhost:5000/foo x_check:bad + get_echo_request_header_value "x_check" | grep -Fx 'bad' + retry_default must_pass_http_request GET localhost:5000/foo x_check:good-sufbad + get_echo_request_header_value "x_check" | grep -Fx 'good-sufbad' + retry_default must_pass_http_request GET localhost:5000/foo x_check:prebad-good + get_echo_request_header_value "x_check" | grep -Fx 'prebad-good' +} + +# Header contains and ignoreCase are not expected to change behavior with normalization +# disabled, so those cases from "case-l7-intentions-request-normalization" are omitted here. + + +# @test "s1 upstream should NOT be able to connect to s2" { +# run retry_default must_fail_tcp_connection localhost:5000 + +# echo "OUTPUT $output" + +# [ "$status" == "0" ] +# } diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization/acl.hcl b/test/integration/connect/envoy/case-l7-intentions-request-normalization/acl.hcl new file mode 100644 index 000000000000..22aeaa7c11ae --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization/acl.hcl @@ -0,0 +1,5 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +// Use default-allow policy so that we can test specific deny rules +default_intention_policy = "allow" diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization/capture.sh b/test/integration/connect/envoy/case-l7-intentions-request-normalization/capture.sh new file mode 100644 index 000000000000..d588be9381ea --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization/capture.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + + +snapshot_envoy_admin localhost:19000 s1 primary || true +snapshot_envoy_admin localhost:19001 s2 || true diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization/setup.sh b/test/integration/connect/envoy/case-l7-intentions-request-normalization/setup.sh new file mode 100644 index 000000000000..22e478b7408d --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization/setup.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + + +set -euo pipefail + +upsert_config_entry primary ' +kind = "service-defaults" +name = "s2" +protocol = "http" +' + +upsert_config_entry primary ' +kind = "mesh" +http { + incoming { + request_normalization { + insecure_disable_path_normalization = false // explicitly set to the default for clarity + merge_slashes = true + path_with_escaped_slashes_action = "UNESCAPE_AND_FORWARD" + headers_with_underscores_action = "REJECT_REQUEST" + } + } +} +' + +upsert_config_entry primary ' +kind = "service-intentions" +name = "s2" +sources { + name = "s1" + permissions = [ + // paths + { + action = "deny" + http { + path_exact = "/value/supersecret" + } + }, + // headers + { + action = "deny" + http { + header = [{ + name = "x-check" + contains = "bad" + ignore_case = true + }] + } + }, + { + action = "deny" + http { + header = [{ + name = "x-check" + exact = "exactbad" + ignore_case = true + }] + } + }, + { + action = "deny" + http { + header = [{ + name = "x-check" + prefix = "prebad-" + ignore_case = true + }] + } + }, + { + action = "deny" + http { + header = [{ + name = "x-check" + suffix = "-sufbad" + ignore_case = true + }] + } + }, + // redundant with above case, but included for real-world example + // and to cover values containing ".". + { + action = "deny" + http { + header = [{ + name = "Host" + suffix = "bad.com" + ignore_case = true + }] + } + } + ] +} +' + +register_services primary + +gen_envoy_bootstrap s1 19000 +gen_envoy_bootstrap s2 19001 diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization/vars.sh b/test/integration/connect/envoy/case-l7-intentions-request-normalization/vars.sh new file mode 100644 index 000000000000..9f9c9bdf0ee8 --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization/vars.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +# Allow for non-normalized path testing by using alternative container. +export SERVICE_CONTAINER="echo" diff --git a/test/integration/connect/envoy/case-l7-intentions-request-normalization/verify.bats b/test/integration/connect/envoy/case-l7-intentions-request-normalization/verify.bats new file mode 100644 index 000000000000..91ce3f307021 --- /dev/null +++ b/test/integration/connect/envoy/case-l7-intentions-request-normalization/verify.bats @@ -0,0 +1,129 @@ +#!/usr/bin/env bats + +load helpers + +@test "s1 proxy admin is up on :19000" { + retry_default curl -f -s localhost:19000/stats -o /dev/null +} + +@test "s2 proxy admin is up on :19001" { + retry_default curl -f -s localhost:19001/stats -o /dev/null +} + +@test "s1 proxy listener should be up and have right cert" { + assert_proxy_presents_cert_uri localhost:21000 s1 +} + +@test "s2 proxy listener should be up and have right cert" { + assert_proxy_presents_cert_uri localhost:21001 s2 +} + +@test "s2 proxies should be healthy" { + assert_service_has_healthy_instances s2 1 +} + +@test "s1 upstream should have healthy endpoints for s2" { + assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary HEALTHY 1 +} + +@test "s2 should have http rbac rules loaded from xDS" { + retry_default assert_envoy_http_rbac_policy_count localhost:19001 1 +} + +# The following tests assert one of two things: that the request was +# rejected by L7 intentions as expected due to normalization, or that the +# request was allowed, and the request received by the upstream matched the +# expected normalized form. + +@test "test allowed path" { + retry_default must_pass_http_request GET localhost:5000/foo + retry_default must_pass_http_request GET localhost:5000/value/foo + retry_default must_pass_http_request GET localhost:5000/foo/supersecret +} + +@test "test disallowed path" { + retry_default must_fail_http_request 403 GET 'localhost:5000/value/supersecret' + retry_default must_fail_http_request 403 GET 'localhost:5000/value/supersecret#foo' + retry_default must_fail_http_request 403 GET 'localhost:5000/value/supersecret?' +} + +@test "test disallowed path with repeat slashes" { + retry_default must_fail_http_request 403 GET 'localhost:5000/value//supersecret' + retry_default must_fail_http_request 403 GET 'localhost:5000/value///supersecret' +} + +@test "test path with repeat slashes normalized" { + # After each request, verify that the request path observed by fortio matches the expected normalized path. + retry_default must_pass_http_request GET 'localhost:5000/value//foo' + get_echo_request_path | grep -Fx '/value/foo' + retry_default must_pass_http_request GET 'localhost:5000/value///foo' + get_echo_request_path | grep -Fx '/value/foo' +} + +@test "test disallowed path with escaped characters" { + # escaped '/' (HTTP reserved) + retry_default must_fail_http_request 403 GET 'localhost:5000/value%2Fsupersecret' + # escaped 'v' (not HTTP reserved) + retry_default must_fail_http_request 403 GET 'localhost:5000/value/%73upersecret' +} + +@test "test path with escaped characters normalized" { + # escaped '/' (HTTP reserved) + retry_default must_pass_http_request GET 'localhost:5000/value%2Ffoo' + get_echo_request_path | grep -Fx '/value/foo' + # escaped 'v' (not HTTP reserved) + retry_default must_pass_http_request GET 'localhost:5000/value/%66oo' + get_echo_request_path | grep -Fx '/value/foo' +} + +@test "test disallowed path with backward slashes" { + # URLs must be quoted due to backslashes, otherwise shell erases them + retry_default must_fail_http_request 403 GET 'localhost:5000/value\supersecret' + retry_default must_fail_http_request 403 GET 'localhost:5000/value\\supersecret' + retry_default must_fail_http_request 403 GET 'localhost:5000/value\/supersecret' + retry_default must_fail_http_request 403 GET 'localhost:5000/value/\/supersecret' +} + +@test "test path with backward slashes normalized" { + retry_default must_pass_http_request GET 'localhost:5000/value\foo' + get_echo_request_path | grep -Fx '/value/foo' + retry_default must_pass_http_request GET 'localhost:5000/value\\foo' + get_echo_request_path | grep -Fx '/value/foo' + retry_default must_pass_http_request GET 'localhost:5000/value\/foo' + get_echo_request_path | grep -Fx '/value/foo' + retry_default must_pass_http_request GET 'localhost:5000/value/\/foo' + get_echo_request_path | grep -Fx '/value/foo' +} + +@test "test disallowed underscore in header key" { + # Envoy responds with 400 when configured to reject underscore headers. + retry_default must_fail_http_request 400 GET localhost:5000/foo x_poison:anything + retry_default must_fail_http_request 400 GET localhost:5000/foo x_check:bad + retry_default must_fail_http_request 400 GET localhost:5000/foo x_check:good-sufbad + retry_default must_fail_http_request 400 GET localhost:5000/foo x_check:prebad-good +} + +@test "test disallowed contains header" { + retry_default must_fail_http_request 403 GET localhost:5000/foo x-check:thiscontainsbadinit +} + +@test "test disallowed ignore case header" { + retry_default must_fail_http_request 403 GET localhost:5000/foo x-check:exactBaD + retry_default must_fail_http_request 403 GET localhost:5000/foo x-check:good-SuFBaD + retry_default must_fail_http_request 403 GET localhost:5000/foo x-check:PrEBaD-good + retry_default must_fail_http_request 403 GET localhost:5000/foo x-check:thiscontainsBaDinit + retry_default must_fail_http_request 403 GET localhost:5000/foo Host:foo.BaD.com +} + +@test "test case-insensitive disallowed header" { + retry_default must_fail_http_request 403 GET localhost:5000/foo Host:foo.BAD.com +} + + +# @test "s1 upstream should NOT be able to connect to s2" { +# run retry_default must_fail_tcp_connection localhost:5000 + +# echo "OUTPUT $output" + +# [ "$status" == "0" ] +# } diff --git a/test/integration/connect/envoy/case-l7-intentions/setup.sh b/test/integration/connect/envoy/case-l7-intentions/setup.sh index 6946ce3263a9..04f35bb92bff 100644 --- a/test/integration/connect/envoy/case-l7-intentions/setup.sh +++ b/test/integration/connect/envoy/case-l7-intentions/setup.sh @@ -51,6 +51,17 @@ sources { }] } }, + { + action = "allow" + http { + path_exact = "/hdr-exact-ignore-case" + header = [{ + name = "x-test-debug" + exact = "foo.bar.com" + ignore_case = true + }] + } + }, { action = "allow" http { @@ -61,6 +72,17 @@ sources { }] } }, + { + action = "allow" + http { + path_exact = "/hdr-prefix-ignore-case" + header = [{ + name = "x-test-debug" + prefix = "foo.bar" + ignore_case = true + }] + } + }, { action = "allow" http { @@ -71,6 +93,38 @@ sources { }] } }, + { + action = "allow" + http { + path_exact = "/hdr-suffix-ignore-case" + header = [{ + name = "x-test-debug" + suffix = "bar.com" + ignore_case = true + }] + } + }, + { + action = "allow" + http { + path_exact = "/hdr-contains" + header = [{ + name = "x-test-debug" + contains = "contains" + }] + } + }, + { + action = "allow" + http { + path_exact = "/hdr-contains-ignore-case" + header = [{ + name = "x-test-debug" + contains = "contains" + ignore_case = true + }] + } + }, { action = "allow" http { diff --git a/test/integration/connect/envoy/case-l7-intentions/verify.bats b/test/integration/connect/envoy/case-l7-intentions/verify.bats index 80a1530476f4..484ec5fd7e3c 100644 --- a/test/integration/connect/envoy/case-l7-intentions/verify.bats +++ b/test/integration/connect/envoy/case-l7-intentions/verify.bats @@ -34,49 +34,84 @@ load helpers @test "test exact path" { retry_default must_pass_http_request GET localhost:5000/exact - retry_default must_fail_http_request GET localhost:5000/exact-nope + retry_default must_fail_http_request 403 GET localhost:5000/exact-nope } @test "test prefix path" { retry_default must_pass_http_request GET localhost:5000/prefix - retry_default must_fail_http_request GET localhost:5000/nope-prefix + retry_default must_fail_http_request 403 GET localhost:5000/nope-prefix } @test "test regex path" { retry_default must_pass_http_request GET localhost:5000/regex - retry_default must_fail_http_request GET localhost:5000/reggex + retry_default must_fail_http_request 403 GET localhost:5000/reggex } @test "test present header" { - retry_default must_pass_http_request GET localhost:5000/hdr-present anything - retry_default must_fail_http_request GET localhost:5000/hdr-present "" + retry_default must_pass_http_request GET localhost:5000/hdr-present x-test-debug:anything + retry_default must_fail_http_request 403 GET localhost:5000/hdr-present x-test-debug: } @test "test exact header" { - retry_default must_pass_http_request GET localhost:5000/hdr-exact exact - retry_default must_fail_http_request GET localhost:5000/hdr-exact exact-nope + retry_default must_pass_http_request GET localhost:5000/hdr-exact x-test-debug:exact + retry_default must_fail_http_request 403 GET localhost:5000/hdr-exact x-test-debug:exact-nope } @test "test prefix header" { - retry_default must_pass_http_request GET localhost:5000/hdr-prefix prefix - retry_default must_fail_http_request GET localhost:5000/hdr-prefix nope-prefix + retry_default must_pass_http_request GET localhost:5000/hdr-prefix x-test-debug:prefix + retry_default must_fail_http_request 403 GET localhost:5000/hdr-prefix x-test-debug:nope-prefix } @test "test suffix header" { - retry_default must_pass_http_request GET localhost:5000/hdr-suffix suffix - retry_default must_fail_http_request GET localhost:5000/hdr-suffix suffix-nope + retry_default must_pass_http_request GET localhost:5000/hdr-suffix x-test-debug:suffix + retry_default must_fail_http_request 403 GET localhost:5000/hdr-suffix x-test-debug:suffix-nope +} + +@test "test contains header" { + retry_default must_pass_http_request GET localhost:5000/hdr-contains x-test-debug:contains + retry_default must_pass_http_request GET localhost:5000/hdr-contains x-test-debug:ccontainss + retry_default must_pass_http_request GET localhost:5000/hdr-contains x-test-debug:still-contains-value + retry_default must_fail_http_request 403 GET localhost:5000/hdr-contains x-test-debug:conntains } @test "test regex header" { - retry_default must_pass_http_request GET localhost:5000/hdr-regex regex - retry_default must_fail_http_request GET localhost:5000/hdr-regex reggex + retry_default must_pass_http_request GET localhost:5000/hdr-regex x-test-debug:regex + retry_default must_fail_http_request 403 GET localhost:5000/hdr-regex x-test-debug:reggex +} + +@test "test exact ignore case header" { + retry_default must_pass_http_request GET localhost:5000/hdr-exact-ignore-case x-test-debug:foo.bar.com + retry_default must_pass_http_request GET localhost:5000/hdr-exact-ignore-case x-test-debug:foo.BAR.com + retry_default must_pass_http_request GET localhost:5000/hdr-exact-ignore-case x-test-debug:fOo.bAr.coM + retry_default must_fail_http_request 403 GET localhost:5000/hdr-exact-ignore-case x-test-debug:fOo.bAr.coM.nope +} + +@test "test prefix ignore case header" { + retry_default must_pass_http_request GET localhost:5000/hdr-prefix-ignore-case x-test-debug:foo.bar.com + retry_default must_pass_http_request GET localhost:5000/hdr-prefix-ignore-case x-test-debug:foo.BAR.com + retry_default must_pass_http_request GET localhost:5000/hdr-prefix-ignore-case x-test-debug:fOo.bAr.coM + retry_default must_fail_http_request 403 GET localhost:5000/hdr-prefix-ignore-case x-test-debug:nope.fOo.bAr.coM +} + +@test "test suffix ignore case header" { + retry_default must_pass_http_request GET localhost:5000/hdr-suffix-ignore-case x-test-debug:foo.bar.com + retry_default must_pass_http_request GET localhost:5000/hdr-suffix-ignore-case x-test-debug:foo.BAR.com + retry_default must_pass_http_request GET localhost:5000/hdr-suffix-ignore-case x-test-debug:fOo.bAr.coM + retry_default must_fail_http_request 403 GET localhost:5000/hdr-suffix-ignore-case x-test-debug:fOo.bAr.coM.nope +} + +@test "test contains ignore case header" { + retry_default must_pass_http_request GET localhost:5000/hdr-contains-ignore-case x-test-debug:cOntAins + retry_default must_pass_http_request GET localhost:5000/hdr-contains-ignore-case x-test-debug:CconTainsS + retry_default must_pass_http_request GET localhost:5000/hdr-contains-ignore-case x-test-debug:still-cOntAins-value + retry_default must_fail_http_request 403 GET localhost:5000/hdr-contains-ignore-case x-test-debug:cOnntAins } @test "test method match" { retry_default must_pass_http_request GET localhost:5000/method-match retry_default must_pass_http_request PUT localhost:5000/method-match - retry_default must_fail_http_request POST localhost:5000/method-match - retry_default must_fail_http_request HEAD localhost:5000/method-match + retry_default must_fail_http_request 403 POST localhost:5000/method-match + retry_default must_fail_http_request 403 HEAD localhost:5000/method-match } # @test "s1 upstream should NOT be able to connect to s2" { diff --git a/test/integration/connect/envoy/helpers.bash b/test/integration/connect/envoy/helpers.bash index 1173101716dd..0eee6a84f75e 100755 --- a/test/integration/connect/envoy/helpers.bash +++ b/test/integration/connect/envoy/helpers.bash @@ -761,17 +761,13 @@ function must_fail_http_connection { } # must_pass_http_request allows you to craft a specific http request to assert -# that envoy will NOT reject the request. Primarily of use for testing L7 -# intentions. +# that envoy will NOT reject the request. function must_pass_http_request { local METHOD=$1 local URL=$2 - local DEBUG_HEADER_VALUE="${3:-""}" + shift 2 local extra_args - if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then - extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}" - fi case "$METHOD" in GET) ;; @@ -786,22 +782,25 @@ function must_pass_http_request { ;; esac + # Treat any remaining args as header KVs + for HEADER_ARG in "$@"; do + extra_args="$extra_args -H ${HEADER_ARG}" + done + run curl --no-keepalive -v -s -f $extra_args "$URL" [ "$status" == 0 ] } # must_fail_http_request allows you to craft a specific http request to assert -# that envoy will reject the request. Primarily of use for testing L7 -# intentions. +# that envoy will reject the request. Must supply the expected status code before +# method and URL. function must_fail_http_request { - local METHOD=$1 - local URL=$2 - local DEBUG_HEADER_VALUE="${3:-""}" + local EXPECT_RESPONSE=$1 + local METHOD=$2 + local URL=$3 + shift 2 local extra_args - if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then - extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}" - fi case "$METHOD" in HEAD) extra_args="$extra_args -I" @@ -819,12 +818,42 @@ function must_fail_http_request { ;; esac + # Treat any remaining args as header KVs + for HEADER_ARG in "$@"; do + extra_args="$extra_args -H ${HEADER_ARG}" + done + # Attempt to curl through upstream run curl --no-keepalive -s -i $extra_args "$URL" echo "OUTPUT $output" - echo "$output" | grep "403 Forbidden" + # Output of curl should include status code immediately after 'HTTP/1.1' + echo "$output" | grep "HTTP/1.1 $EXPECT_RESPONSE" +} + +# Gets the JSON response containing request parameters from the echo service response. +# See https://github.com/mendhak/docker-http-https-echo?tab=readme-ov-file#screenshots +# for example response body. +# Requires SERVICE_CONTAINER=echo. +function get_echo_output { + # Take the JSON response from $output, starting with first line containing only '{' + # and ending with the next line containing only '}'. + # The first sed converts a trailing '}* ' (curl -v output) to just '}'. + local json=$(echo "$output" | sed 's/}\*.*/}/' | sed -n -e '/^{$/,/^}$/{ p; }') + echo $json | jq -r '.' || echo "Output did not contain valid JSON: $output" >&3 +} + +# Gets the value of the raw request path from the echo service response. +# Requires SERVICE_CONTAINER=echo. +function get_echo_request_path { + get_echo_output | jq -r '.path' +} + +# Gets the value of a given request header from the echo service response. +# Requires SERVICE_CONTAINER=echo. +function get_echo_request_header_value { + get_echo_output | jq -r ".headers.$1" } function gen_envoy_bootstrap { diff --git a/test/integration/connect/envoy/run-tests.sh b/test/integration/connect/envoy/run-tests.sh index 1efebe7cf620..274f75f5db98 100755 --- a/test/integration/connect/envoy/run-tests.sh +++ b/test/integration/connect/envoy/run-tests.sh @@ -602,15 +602,43 @@ function run_container { "run_container_$1" } +# Run the common service container. By default, uses fortio/fortio. +# +# To use mendhak/http-https-echo, set SERVICE_CONTAINER=echo in vars.sh. +# +# To provide a custom docker run command for test containers, override +# common_run_container_service in vars.sh (which will be sourced prior to +# invocation). Use $(container_name_prev) in the custom function to get +# the correct effective container name. See common_run_container-fortio +# for the expected args list. function common_run_container_service { - local service="$1" - local CLUSTER="$2" - local httpPort="$3" - local grpcPort="$4" + local serviceContainer=${SERVICE_CONTAINER:-fortio} + local containerName=$(container_name_prev) - docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name_prev) \ + case "$serviceContainer" in + fortio) + common_run_container-fortio "$containerName" "$@" + ;; + echo) + common_run_container-echo "$containerName" "$@" + ;; + *) + echo "Unknown common run container: $runContainer" + return 1 + ;; + esac +} + +function common_run_container-fortio { + local containerName="$1" + local service="$2" + local cluster="$3" + local httpPort="$4" + local grpcPort="$5" + + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $containerName \ -e "FORTIO_NAME=${service}" \ - $(network_snippet $CLUSTER) \ + $(network_snippet $cluster) \ "${HASHICORP_DOCKER_PROXY}/fortio/fortio" \ server \ -http-port ":$httpPort" \ @@ -618,6 +646,25 @@ function common_run_container_service { -redirect-port disabled >/dev/null } +# Alternative to Fortio, which has limited ability to echo back arbitrary +# requests (only one pre-determined debug path), and uses Go's net/http, which +# force-normalizes paths. Useful for verifying HTTP request parameters sent by +# Envoy to the upstream. +function common_run_container-echo { + local containerName="$1" + local cluster="$3" + local httpPort="$4" + + # HTTPS_PORT=0 will randomly assign a port number. It must be set, otherwise + # multiple containers on same network will fail due to using the same default port. + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $containerName \ + -e "HTTP_PORT=${httpPort}" \ + -e "HTTPS_PORT=0" \ + $(network_snippet $cluster) \ + ${HASHICORP_DOCKER_PROXY}/mendhak/http-https-echo:34 >/dev/null +} + + function run_container_s1 { common_run_container_service s1 primary 8080 8079 } diff --git a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.hbs b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.hbs index 3ae87f1be1b6..5164f8be1bb1 100644 --- a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.hbs @@ -69,7 +69,20 @@ {{/if}} + {{#if shouldShowIgnoreCaseField}} + + Ignore Case + + + {{/if}} + - \ No newline at end of file + diff --git a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.js b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.js index ddbbc20eb5b0..11faf44befae 100644 --- a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.js +++ b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.js @@ -4,7 +4,7 @@ */ import Component from '@ember/component'; -import { get, set, computed } from '@ember/object'; +import { set, computed } from '@ember/object'; import { alias, equal, not } from '@ember/object/computed'; import { inject as service } from '@ember/service'; @@ -37,6 +37,7 @@ export default Component.extend({ Exact: 'Exactly Matching', Prefix: 'Prefixed by', Suffix: 'Suffixed by', + Contains: 'Containing', Regex: 'Regular Expression', Present: 'Is present', }; @@ -49,9 +50,14 @@ export default Component.extend({ headerTypeEqualsPresent: equal('headerType', 'Present'), shouldShowValueField: not('headerTypeEqualsPresent'), + shouldShowIgnoreCaseField: computed('headerType', function () { + return this.headerType !== 'Present' && this.headerType !== 'Regex'; + }), + actions: { change: function (name, changeset, e) { - const value = typeof get(e, 'target.value') !== 'undefined' ? e.target.value : e; + const valueIndicator = e.target?.type === 'checkbox' ? e.target?.checked : e.target?.value; + const value = typeof valueIndicator !== 'undefined' ? valueIndicator : e; switch (name) { default: changeset.set(name, value); @@ -65,6 +71,7 @@ export default Component.extend({ // Present is a boolean, whereas all other header types have a value const value = changeset.HeaderType === 'Present' ? true : changeset.Value; changeset.set(changeset.HeaderType, value); + changeset.set('IgnoreCase', changeset.IgnoreCase); // this will prevent the changeset from overwriting the // computed properties on the ED object diff --git a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/pageobject.js b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/pageobject.js index c142a4c8b7d6..4e309f1892cb 100644 --- a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/pageobject.js +++ b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/pageobject.js @@ -11,7 +11,14 @@ export default (scope = '.consul-intention-permission-header-form') => { scope: scope, HeaderType: { scope: '[data-property="headertype"]', - ...powerSelect(['ExactlyMatching', 'PrefixedBy', 'SuffixedBy', 'RegEx', 'IsPresent']), + ...powerSelect([ + 'ExactlyMatching', + 'PrefixedBy', + 'SuffixedBy', + 'Containing', + 'RegEx', + 'IsPresent', + ]), }, Name: { scope: '[data-property="name"] input', diff --git a/ui/packages/consul-ui/app/helpers/route-match.js b/ui/packages/consul-ui/app/helpers/route-match.js index 479a3832778b..bdf77cc32403 100644 --- a/ui/packages/consul-ui/app/helpers/route-match.js +++ b/ui/packages/consul-ui/app/helpers/route-match.js @@ -6,21 +6,26 @@ import { helper } from '@ember/component/helper'; export default helper(function routeMatch([item], hash) { - const prop = ['Present', 'Exact', 'Prefix', 'Suffix', 'Regex'].find( + const prop = ['Present', 'Exact', 'Prefix', 'Suffix', 'Contains', 'Regex'].find( (prop) => typeof item[prop] !== 'undefined' ); + let invertPrefix = item.Invert ? 'NOT ' : ''; + let ignoreCaseSuffix = item.IgnoreCase ? ' (case-insensitive)' : ''; + switch (prop) { case 'Present': - return `${item.Invert ? `NOT ` : ``}present`; + return `${invertPrefix}present`; case 'Exact': - return `${item.Invert ? `NOT ` : ``}exactly matching "${item.Exact}"`; + return `${invertPrefix}exactly matching "${item.Exact}"${ignoreCaseSuffix}`; case 'Prefix': - return `${item.Invert ? `NOT ` : ``}prefixed by "${item.Prefix}"`; + return `${invertPrefix}prefixed by "${item.Prefix}"${ignoreCaseSuffix}`; case 'Suffix': - return `${item.Invert ? `NOT ` : ``}suffixed by "${item.Suffix}"`; + return `${invertPrefix}suffixed by "${item.Suffix}"${ignoreCaseSuffix}`; + case 'Contains': + return `${invertPrefix}containing "${item.Contains}"${ignoreCaseSuffix}`; case 'Regex': - return `${item.Invert ? `NOT ` : ``}matching the regex "${item.Regex}"`; + return `${invertPrefix}matching the regex "${item.Regex}"`; } return ''; }); diff --git a/ui/packages/consul-ui/app/models/intention-permission-http-header.js b/ui/packages/consul-ui/app/models/intention-permission-http-header.js index b327ff91ab1e..f17a0d2d96a6 100644 --- a/ui/packages/consul-ui/app/models/intention-permission-http-header.js +++ b/ui/packages/consul-ui/app/models/intention-permission-http-header.js @@ -13,7 +13,7 @@ export const schema = { required: true, }, HeaderType: { - allowedValues: ['Exact', 'Prefix', 'Suffix', 'Regex', 'Present'], + allowedValues: ['Exact', 'Prefix', 'Suffix', 'Contains', 'Regex', 'Present'], }, }; @@ -23,11 +23,13 @@ export default class IntentionPermission extends Fragment { @attr('string') Exact; @attr('string') Prefix; @attr('string') Suffix; + @attr('string') Contains; @attr('string') Regex; // this is a boolean but we don't want it to automatically be set to false @attr() Present; @or(...schema.HeaderType.allowedValues) Value; + @attr('boolean') IgnoreCase; @computed(...schema.HeaderType.allowedValues) get HeaderType() { diff --git a/ui/packages/consul-ui/mock-api/v1/connect/_ b/ui/packages/consul-ui/mock-api/v1/connect/_ index 7ba49d725677..a87d00208154 100644 --- a/ui/packages/consul-ui/mock-api/v1/connect/_ +++ b/ui/packages/consul-ui/mock-api/v1/connect/_ @@ -78,11 +78,15 @@ ${range(headerCount).map(item => ` ${fake.random.boolean() ? ` "Invert": true, ` : ``} +${fake.random.boolean() ? ` + "IgnoreCase": true, +` : ``} ${fake.helpers.randomize([ '"Present": true', '"Exact": "abc"', '"Prefix": "abc"', '"Suffix": "xyz"', + '"Contains": "abc"', '"Regex": "[abc]"' ])} } diff --git a/ui/packages/consul-ui/mock-api/v1/connect/intentions/_ b/ui/packages/consul-ui/mock-api/v1/connect/intentions/_ index 26dd645f90c5..0349dd5211c5 100644 --- a/ui/packages/consul-ui/mock-api/v1/connect/intentions/_ +++ b/ui/packages/consul-ui/mock-api/v1/connect/intentions/_ @@ -63,11 +63,15 @@ ${range(headerCount).map(item => ` ${fake.random.boolean() ? ` "Invert": true, ` : ``} +${fake.random.boolean() ? ` + "IgnoreCase": true, +` : ``} ${fake.helpers.randomize([ '"Present": true', '"Exact": "abc"', '"Prefix": "abc"', '"Suffix": "xyz"', + '"Contains": "abc"', '"Regex": "[abc]"' ])} } diff --git a/ui/packages/consul-ui/mock-api/v1/connect/intentions/exact b/ui/packages/consul-ui/mock-api/v1/connect/intentions/exact index 9de0cf4b33c4..2b4142bf7437 100644 --- a/ui/packages/consul-ui/mock-api/v1/connect/intentions/exact +++ b/ui/packages/consul-ui/mock-api/v1/connect/intentions/exact @@ -69,11 +69,15 @@ ${range(headerCount).map(item => ` ${fake.random.boolean() ? ` "Invert": true, ` : ``} +${fake.random.boolean() ? ` + "IgnoreCase": true, +` : ``} ${fake.helpers.randomize([ '"Present": true', '"Exact": "abc"', '"Prefix": "abc"', '"Suffix": "xyz"', + '"Contains": "abc"', '"Regex": "[abc]"' ])} } diff --git a/website/content/docs/connect/config-entries/mesh.mdx b/website/content/docs/connect/config-entries/mesh.mdx index 9352b2cc240d..b64062e5189f 100644 --- a/website/content/docs/connect/config-entries/mesh.mdx +++ b/website/content/docs/connect/config-entries/mesh.mdx @@ -264,6 +264,58 @@ spec: Note that the Kubernetes example does not include a `partition` field. Configuration entries are applied on Kubernetes using [custom resource definitions (CRD)](/consul/docs/k8s/crds), which can only be scoped to their own partition. +### Request Normalization + +Enable options under `HTTP.Incoming.RequestNormalization` to apply normalization to all inbound traffic to mesh proxies. + + + +```hcl +Kind = "mesh" +HTTP { + Incoming { + RequestNormalization { + InsecureDisablePathNormalization = false // default false, shown for completeness + MergeSlashes = true + PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD" + HeadersWithUnderscoresAction = "REJECT_REQUEST" + } + } +} +``` + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: Mesh +metadata: + name: mesh +spec: + http: + incoming: + requestNormalization: + insecureDisablePathNormalization: false # default false, shown for completeness + mergeSlashes: true + pathWithEscapedSlashesAction: UNESCAPE_AND_FORWARD + headersWithUnderscoresAction: REJECT_REQUEST +``` + +```json +{ + "Kind": "mesh", + "HTTP": { + "Incoming": { + "RequestNormalization": { + "InsecureDisablePathNormalization": false, + "MergeSlashes": true, + "PathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD", + "HeadersWithUnderscoresAction": "REJECT_REQUEST" + } + } + } +} +``` + + ## Available Fields @@ -452,6 +504,57 @@ Note that the Kubernetes example does not include a `partition` field. Configura for all Envoy proxies. As a result, Consul will not include the \`x-forwarded-client-cert\` header in the next hop. If set to \`false\` (default), the XFCC header is propagated to upstream applications.`, }, + { + name: 'Incoming', + type: 'DirectionalHTTPConfig: ', + description: `HTTP configuration for inbound traffic to mesh proxies.`, + children: [ + { + name: 'RequestNormalization', + type: 'RequestNormalizationConfig: ', + description: `Request normalization configuration for inbound traffic to mesh proxies.`, + children: [ + { + name: 'InsecureDisablePathNormalization', + type: 'bool: false', + description: `Sets the value of the \`normalize_path\` option in the Envoy listener's \`HttpConnectionManager\`. The default value is \`false\`. + When set to \`true\` in Consul, \`normalize_path\` is set to \`false\` for the Envoy proxy. + This parameter disables the normalization of request URL paths according to RFC 3986, + conversion of \`\\\` to \`/\`, and decoding non-reserved %-encoded characters. When using L7 + intentions with path match rules, we recommend enabling path normalization in order + to avoid match rule circumvention with non-normalized path values.`, + }, + { + name: 'MergeSlashes', + type: 'bool: false', + description: `Sets the value of the \`merge_slashes\` option in the Envoy listener's \`HttpConnectionManager\`. The default value is \`false\`. + This option controls the normalization of request URL paths by merging consecutive \`/\` characters. This normalization is not part + of RFC 3986. When using L7 intentions with path match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path values, unless legitimate service + traffic depends on allowing for repeat \`/\` characters, or upstream services are configured to + differentiate between single and multiple slashes.`, + }, + { + name: 'PathWithEscapedSlashesAction', + type: 'string: ""', + description: `Sets the value of the \`path_with_escaped_slashes_action\` option in the Envoy listener's + \`HttpConnectionManager\`. The default value of this option is empty, which is + equivalent to \`IMPLEMENTATION_SPECIFIC_DEFAULT\`. This parameter controls the action taken in response to request URL paths with escaped + slashes in the path. When using L7 intentions with path match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path values, unless legitimate service + traffic depends on allowing for escaped \`/\` or \`\\\` characters, or upstream services are configured to + differentiate between escaped and unescaped slashes. Refer to the Envoy documentation for more information on available + options.`, + }, + { + name: 'HeadersWithUnderscoresAction', + type: 'string: ""', + description: `Sets the value of the \`headers_with_underscores_action\` option in the Envoy listener's + \`HttpConnectionManager\` under \`common_http_protocol_options\`. The default value of this option is + empty, which is equivalent to \`ALLOW\`. Refer to the Envoy documentation for more information on available options.`, + }, + ], + }, + ], + } ], }, { diff --git a/website/content/docs/connect/config-entries/service-intentions.mdx b/website/content/docs/connect/config-entries/service-intentions.mdx index 929f9e2e606e..4440b2a76c1e 100644 --- a/website/content/docs/connect/config-entries/service-intentions.mdx +++ b/website/content/docs/connect/config-entries/service-intentions.mdx @@ -96,7 +96,9 @@ The following outline shows how to format the service intentions configuration e - [`exact`](#spec-sources-permissions-http-header): string | no default - [`prefix`](#spec-sources-permissions-http-header): string | no default - [`suffix`](#spec-sources-permissions-http-header): string | no default + - [`contains`](#spec-sources-permissions-http-header): string | no default - [`regex`](#spec-sources-permissions-http-header): string | no default + - [`ignoreCase`](#spec-sources-permissions-http-header): boolean | `false` - [`invert`](#spec-sources-permissions-http-header): boolean | `false` - [`description`](#spec-sources-description): string @@ -156,18 +158,31 @@ Sources = [ { Name = "" # string Present = # boolean + Invert = # boolean }, { Name = "" # string Exact = "" # boolean + IgnoreCase = # boolean + Invert = # boolean }, { Name = "" # string Prefix = "" # string + IgnoreCase = # boolean + Invert = # boolean }, { Name = "" # string Suffix = "" # string + IgnoreCase = # boolean + Invert = # boolean + }, + { + Name = "" # string + Contains = "" # string + IgnoreCase = # boolean + Invert = # boolean }, { Name = "" # string @@ -227,12 +242,23 @@ spec: header: - name: present: true + invert: false - name: - exact: false + exact: + ignoreCase: false + invert: false - name: prefix: + ignoreCase: false + invert: false - name: suffix: + ignoreCase: false + invert: false + - name: + contains: + ignoreCase: false + invert: false - name: regex: invert: false @@ -287,19 +313,32 @@ spec: "Header":[ { "Name":"", - "Present":true + "Present":true, + "Invert":false + }, + { + "Name":"", + "Exact":"", + "IgnoreCase":false,, + "Invert":false }, { "Name":"", - "Exact":false + "Prefix":"", + "IgnoreCase":false, + "Invert":false }, { "Name":"", - "Prefix":"" + "Suffix":"", + "IgnoreCase":false, + "Invert":false }, { "Name":"", - "Suffix":"" + "Contains":"", + "IgnoreCase":false, + "Invert":false }, { "Name":"", @@ -923,16 +962,22 @@ Specifies a set of criteria for matching HTTP request headers. The request heade - Default: None - Data type: List of maps -Each member of the `header` list is a map that contains a `name` field and at least one match criterion. The following table describes the parameters that each member of the `header` list may contain: +Each member of the `header` list is a map that contains a `name` field and at least one match criterion. + +~> **Warning**: If it is possible for a header to contain multiple values, we recommend using `contains` or `regex` rather than `exact`, `prefix`, or `suffix`. Envoy internally concatenates multiple header values into a single CSV value prior to applying match rules, which may result in match rules that depend on the beginning or end of a string vulnerable to circumvention. A more robust alternative is using `contains` or, if a stricter value match is required, configuring a regex pattern that is tolerant of comma-separated values. + +The following table describes the parameters that each member of the `header` list may contain: | Parameter | Description | Data type | Required | | --- | --- | --- | --- | | `name` | Specifies the name of the header to match. | string | required | -| `present` | Enables a match if the header configured in the `name` field appears in the request. Consul matches on any value as long as the header key appears in the request. Do not specify `present` if `exact`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | boolean | optional | -| `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `exact` value, Consul applies the permission. Do not specify `exact` if `present`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional | -| `prefix` | Specifies a prefix value for the header key set in the `name` field. If the request header value starts with the `prefix` value, Consul applies the permission. Do not specify `prefix` if `present`, `exact`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional | -| `suffix` | Specifies a suffix value for the header key set in the `name` field. If the request header value ends with the `suffix` value, Consul applies the permission. Do not specify `suffix` if `present`, `exact`, `prefix`, or `regex` are configured in the same `header` configuration. | string | optional | -| `regex` | Specifies a regular expression pattern as the value for the header key set in the `name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `regex` if `present`, `exact`, `prefix`, or `suffix` are configured in the same `header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional | +| `present` | Enables a match if the header configured in the `name` field appears in the request. Consul matches on any value as long as the header key appears in the request. Do not specify `present` if `exact`, `prefix`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | boolean | optional | +| `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `exact` value, Consul applies the permission. Do not specify `exact` if `present`, `prefix`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional | +| `prefix` | Specifies a prefix value for the header key set in the `name` field. If the request header value starts with the `prefix` value, Consul applies the permission. Do not specify `prefix` if `present`, `exact`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional | +| `suffix` | Specifies a suffix value for the header key set in the `name` field. If the request header value ends with the `suffix` value, Consul applies the permission. Do not specify `suffix` if `present`, `exact`, `prefix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional | +| `contains` | Specifies a contains value for the header key set in the `name` field. If the request header value includes the `contains` value, Consul applies the permission. Do not specify `contains` if `present`, `exact`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional | +| `regex` | Specifies a regular expression pattern as the value for the header key set in the `name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `regex` if `present`, `exact`, `prefix`, `suffix`, or `contains` are configured in the same `header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional | +| `ignoreCase` | Ignores the case of the provided header value when matching with exact, prefix, suffix, or contains. Default is `false`. | boolean | optional | | `invert` | Inverts the matching logic configured in the `header`. Default is `false`. | boolean | optional | ### `spec.sources[].type` diff --git a/website/content/docs/connect/intentions/index.mdx b/website/content/docs/connect/intentions/index.mdx index c9bbbabf2acc..8d6364638a0a 100644 --- a/website/content/docs/connect/intentions/index.mdx +++ b/website/content/docs/connect/intentions/index.mdx @@ -36,7 +36,11 @@ application](/consul/docs/connect/native) enforces intentions on inbound connect L4 intentions mediate the ability to establish new connections. Modifying an intention does not have an effect on existing connections. As a result, changing a connection from `allow` to `deny` does not sever the connection. -L7 intentions mediate the ability to issue new requests. When an intention is modified, requests received after the modification use the latest intention rules to enforce access. Changing a connection from `allow` to `deny` does not sever the connection, but doing so blocks new requests from being processed. +L7 intentions mediate the ability to issue new requests. When an intention is modified, requests received after the modification use the latest intention rules to enforce access. Changing a connection from `allow` to `deny` does not sever the connection, but doing so blocks new requests from being processed. + +When using L7 intentions, we recommend that you review and update the [Mesh request normalization configuration](/consul/docs/connect/security#request-normalization-and-configured) to avoid unintended match rule circumvention. More details are available in the [Mesh configuration entry reference](/consul/docs/connect/config-entries/mesh#request-normalization). + +When you use L7 intentions with header matching and it is possible for a header to contain multiple values, we recommend using `contains` or `regex` instead of `exact`, `prefix`, or `suffix`. For more information, refer to the [service intentions configuration entry reference](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header). ### Caching diff --git a/website/content/docs/connect/security.mdx b/website/content/docs/connect/security.mdx index 1889f57406d8..a65d4fabcd8f 100644 --- a/website/content/docs/connect/security.mdx +++ b/website/content/docs/connect/security.mdx @@ -32,10 +32,38 @@ Consul should be configured with a default deny intention policy. This forces all service-to-service communication to be explicitly allowed via an allow [intention](/consul/docs/connect/intentions). +One advantage of using a default deny policy in combination with specific "allow" rules +is that a failure of intentions due to misconfiguration always results in +_denied_ traffic, rather than unwanted _allowed_ traffic. + In the absence of `default_intention_policy` Consul will fall back to the ACL default policy when determining whether to allow or deny communications without an explicit intention. +### Request Normalization Configured for L7 Intentions + +Atypical traffic patterns may interfere with the enforcement of L7 intentions. For +example, if a service makes request to a non-normalized URI path and Consul is not +configured to force path normalization, it becomes possible to circumvent path match rules. While a +default deny policy can limit the impact of this issue, we still recommend +that you review your current request normalization configuration. Normalization is critical to avoid unwanted +traffic, especially when using unrecommended security options such as a default allow intentions policy. + +Consul adopts a default normalization mode that adheres to [RFC 3986]( +https://tools.ietf.org/html/rfc3986#section-6), but additional options to enable stricter +normalization are available in the cluster-wide [Mesh configuration entry]( +/consul/docs/connect/config-entries/mesh). We recommend reviewing these options and +enabling the strictest set that does not interfere with application traffic. + +We also recommend that you review L7 intention header match rules for potential +issues with multiple header values. Refer to the [service intentions +configuration entry reference](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header) +for more information. + +You do not need to enable request normalization if you are not using L7 intentions. +However, normalization may also benefit the use of other service mesh features that +rely on L7 attribute matching, such as [service routers](/consul/docs/connect/manage-traffic#routing). + ### ACLs Enabled with Default Deny Consul must be configured to use ACLs with a default deny policy. This forces @@ -51,6 +79,10 @@ this. **If ACLs are not enabled**, deny intentions will still be enforced, but a may edit intentions. This renders the security of the created intentions effectively useless. +The advantage of a default deny policy in combination with specific "allow" rules +is that at worst, a failure of intentions due to misconfiguration will result in +_denied_ traffic, rather than unwanted _allowed_ traffic. + ### TCP and UDP Encryption Enabled TCP and UDP encryption must be enabled to prevent plaintext communication diff --git a/website/content/docs/security/security-models/core.mdx b/website/content/docs/security/security-models/core.mdx index 1c57c6cc51cb..9b0da86089ca 100644 --- a/website/content/docs/security/security-models/core.mdx +++ b/website/content/docs/security/security-models/core.mdx @@ -26,6 +26,10 @@ environment, but the general mechanisms for a secure Consul deployment revolve a [authentication methods](/consul/docs/security/acl/auth-methods) can be used to enable trusted external parties to authorize ACL token creation. +- **Intentions** - If in use, configure service intentions to use a default-deny policy. If L7 intentions are + in use, enable [Mesh request normalization](/consul/docs/connect/config-entries/mesh#request-normalization) + and review your [header match rules](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header) to prevent malformed requests from bypassing intentions. + - **Namespaces** - Read and write operations can be scoped to a logical namespace to restrict access to Consul components within a multi-tenant environment. @@ -178,6 +182,13 @@ environment and adapt these configurations accordingly. - **🏷 Namespace** - a named, logical scoping of Consul Enterprise resources, typically to enable multi-tenant environments. Consul CE clusters always operate within the "default" namespace. +- **Intentions** - Service intentions control traffic communication between services at the network layer (L4) and + application layer (L7). If in use, we strongly recommend configuring intentions to use a default-deny policy. + When L7 intentions are in use, review your configuration for [Mesh request normalization](/consul/docs/connect/config-entries/mesh#request-normalization) + and use the strictest set of options suitable to your environment. At minimum, we + recommend keeping path normalization enabled, because this default setting prevents requests that do not conform to [RFC 3986]( + https://tools.ietf.org/html/rfc3986#section-6) from bypassing path match rules. + - **Gossip Encryption** - A shared, base64-encoded 32-byte symmetric key is required to [encrypt Serf gossip communication](/consul/tutorials/security/gossip-encryption-secure?utm_source=consul.io&utm_medium=docs) within a cluster using AES GCM. The key size determines which AES encryption types to use; 16, 24, or 32 bytes to select AES-128, AES-192, @@ -252,6 +263,10 @@ environment and adapt these configurations accordingly. } ``` +- **Customize Mesh HTTP Request Normalization** - If L7 intentions are in use, we recommend configuring request normalization to + avoid match rule circumvention. Other normalization options, such as dropping or rejecting headers with underscores, + may also be appropriate depending on your requirements. Review the options in the [Mesh configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization) to determine the appropriate settings for your use case. + - **Customize Default Limits** - Consul has a number of builtin features with default connection limits that should be tuned to fit your environment. diff --git a/website/content/docs/upgrading/upgrade-specific.mdx b/website/content/docs/upgrading/upgrade-specific.mdx index b731408f2711..c7fec8cb3412 100644 --- a/website/content/docs/upgrading/upgrade-specific.mdx +++ b/website/content/docs/upgrading/upgrade-specific.mdx @@ -43,6 +43,15 @@ The Kubernetes-only legacy API gateway is superseded by the modern, multi-runtim [API gateway](/consul/docs/connect/config-entries/api-gateway). On Kubernetes, the modern API gateway is associated with the `connectInject.apiGateway` stanza. +### Mesh traffic request path normalization enabled by default + +As of Consul v1.19.3, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. + +## Consul 1.18.x + +### Mesh traffic request path normalization enabled by default + +As of Consul v1.18.5, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. ## Consul 1.17.x @@ -65,6 +74,10 @@ service-defaults are configured in each partition and namespace before upgrading #### ACL tokens with templated policies [ACL templated policies](/consul/docs/security/acl#templated-policies) were added to 1.17.0 to simplify obtaining the right permissions for ACL tokens. When performing a [rolling upgrade](/consul/tutorials/datacenter-operations/upgrade-federated-environment#server-rolling-upgrade) and a version of Consul prior to 1.17.x is presented with a token created Consul v1.17.x or newer that contains templated policies, the templated policies field is not recognized. As a result, the token might not have the expected permissions on the older version of Consul. +### Mesh traffic request path normalization enabled by default + +As of Consul v1.17.8, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. + ## Consul 1.16.x ### Known issues @@ -241,6 +254,10 @@ In Consul v1.15 and higher: +### Mesh traffic request path normalization enabled by default + +As of Consul v1.15.15, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. + ## Consul 1.14.x ### Service Mesh Compatibility From 28b37812b8a415397fe1c51f8e5d44038feae159 Mon Sep 17 00:00:00 2001 From: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:24:19 -0500 Subject: [PATCH 28/97] Suppress CVE-2024-9143 (#21848) Update security-scan.hcl --- .release/security-scan.hcl | 1 + 1 file changed, 1 insertion(+) diff --git a/.release/security-scan.hcl b/.release/security-scan.hcl index 3edf2cac8245..3e9506d79580 100644 --- a/.release/security-scan.hcl +++ b/.release/security-scan.hcl @@ -39,6 +39,7 @@ container { # N.b. `vulnerabilites` is the correct spelling for this tool. vulnerabilites = [ "CVE-2024-8096", # curl@8.9.1-r2, + "CVE-2024-9143", # openssl@3.3.2-r0, ] paths = [ "internal/tools/proto-gen-rpc-glue/e2e/consul/*", From 0ce6730cbe7cb06937a8960ece6d526694ce9734 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Thu, 17 Oct 2024 13:31:22 -0400 Subject: [PATCH 29/97] docs: clarify Envoy and dataplane LTS support policy (#21337) Update matrices and clarify statements as to when Consul expands support to new major versions of Envoy and Consul dataplane in light of Consul LTS or Envoy EOL status. --- .../content/docs/connect/proxies/envoy.mdx | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/website/content/docs/connect/proxies/envoy.mdx b/website/content/docs/connect/proxies/envoy.mdx index 8180787efbeb..7546edc3ae48 100644 --- a/website/content/docs/connect/proxies/envoy.mdx +++ b/website/content/docs/connect/proxies/envoy.mdx @@ -43,10 +43,12 @@ refer to the previous release's version of this page. ### Envoy and Consul Client Agent Every major Consul release initially supports **four major Envoy releases**. -Standard major Consul releases do not expand that support in minor releases. However, [Consul Enterprise Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) -releases do expand their Envoy version compatibility window in minor releases -to ensure compatibility with a maintained Envoy version. +releases expand their Envoy version compatibility window in minor releases to +ensure compatibility with a maintained Envoy version. Standard (non-LTS) Consul +Enterprise releases may also expand support to a new major version of Envoy in +order to receive important security fixes, if the previous major Envoy version +has reached end-of-life. Every major Consul release maintains and tests compatibility with specific Envoy patch releases to ensure users can benefit from bug and security fixes in Envoy. @@ -86,18 +88,18 @@ which packages both Envoy and the `consul-dataplane` binary in a single containe To enable seamless upgrades, each major version of Consul also supports the previous and next Consul dataplane versions. -Compared to standard Consul releases, Consul Enterprise -[Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) -releases have the following differences with Consul dataplane compatibility: -- [Expanded compatibility window](#enterprise-long-term-support-releases): +Compared to community edition releases, Consul Enterprise releases have +the following differences with Consul dataplane compatibility: +- [LTS-Only: Expanded compatibility window](#enterprise-long-term-support-releases): Active Consul Enterprise LTS releases expand their Consul dataplane - version compatibility window until the LTS release reaches its - end of maintenance. + version compatibility window to include the version of Consul dataplane + aligned with the next Consul LTS release. - [Maintained Envoy version](#consul-dataplane-releases-that-span-envoy-major-versions): - Major versions of Consul dataplane aligned with a Consul Enterprise LTS version - may contain minor version updates that use a new major version of Envoy. - These minor version updates are necessary to ensure maintained versions - of Consul dataplane use a maintained version of Envoy. + Major versions of Consul dataplane aligned with a maintained Consul + Enterprise version may contain minor version updates that use a new + major version of Envoy. These minor version updates are necessary to + ensure that maintained versions of Consul dataplane use a maintained + version of Envoy. #### Standard releases @@ -126,16 +128,20 @@ until the LTS release reaches its end of maintenance. #### Consul dataplane releases that span Envoy major versions -Major versions of Consul dataplane aligned with a Consul Enterprise LTS version +Major versions of Consul dataplane aligned with active versions of Consul may contain minor version updates that use a new major version of Envoy. These minor version updates are necessary to ensure maintained versions -of Consul dataplane use a maintained version of Envoy. +of Consul dataplane use a maintained version of Envoy including important +security fixes. -| `consul-dataplane` Version Range | Associated Consul Enterprise LTS version | Contained Envoy Binary Version | +| `consul-dataplane` Version Range | Associated Consul Enterprise version | Contained Envoy Binary Version | | -------------------------------- | ---------------------------------------- | ------------------------------ | | 1.5.0 - 1.5.latest | 1.18.x Ent | Envoy 1.29.x | | 1.4.0 - 1.4.latest | 1.18.x Ent | Envoy 1.28.x | -| 1.1.9 - 1.1.latest | 1.15.x Ent | Envoy 1.26.x | +| 1.2.0 - 1.2.latest | 1.18.x Ent | Envoy 1.27.x | +| 1.2.0 - 1.2.7 | 1.18.x Ent | Envoy 1.27.x | +| 1.1.11 - 1.1.latest | 1.15.x Ent | Envoy 1.27.x | +| 1.1.9 - 1.1.10 | 1.15.x Ent | Envoy 1.26.x | | 1.1.0 - 1.1.8 | 1.15.x Ent | Envoy 1.25.x | ## Getting Started From 77daebd3f8547cb1504171fad66d06bd185ca7d5 Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Thu, 17 Oct 2024 16:35:44 -0400 Subject: [PATCH 30/97] Update compatibility matrix to include 1.20.x (#21843) * Update compatibility matrix to include 1.20.x * Update compatibility.mdx --- website/content/docs/k8s/compatibility.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/website/content/docs/k8s/compatibility.mdx b/website/content/docs/k8s/compatibility.mdx index e3b7ecd743ec..a786ed513ad1 100644 --- a/website/content/docs/k8s/compatibility.mdx +++ b/website/content/docs/k8s/compatibility.mdx @@ -29,6 +29,7 @@ apply to both Consul Enterprise and Consul community edition (CE). | Consul version | Compatible `consul-k8s` versions | Compatible Kubernetes versions | Compatible OpenShift versions | | -------------- | -------------------------------- | -------------------------------| ------------------------------| +| 1.20.x | 1.6.x | 1.28.x - 1.30.x | 4.13.x - 4.15.x | | 1.19.x | 1.5.x | 1.27.x - 1.29.x | 4.13.x - 4.15.x | | 1.18.x CE | 1.4.x | 1.26.x - 1.29.x | 4.13.x - 4.15.x | | 1.17.x | 1.3.x | 1.25.x - 1.28.x | 4.12.x - 4.15.x | From 94ca67463bad7091e8cd42d9e879a4ffa67c272c Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Thu, 17 Oct 2024 17:34:15 -0400 Subject: [PATCH 31/97] Update Envoy compatibility matrices to include consul 1.20.x and dataplane 1.6.x (#21852) * Update Envoy compatibility matrices to include consul 1.20.x and dataplane 1.6.x * Remove non-LTS version from LTS table * Fix incorrect version in dataplane release matrix * Remove releases that don't span versions from the matrix of releases that span versions --- website/content/docs/connect/proxies/envoy.mdx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/website/content/docs/connect/proxies/envoy.mdx b/website/content/docs/connect/proxies/envoy.mdx index 7546edc3ae48..927bac2fcdf8 100644 --- a/website/content/docs/connect/proxies/envoy.mdx +++ b/website/content/docs/connect/proxies/envoy.mdx @@ -108,6 +108,7 @@ apply to both Consul Enterprise and Consul community edition (CE). | Consul Version | Default `consul-dataplane` Version | Other compatible `consul-dataplane` Versions | | -------------- | -------------------------------------|----------------------------------------------| +| 1.20.x CE | 1.6.x (Envoy 1.31.x) | 1.5.x (Envoy 1.29.x) | | 1.19.x CE | 1.5.x (Envoy 1.29.x) | 1.4.x (Envoy 1.28.x) | | 1.18.x CE | 1.4.x (Envoy 1.28.x) | 1.3.x (Envoy 1.27.x) | | 1.17.x | 1.3.x (Envoy 1.27.x) | 1.4.x (Envoy 1.28.x), 1.2.x (Envoy 1.26.x) | @@ -122,7 +123,6 @@ until the LTS release reaches its end of maintenance. | Consul Version | Default `consul-dataplane` Version | Other compatible `consul-dataplane` Versions | | -------------- | -------------------------------------|----------------------------------------------| -| 1.19.x Ent | 1.5.x (Envoy 1.29.x) | 1.4.x (Envoy 1.28.x) | | 1.18.x Ent | 1.4.x (Envoy 1.28.x) | 1.3.x (Envoy 1.27.x) | | 1.15.x Ent | 1.1.x (Envoy 1.26.x) | 1.4.x (Envoy 1.28.x) - 1.0.x (Envoy 1.24.x) | @@ -136,10 +136,6 @@ security fixes. | `consul-dataplane` Version Range | Associated Consul Enterprise version | Contained Envoy Binary Version | | -------------------------------- | ---------------------------------------- | ------------------------------ | -| 1.5.0 - 1.5.latest | 1.18.x Ent | Envoy 1.29.x | -| 1.4.0 - 1.4.latest | 1.18.x Ent | Envoy 1.28.x | -| 1.2.0 - 1.2.latest | 1.18.x Ent | Envoy 1.27.x | -| 1.2.0 - 1.2.7 | 1.18.x Ent | Envoy 1.27.x | | 1.1.11 - 1.1.latest | 1.15.x Ent | Envoy 1.27.x | | 1.1.9 - 1.1.10 | 1.15.x Ent | Envoy 1.26.x | | 1.1.0 - 1.1.8 | 1.15.x Ent | Envoy 1.25.x | From e9dbcedaf3e0518689ed4738241a3e7e65e71e46 Mon Sep 17 00:00:00 2001 From: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:19:53 -0500 Subject: [PATCH 32/97] Upgrade envoy version in nightly integration tests (#21864) Update nightly-test-integrations.yml --- .github/workflows/nightly-test-integrations.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly-test-integrations.yml b/.github/workflows/nightly-test-integrations.yml index cfaa25303062..184937c09396 100644 --- a/.github/workflows/nightly-test-integrations.yml +++ b/.github/workflows/nightly-test-integrations.yml @@ -217,7 +217,7 @@ jobs: # matrix.consul-version (i.e. whenever the highest common Envoy version across active # Consul versions changes). The minor Envoy version does not necessarily need to be # kept current for the purpose of these tests, but the major (1.N) version should be. - ENVOY_VERSION: 1.27.6 + ENVOY_VERSION: 1.28.7 steps: - name: Checkout code uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 From 2618fc1bd9894f97a71e2040516bbe21e3d9fecd Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Mon, 21 Oct 2024 21:58:16 -0400 Subject: [PATCH 33/97] chore: retain retracted api submodule version (#21861) --- api/go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/api/go.mod b/api/go.mod index 715a594dcf47..8df6a0aaa1f5 100644 --- a/api/go.mod +++ b/api/go.mod @@ -5,6 +5,7 @@ go 1.19 replace github.com/hashicorp/consul/sdk => ../sdk retract ( + v1.29.5 // cut from incorrect branch v1.28.0 // tag was mutated v1.27.1 // tag was mutated v1.21.2 // tag was mutated From 40c7f736291652f25bba19fe2809904160eb4178 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Mon, 28 Oct 2024 13:06:28 -0400 Subject: [PATCH 34/97] [NET-1151 NET-11046] docs: clarify request normalization and L7 headers feature availability (#21855) docs: clarify request normalization and L7 headers feature availability - Add notes on feature availability tied to specific fix versions - Add missing 1.20 upgrade entry - Remove erroneous 1.17 upgrade entry (version DNE) - Add missing HCL variant for service intentions config --- website/content/docs/connect/config-entries/mesh.mdx | 2 ++ .../docs/connect/config-entries/service-intentions.mdx | 10 +++++++--- website/content/docs/connect/security.mdx | 2 ++ website/content/docs/upgrading/upgrade-specific.mdx | 10 ++++++---- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/website/content/docs/connect/config-entries/mesh.mdx b/website/content/docs/connect/config-entries/mesh.mdx index b64062e5189f..cf75c4bfa4ab 100644 --- a/website/content/docs/connect/config-entries/mesh.mdx +++ b/website/content/docs/connect/config-entries/mesh.mdx @@ -268,6 +268,8 @@ Note that the Kubernetes example does not include a `partition` field. Configura Enable options under `HTTP.Incoming.RequestNormalization` to apply normalization to all inbound traffic to mesh proxies. +~> **Compatibility warning**: This feature is available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15. We recommend upgrading to the latest version of Consul to take advantage of the latest features and improvements. + ```hcl diff --git a/website/content/docs/connect/config-entries/service-intentions.mdx b/website/content/docs/connect/config-entries/service-intentions.mdx index 4440b2a76c1e..47d980f9a820 100644 --- a/website/content/docs/connect/config-entries/service-intentions.mdx +++ b/website/content/docs/connect/config-entries/service-intentions.mdx @@ -48,7 +48,9 @@ The following outline shows how to format the service intentions configuration e - [`Exact`](#sources-permissions-http-header): string - [`Prefix`](#sources-permissions-http-header): string - [`Suffix`](#sources-permissions-http-header): string - - [`Regex`](#sources-permissions-http-header): string + - [`Contains`](#spec-sources-permissions-http-header): string + - [`Regex`](#spec-sources-permissions-http-header): string + - [`IgnoreCase`](#spec-sources-permissions-http-header): boolean | `false` - [`Invert`](#sources-permissions-http-header): boolean | `false` - [`Precedence`](#sources-precedence): number - [`Type`](#sources-type): string | `consul` @@ -648,7 +650,9 @@ Each member of the `Header` list is a map that contains a `Name` field and at le | `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `Exact` value, Consul applies the permission. Do not specify `Exact` if `Present`, `Prefix`, `Suffix`, or `Regex` are configured in the same `Header` configuration. | string | optional | | `Prefix` | Specifies a prefix value for the header key set in the `Name` field. If the request header value starts with the `Prefix` value, Consul applies the permission. Do not specify `Prefix` if `Present`, `Exact`, `Suffix`, or `Regex` are configured in the same `Header` configuration. | string | optional | | `Suffix` | Specifies a suffix value for the header key set in the `Name` field. If the request header value ends with the `Suffix` value, Consul applies the permission. Do not specify `Suffix` if `Present`, `Exact`, `Prefix`, or `Regex` are configured in the same `Header` configuration. | string | optional | -| `Regex` | Specifies a regular expression pattern as the value for the header key set in the `Name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `Regex` if `Present`, `Exact`, `Prefix`, or `Suffix` are configured in the same `Header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional | +| `Contains` | Specifies a contains value for the header key set in the `Name` field. If the request header value includes the `Contains` value, Consul applies the permission. Do not specify `Contains` if `Present`, `Exact`, `Prefix`, `Suffix`, or `Regex` are configured in the same `header` configuration. | string | optional | +| `Regex` | Specifies a regular expression pattern as the value for the header key set in the `Name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `Regex` if `Present`, `Exact`, `Prefix`, `Suffix`, or `Contains` are configured in the same `Header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional | +| `IgnoreCase` | Ignores the case of the provided header value when matching with `Exact`, `Prefix`, `Suffix`, or `Contains`. Default is `false`. | boolean | optional | | `Invert` | Inverts the matching logic configured in the `Header`. Default is `false`. | boolean | optional | ### `Sources[].Precedence` @@ -964,7 +968,7 @@ Specifies a set of criteria for matching HTTP request headers. The request heade Each member of the `header` list is a map that contains a `name` field and at least one match criterion. -~> **Warning**: If it is possible for a header to contain multiple values, we recommend using `contains` or `regex` rather than `exact`, `prefix`, or `suffix`. Envoy internally concatenates multiple header values into a single CSV value prior to applying match rules, which may result in match rules that depend on the beginning or end of a string vulnerable to circumvention. A more robust alternative is using `contains` or, if a stricter value match is required, configuring a regex pattern that is tolerant of comma-separated values. +~> **Warning**: If it is possible for a header to contain multiple values, we recommend using `contains` or `regex` rather than `exact`, `prefix`, or `suffix`. Envoy internally concatenates multiple header values into a single CSV value prior to applying match rules, which may result in match rules that depend on the beginning or end of a string vulnerable to circumvention. A more robust alternative is using `contains` or, if a stricter value match is required, configuring a regex pattern that is tolerant of comma-separated values. These options are available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15. The following table describes the parameters that each member of the `header` list may contain: diff --git a/website/content/docs/connect/security.mdx b/website/content/docs/connect/security.mdx index a65d4fabcd8f..cefcaa3be21d 100644 --- a/website/content/docs/connect/security.mdx +++ b/website/content/docs/connect/security.mdx @@ -42,6 +42,8 @@ an explicit intention. ### Request Normalization Configured for L7 Intentions +~> **Compatibility warning**: This feature is available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15. We recommend upgrading to the latest version of Consul to take advantage of the latest features and improvements. + Atypical traffic patterns may interfere with the enforcement of L7 intentions. For example, if a service makes request to a non-normalized URI path and Consul is not configured to force path normalization, it becomes possible to circumvent path match rules. While a diff --git a/website/content/docs/upgrading/upgrade-specific.mdx b/website/content/docs/upgrading/upgrade-specific.mdx index c7fec8cb3412..4ff5eb8c3036 100644 --- a/website/content/docs/upgrading/upgrade-specific.mdx +++ b/website/content/docs/upgrading/upgrade-specific.mdx @@ -14,6 +14,12 @@ provided for their upgrades as a result of new features or changed behavior. This page is used to document those details separately from the standard upgrade flow. +## Consul 1.20.x + +### Mesh traffic request path normalization enabled by default + +As of Consul v1.20.1, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. + ## Consul v1.19.x ### Health endpoint status filtering is now processed on the server side when using client agents @@ -74,10 +80,6 @@ service-defaults are configured in each partition and namespace before upgrading #### ACL tokens with templated policies [ACL templated policies](/consul/docs/security/acl#templated-policies) were added to 1.17.0 to simplify obtaining the right permissions for ACL tokens. When performing a [rolling upgrade](/consul/tutorials/datacenter-operations/upgrade-federated-environment#server-rolling-upgrade) and a version of Consul prior to 1.17.x is presented with a token created Consul v1.17.x or newer that contains templated policies, the templated policies field is not recognized. As a result, the token might not have the expected permissions on the older version of Consul. -### Mesh traffic request path normalization enabled by default - -As of Consul v1.17.8, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. - ## Consul 1.16.x ### Known issues From 31aae80389fa954e35c02f34d97c853f54c8c1b7 Mon Sep 17 00:00:00 2001 From: Tom Davies Date: Mon, 28 Oct 2024 19:18:04 +0000 Subject: [PATCH 35/97] Allow multiple endpoints in Envoy clusters configured with hostnames (#21655) * xds: allow multiple endpoints for strict_dns * xds: fixes typo in multi hostname warning --- .changelog/21655.txt | 3 +++ agent/xds/clusters.go | 15 ++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 .changelog/21655.txt diff --git a/.changelog/21655.txt b/.changelog/21655.txt new file mode 100644 index 000000000000..3ef13bdf88fa --- /dev/null +++ b/.changelog/21655.txt @@ -0,0 +1,3 @@ +```release-note:improvement +xds: configures Envoy to load balance over all instances of an external service configured with hostnames when "envoy_dns_discovery_type" is set to "STRICT_DNS" +``` diff --git a/agent/xds/clusters.go b/agent/xds/clusters.go index 1d69f804c7dd..244585dfdf3e 100644 --- a/agent/xds/clusters.go +++ b/agent/xds/clusters.go @@ -1824,13 +1824,15 @@ func configureClusterWithHostnames( cluster.DnsRefreshRate = durationpb.New(rate) cluster.DnsLookupFamily = envoy_cluster_v3.Cluster_V4_ONLY + envoyMaxEndpoints := 1 discoveryType := envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_LOGICAL_DNS} if dnsDiscoveryType == "strict_dns" { discoveryType.Type = envoy_cluster_v3.Cluster_STRICT_DNS + envoyMaxEndpoints = len(hostnameEndpoints) } cluster.ClusterDiscoveryType = &discoveryType - endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, 1) + endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, envoyMaxEndpoints) uniqueHostnames := make(map[string]bool) var ( @@ -1848,12 +1850,15 @@ func configureClusterWithHostnames( continue } - if len(endpoints) == 0 { + if len(endpoints) < envoyMaxEndpoints { endpoints = append(endpoints, makeLbEndpoint(addr, port, health, weight)) hostname = addr idx = i - break + + if len(endpoints) == envoyMaxEndpoints { + break + } } } @@ -1867,8 +1872,8 @@ func configureClusterWithHostnames( endpoints = append(endpoints, fallback) } - if len(uniqueHostnames) > 1 { - logger.Warn(fmt.Sprintf("service contains instances with more than one unique hostname; only %q be resolved by Envoy", hostname), + if len(uniqueHostnames) > 1 && envoyMaxEndpoints == 1 { + logger.Warn(fmt.Sprintf("service contains instances with more than one unique hostname; only %q will be resolved by Envoy", hostname), "dc", dc, "service", service.String()) } From 6351a821aa171fddfab01776cce199d62aa6d5e2 Mon Sep 17 00:00:00 2001 From: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> Date: Tue, 29 Oct 2024 09:53:41 -0700 Subject: [PATCH 36/97] docs: add missing slash in redirect (#21881) missing slash --- website/redirects.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/redirects.js b/website/redirects.js index 536a11abadf2..605a830f9fed 100644 --- a/website/redirects.js +++ b/website/redirects.js @@ -238,7 +238,7 @@ module.exports = [ permanent: true, }, { - source: 'consul/docs/architecture/v2/:slug*', + source: '/consul/docs/architecture/v2/:slug*', destination: '/consul/docs/architecture/catalog#v2-catalog', permanent: true, }, From 59447e95797697160804707d9e0e5a6fa31f85ad Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 30 Oct 2024 17:03:25 -0400 Subject: [PATCH 37/97] Update changelog (#21896) --- CHANGELOG.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 675b8d5bf572..69978221dea0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## 1.20.1 (October 29, 2024) +BREAKING CHANGES: + +* mesh: Enable Envoy `HttpConnectionManager.normalize_path` by default on inbound traffic to mesh proxies. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005). [[GH-21816](https://github.com/hashicorp/consul/issues/21816)] + +SECURITY: + +* mesh: Add `contains` and `ignoreCase` to L7 Intentions HTTP header matching criteria to support configuration resilient to variable casing and multiple values. This resolves [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). [[GH-21816](https://github.com/hashicorp/consul/issues/21816)] +* mesh: Add `http.incoming.requestNormalization` to Mesh configuration entry to support inbound service traffic request normalization. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005) and [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). [[GH-21816](https://github.com/hashicorp/consul/issues/21816)] + +IMPROVEMENTS: + +* api: remove dependency on proto-public, protobuf, and grpc [[GH-21780](https://github.com/hashicorp/consul/issues/21780)] +* snapshot agent: **(Enterprise only)** Implement Service Principal Auth for snapshot agent on azure. +* xds: configures Envoy to load balance over all instances of an external service configured with hostnames when "envoy_dns_discovery_type" is set to "STRICT_DNS" [[GH-21655](https://github.com/hashicorp/consul/issues/21655)] + ## 1.20.0 (October 14, 2024) SECURITY: @@ -59,6 +75,38 @@ BUG FIXES: * jwt-provider: change dns lookup family from the default of AUTO which would prefer ipv6 to ALL if LOGICAL_DNS is used or PREFER_IPV4 if STRICT_DNS is used to gracefully handle transitions to ipv6. [[GH-21703](https://github.com/hashicorp/consul/issues/21703)] +## 1.19.3 Enterprise (October 29, 2024) +BREAKING CHANGES: + +* mesh: **(Enterprise Only)** Enable Envoy `HttpConnectionManager.normalize_path` by default on inbound traffic to mesh proxies. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005). + +SECURITY: + +* Explicitly set 'Content-Type' header to mitigate XSS vulnerability. [[GH-21704](https://github.com/hashicorp/consul/issues/21704)] +* Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. [[GH-21711](https://github.com/hashicorp/consul/issues/21711)] +* UI: Remove codemirror linting due to package dependency [[GH-21726](https://github.com/hashicorp/consul/issues/21726)] +* Upgrade Go to use 1.22.7. This addresses CVE +[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] +* Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs +[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and +[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] +* mesh: **(Enterprise Only)** Add `contains` and `ignoreCase` to L7 Intentions HTTP header matching criteria to support configuration resilient to variable casing and multiple values. This resolves [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +* mesh: **(Enterprise Only)** Add `http.incoming.requestNormalization` to Mesh configuration entry to support inbound service traffic request normalization. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005) and [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +* ui: Pin a newer resolution of Braces [[GH-21710](https://github.com/hashicorp/consul/issues/21710)] +* ui: Pin a newer resolution of Codemirror [[GH-21715](https://github.com/hashicorp/consul/issues/21715)] +* ui: Pin a newer resolution of Markdown-it [[GH-21717](https://github.com/hashicorp/consul/issues/21717)] +* ui: Pin a newer resolution of ansi-html [[GH-21735](https://github.com/hashicorp/consul/issues/21735)] + +IMPROVEMENTS: + +* security: upgrade ubi base image to 9.4 [[GH-21750](https://github.com/hashicorp/consul/issues/21750)] +* api: remove dependency on proto-public, protobuf, and grpc [[GH-21780](https://github.com/hashicorp/consul/issues/21780)] +* xds: configures Envoy to load balance over all instances of an external service configured with hostnames when "envoy_dns_discovery_type" is set to "STRICT_DNS" [[GH-21655](https://github.com/hashicorp/consul/issues/21655)] + +BUG FIXES: + +* jwt-provider: change dns lookup family from the default of AUTO which would prefer ipv6 to ALL if LOGICAL_DNS is used or PREFER_IPV4 if STRICT_DNS is used to gracefully handle transitions to ipv6. [[GH-21703](https://github.com/hashicorp/consul/issues/21703)] + ## 1.19.2 (August 26, 2024) SECURITY: @@ -73,6 +121,39 @@ BUG FIXES: * api-gateway: **(Enterprise only)** ensure clusters are properly created for JWT providers with a remote URI for the JWKS endpoint [[GH-21604](https://github.com/hashicorp/consul/issues/21604)] +## 1.18.5 Enterprise (October 29, 2024) + +Enterprise LTS: Consul Enterprise 1.18 is a Long-Term Support (LTS) release. +BREAKING CHANGES: + +* mesh: **(Enterprise Only)** Enable Envoy `HttpConnectionManager.normalize_path` by default on inbound traffic to mesh proxies. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005). + +SECURITY: + +* Explicitly set 'Content-Type' header to mitigate XSS vulnerability. [[GH-21704](https://github.com/hashicorp/consul/issues/21704)] +* Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. [[GH-21711](https://github.com/hashicorp/consul/issues/21711)] +* Upgrade Go to use 1.22.7. This addresses CVE +[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] +* Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs +[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and +[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] +* mesh: **(Enterprise Only)** Add `contains` and `ignoreCase` to L7 Intentions HTTP header matching criteria to support configuration resilient to variable casing and multiple values. This resolves [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +* mesh: **(Enterprise Only)** Add `http.incoming.requestNormalization` to Mesh configuration entry to support inbound service traffic request normalization. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005) and [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +* ui: Pin a newer resolution of Braces [[GH-21710](https://github.com/hashicorp/consul/issues/21710)] +* ui: Pin a newer resolution of Codemirror [[GH-21715](https://github.com/hashicorp/consul/issues/21715)] +* ui: Pin a newer resolution of Markdown-it [[GH-21717](https://github.com/hashicorp/consul/issues/21717)] +* ui: Pin a newer resolution of ansi-html [[GH-21735](https://github.com/hashicorp/consul/issues/21735)] + +IMPROVEMENTS: + +* security: upgrade ubi base image to 9.4 [[GH-21750](https://github.com/hashicorp/consul/issues/21750)] +* api: remove dependency on proto-public, protobuf, and grpc [[GH-21780](https://github.com/hashicorp/consul/issues/21780)] +* xds: configures Envoy to load balance over all instances of an external service configured with hostnames when "envoy_dns_discovery_type" is set to "STRICT_DNS" [[GH-21655](https://github.com/hashicorp/consul/issues/21655)] + +BUG FIXES: + +* jwt-provider: change dns lookup family from the default of AUTO which would prefer ipv6 to ALL if LOGICAL_DNS is used or PREFER_IPV4 if STRICT_DNS is used to gracefully handle transitions to ipv6. [[GH-21703](https://github.com/hashicorp/consul/issues/21703)] + ## 1.18.4 Enterprise (August 26, 2024) Enterprise LTS: Consul Enterprise 1.18 is a Long-Term Support (LTS) release. @@ -93,6 +174,35 @@ IMPROVEMENTS: * Use Envoy's default for a route's validate_clusters option, which is false. This fixes a case where non-existent clusters could cause a route to no longer route to any of its backends, including existing ones. [[GH-21587](https://github.com/hashicorp/consul/issues/21587)] +## 1.15.15 Enterprise (October 29, 2024) + +Enterprise LTS: Consul Enterprise 1.15 is a Long-Term Support (LTS) release. +BREAKING CHANGES: + +* mesh: **(Enterprise Only)** Enable Envoy `HttpConnectionManager.normalize_path` by default on inbound traffic to mesh proxies. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005). + +SECURITY: + +* Explicitly set 'Content-Type' header to mitigate XSS vulnerability. [[GH-21704](https://github.com/hashicorp/consul/issues/21704)] +* Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. [[GH-21711](https://github.com/hashicorp/consul/issues/21711)] +* UI: Remove codemirror linting due to package dependency [[GH-21726](https://github.com/hashicorp/consul/issues/21726)] +* Upgrade Go to use 1.22.7. This addresses CVE +[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] +* Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs +[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and +[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] +* mesh: **(Enterprise Only)** Add `contains` and `ignoreCase` to L7 Intentions HTTP header matching criteria to support configuration resilient to variable casing and multiple values. This resolves [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +* mesh: **(Enterprise Only)** Add `http.incoming.requestNormalization` to Mesh configuration entry to support inbound service traffic request normalization. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005) and [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +* ui: Pin a newer resolution of Braces [[GH-21710](https://github.com/hashicorp/consul/issues/21710)] +* ui: Pin a newer resolution of Codemirror [[GH-21715](https://github.com/hashicorp/consul/issues/21715)] +* ui: Pin a newer resolution of Markdown-it [[GH-21717](https://github.com/hashicorp/consul/issues/21717)] +* ui: Pin a newer resolution of ansi-html [[GH-21735](https://github.com/hashicorp/consul/issues/21735)] + +IMPROVEMENTS: + +* security: upgrade ubi base image to 9.4 [[GH-21750](https://github.com/hashicorp/consul/issues/21750)] +* xds: configures Envoy to load balance over all instances of an external service configured with hostnames when "envoy_dns_discovery_type" is set to "STRICT_DNS" [[GH-21655](https://github.com/hashicorp/consul/issues/21655)] + ## 1.15.14 Enterprise (August 26, 2024) Enterprise LTS: Consul Enterprise 1.15 is a Long-Term Support (LTS) release. From 1dfc265abe20b202bd90cf3946020a1587717667 Mon Sep 17 00:00:00 2001 From: Deniz Onur Duzgun <59659739+dduzgun-security@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:52:01 -0500 Subject: [PATCH 38/97] ci(security-scanner): add support for Red Hat UBI images and fix typo (#21912) * ci(security-scanner): add support for Red Hat UBI images and fix typo * hclfmt * clean-up comments Co-authored-by: Kent Gruber --------- Co-authored-by: Kent Gruber --- .release/security-scan.hcl | 8 +++----- scan.hcl | 3 +-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.release/security-scan.hcl b/.release/security-scan.hcl index 3e9506d79580..20c105f3b41f 100644 --- a/.release/security-scan.hcl +++ b/.release/security-scan.hcl @@ -14,7 +14,7 @@ container { dependencies = true - alpine_secdb = true + osv = true secrets { matchers { @@ -36,8 +36,7 @@ container { # periodically cleaned up to remove items that are no longer found by the scanner. triage { suppress { - # N.b. `vulnerabilites` is the correct spelling for this tool. - vulnerabilites = [ + vulnerabilities = [ "CVE-2024-8096", # curl@8.9.1-r2, "CVE-2024-9143", # openssl@3.3.2-r0, ] @@ -79,8 +78,7 @@ binary { # periodically cleaned up to remove items that are no longer found by the scanner. triage { suppress { - # N.b. `vulnerabilites` is the correct spelling for this tool. - vulnerabilites = [ + vulnerabilities = [ ] paths = [ "internal/tools/proto-gen-rpc-glue/e2e/consul/*", diff --git a/scan.hcl b/scan.hcl index 0da769efb473..f67bb4b24e1c 100644 --- a/scan.hcl +++ b/scan.hcl @@ -28,8 +28,7 @@ repository { # periodically cleaned up to remove items that are no longer found by the scanner. triage { suppress { - # N.b. `vulnerabilites` is the correct spelling for this tool. - vulnerabilites = [ + vulnerabilities = [ ] paths = [ "internal/tools/proto-gen-rpc-glue/e2e/consul/*", From f376b6a22714871d43f126d320a5332f6989577d Mon Sep 17 00:00:00 2001 From: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> Date: Tue, 5 Nov 2024 04:59:52 -0800 Subject: [PATCH 39/97] Docs/CE-749-remove-references-from-consul (#21914) * delete HCP Consul Central references * Path correction * missed listing * Nav update --- website/content/api-docs/api-structure.mdx | 5 - website/content/api-docs/hcp-link.mdx | 190 ------------------ website/content/api-docs/index.mdx | 1 - .../docs/connect/cluster-peering/index.mdx | 7 - .../usage/create-sameness-groups.mdx | 2 - .../usage/establish-cluster-peering.mdx | 2 +- .../content/docs/connect/dataplane/index.mdx | 2 +- .../usage/create-sameness-groups.mdx | 2 - website/content/docs/k8s/helm.mdx | 86 -------- website/data/api-docs-nav-data.json | 4 - website/redirects.js | 7 +- 11 files changed, 8 insertions(+), 300 deletions(-) delete mode 100644 website/content/api-docs/hcp-link.mdx diff --git a/website/content/api-docs/api-structure.mdx b/website/content/api-docs/api-structure.mdx index 32a8a2c17c49..edfbcf32589e 100644 --- a/website/content/api-docs/api-structure.mdx +++ b/website/content/api-docs/api-structure.mdx @@ -159,8 +159,3 @@ UUID-format identifiers generated by the Consul API use the These UUID-format strings are generated using high quality, purely random bytes. It is not intended to be RFC compliant, merely to use a well-understood string representation of a 128-bit value. - -## CORS HTTP Response Headers - -As of Consul 1.18, Consul adds an HTTP header `Access-Control-Expose-Headers: x-consul-default-acl-policy` to -all responses in order to support linking self-managed Enterprise clusters to HCP Consul Central. diff --git a/website/content/api-docs/hcp-link.mdx b/website/content/api-docs/hcp-link.mdx deleted file mode 100644 index 7f543066912b..000000000000 --- a/website/content/api-docs/hcp-link.mdx +++ /dev/null @@ -1,190 +0,0 @@ ---- -layout: api -page_title: HCP Linking HTTP API -description: The Link resource allows for linking your cluster to HCP Consul Central. ---- - -# Link HTTP API - --> **1.18.0+:** The Link API is available in Consul versions 1.18.0 and newer. - --> **Note:** This endpoint does not use the `/v1/` prefix. - -The `/api/hcp/v2/link/global` endpoint allows you to link your Consul cluster to [HCP Consul Central](/hcp/docs/consul/concepts/consul-central). - -## Establish or update link to HCP Consul Central - -This endpoint creates or updates a Link, which establishes a connection with HCP Consul Central. - -| Method | Path | Produces | -| ------ | ----------------------------- | ------------------ | -| `PUT` | `/api/hcp/v2/link/global` | `application/json` | - -The table below shows this endpoint's support for -[blocking queries](/consul/api-docs/features/blocking), -[consistency modes](/consul/api-docs/features/consistency), -[agent caching](/consul/api-docs/features/caching), and -[required ACLs](/consul/api-docs/api-structure#authentication). - -| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | -| ---------------- | --------------------- | ------------- | ------------------------------ | -| `NO` | `stale`, `consistent` | `none` | `operator:write`, `acl:write` | - -### Link API vs. configuration-based linking - -The Link API described here is an alternative method to accomplish the same thing as [configuration-based linking](/consul/docs/agent/config/config-files#self-managed-hcp-parameters). You should generally only choose one method or the other for linking your cluster, not both. If you do use both methods, they interact in the following ways: - -* When Consul is started, values set in the `cloud` configuration will take precedence over what was previously set by the API or CLI. -* Clusters can only be unlinked from HCP Consul Central by the API or CLI, regardless of if they were established via configuration, API, or CLI. - -### JSON Request Body Schema - -- `data` `(object: )` - - - `resourceId` `(string: )` - The ID of the HCP Consul Central cluster to link to. Has the format of: - `organization//project//hashicorp.consul.global-network-manager.cluster/` - - - `clientId` `(string: )` - The ID used to authenticate to HCP, which is returned as part of the HCP - Consul Central cluster creation. It can also be obtained by fetching the HCP Consul Central cluster secrets. - - - `clientSecret` `(string: )` - The secret used to authenticate to HCP, which is returned as part of the - HCP Consul Central cluster creation. It can also be obtained by fetching the HCP Consul Central cluster secrets. - -### Sample Payload - -```json -{ - "data": { - "resourceId": "organization/c0bf7aac-7690-4905-a8aa-889df1510314/project/6e82a47b-79af-4920-ad42-c0f74421ab52/hashicorp.consul.global-network-manager.cluster/my-cluster", - "clientId": "3jz6zk2tlr802htzwquczlxlsrohlpm5", - "clientSecret": "07ywcvaqmg1f8ko9eq4julep2tfglnv4o18rz3py9dik4ywox0ytoscycn39o4vs" - } -} -``` - -### Sample Request - -```shell-session -$ curl --request PUT \ - --header "X-Consul-Token: 9cdjse6c-2dia-3720-81fe-5dae3k714a6e" \ - --data @payload.json \ - http://127.0.0.1:8500/api/hcp/v2/link/global -``` - -### Sample Response - -```json -{ - "data": { - "clientId": "3jz6zk2tlr802htzwquczlxlsrohlpm5", - "clientSecret": "07ywcvaqmg1f8ko9eq4julep2tfglnv4o18rz3py9dik4ywox0ytoscycn39o4vs", - "resourceId": "organization/c0bf7aac-7690-4905-a8aa-889df1510314/project/6e82a47b-79af-4920-ad42-c0f74421ab52/hashicorp.consul.global-network-manager.cluster/my-cluster" - }, - "generation": "01HMHTHZND8VJDXHHJBKDR4TTA", - "id": { - "name": "global", - "tenancy": { - "peerName": "local" - }, - "type": { - "group": "hcp", - "groupVersion": "v2", - "kind": "Link" - }, - "uid": "01HMHTHZND8VJDXHHJBGY1KG0F" - }, - "version": "60" -} -``` - -## Read Link - -This endpoint reads a Link so you can view information about your cluster's current linking status. - -| Method | Path | Produces | -| ------ | ----------------------------- | ------------------ | -| `GET` | `/api/hcp/v2/link/global` | `application/json` | - -The table below shows this endpoint's support for -[blocking queries](/consul/api-docs/features/blocking), -[consistency modes](/consul/api-docs/features/consistency), -[agent caching](/consul/api-docs/features/caching), and -[required ACLs](/consul/api-docs/api-structure#authentication). - -| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | -| ---------------- | --------------------- | ------------- | ---------------- | -| `NO` | `stale`, `consistent` | `none` | `operator:read` | - -### Sample Request - -```shell-session -$ curl --header "X-Consul-Token: 5cdcae6c-0cce-4210-86fe-5dff3b984a6e" \ - http://127.0.0.1:8500/api/hcp/v2/link/global -``` - -### Sample Response -```json -{ - "data": { - "accessLevel": "ACCESS_LEVEL_GLOBAL_READ_WRITE", - "clientId": "3jz6zk2tlr802htzwquczlxlsrohlpm5", - "clientSecret": "07ywcvaqmg1f8ko9eq4julep2tfglnv4o18rz3py9dik4ywox0ytoscycn39o4vs", - "hcpClusterUrl": "https://portal.cloud.hashicorp.com/services/consul/clusters/self-managed/my-cluster?project_id=6e82a47b-79af-4920-ad42-c0f74421ab52", - "resourceId": "organization/c0bf7aac-7690-4905-a8aa-889df1510314/project/6e82a47b-79af-4920-ad42-c0f74421ab52/hashicorp.consul.global-network-manager.cluster/my-cluster" - }, - "generation": "01HMHTF4K5V27T91FMVHGFE87F", - "id": { - "name": "global", - "tenancy": { - "peerName": "local" - }, - "type": { - "group": "hcp", - "groupVersion": "v2", - "kind": "Link" - }, - "uid": "01HMHS7DJ9FEQH5XK1VD0W0536" - }, - "status": { - "consul.io/hcp/link": { - "conditions": [ - { - "message": "Successfully linked to cluster 'organization/c0bf7aac-7690-4905-a8aa-889df1510314/project/6e82a47b-79af-4920-ad42-c0f74421ab52/hashicorp.consul.global-network-manager.cluster/my-cluster'", - "reason": "SUCCESS", - "state": "STATE_TRUE", - "type": "linked" - } - ], - "observedGeneration": "01HMHS7DN1C417JXJF7DBVS79F", - "updatedAt": "2024-01-19T21:14:59.707744Z" - } - }, - "version": "53" -} -``` - -## Delete Link - -This endpoint deletes a Link, which removes the cluster's connection with HCP Consul Central. - -| Method | Path | Produces | -| --------- | ----------------------------- | ------------------ | -| `DELETE` | `/api/hcp/v2/link/global` | `application/json` | - -The table below shows this endpoint's support for -[blocking queries](/consul/api-docs/features/blocking), -[consistency modes](/consul/api-docs/features/consistency), -[agent caching](/consul/api-docs/features/caching), and -[required ACLs](/consul/api-docs/api-structure#authentication). - -| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | -| ---------------- | ---------------------- | ------------- | -------------------------------- | -| `NO` | `stale`, `consistent` | `none` | `operator:write`, `acl:write` | - -### Sample Request - -```shell-session -$ curl --request DELETE \ - --header "X-Consul-Token: 5cdcae6c-0cce-4210-86fe-5dff3b984a6e" \ - http://127.0.0.1:8500/api/hcp/v2/link/global -``` diff --git a/website/content/api-docs/index.mdx b/website/content/api-docs/index.mdx index 1b972e442523..20d0021e30cd 100644 --- a/website/content/api-docs/index.mdx +++ b/website/content/api-docs/index.mdx @@ -49,7 +49,6 @@ The following API endpoints help you manage Consul operations. - [`/namespace`](/consul/api-docs/namespaces): Create and manage namespaces in Consul. Namespaces isolate groups of resources to lower operational overhead. - [`/snapshot`](/consul/api-docs/snapshot): Save and restore Consul server state in the event of a disaster. - [`/txn`](/consul/api-docs/txn): Apply multiple operations, such as updating the catalog and retrieving multiple KV entries, in a single transaction. -- [`/api/hcp/v2/link/global`](/consul/api-docs/hcp-link): Link cluster to [HCP Consul Central](/hcp/docs/consul/concepts/consul-central). HCP Consul Central is a management plane service hosted by HashiCorp that enables you to monitor and manage Consul clusters. ## Configure your services dynamically diff --git a/website/content/docs/connect/cluster-peering/index.mdx b/website/content/docs/connect/cluster-peering/index.mdx index 2aa5147235f3..83cc4b97e4c4 100644 --- a/website/content/docs/connect/cluster-peering/index.mdx +++ b/website/content/docs/connect/cluster-peering/index.mdx @@ -70,13 +70,6 @@ The following resources are available to help you use Consul's cluster peering f - [Manage L7 traffic with cluster peering on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/l7-traffic) - [Create sameness groups on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/create-sameness-groups) -### HCP Consul Central documentation - -- [Cluster peering](/hcp/docs/consul/usage/cluster-peering) -- [Cluster peering topologies](/hcp/docs/consul/usage/cluster-peering/topologies) -- [Establish cluster peering connections on HCP Consul Central](/hcp/docs/consul/usage/cluster-peering/create-connections) -- [Cluster peering with HCP Consul Central](/hcp/docs/extend/cluster-peering/establish) - ### Reference documentation - [Cluster peering technical specifications](/consul/docs/connect/cluster-peering/tech-specs) diff --git a/website/content/docs/connect/cluster-peering/usage/create-sameness-groups.mdx b/website/content/docs/connect/cluster-peering/usage/create-sameness-groups.mdx index 49b814177799..71537355eb90 100644 --- a/website/content/docs/connect/cluster-peering/usage/create-sameness-groups.mdx +++ b/website/content/docs/connect/cluster-peering/usage/create-sameness-groups.mdx @@ -43,8 +43,6 @@ Mesh gateways are required for cluster peering connections and recommended to se You must establish connections with cluster peers before you can create a sameness group that includes them. A cluster peering connection exists between two admin partitions in different datacenters, and each connection between two partitions must be established separately with each peer. Refer to [establish cluster peering connections](/consul/docs/connect/cluster-peering/usage/establish-cluster-peering) for step-by-step instructions. -You can establish and manage cluster peering relationships between all of your self-managed clusters using [HCP Consul Central](/hcp/docs/consul/concepts/consul-central). For more information, refer to [cluster peering global view](/hcp/docs/consul/monitor/consul-central/global-views#cluster-peering) in the HCP documentation. - To establish cluster peering connections and define a group as part of the same workflow, follow instructions up to [Export services between clusters](/consul/docs/connect/cluster-peering/usage/establish-cluster-peering#export-services-between-clusters). You can use the same exported services and service intention configuration entries to establish the cluster peering connection and create the sameness group. ## Create a sameness group diff --git a/website/content/docs/connect/cluster-peering/usage/establish-cluster-peering.mdx b/website/content/docs/connect/cluster-peering/usage/establish-cluster-peering.mdx index 4e0128bb3e68..b2ed30f46058 100644 --- a/website/content/docs/connect/cluster-peering/usage/establish-cluster-peering.mdx +++ b/website/content/docs/connect/cluster-peering/usage/establish-cluster-peering.mdx @@ -16,7 +16,7 @@ This page details the process for establishing a cluster peering connection betw Cluster peering between services cannot be established until all four steps are complete. If you want to establish cluster peering connections and create sameness groups at the same time, refer to the guidance in [create sameness groups](/consul/docs/connect/cluster-peering/usage/create-sameness-groups). -For Kubernetes guidance, refer to [Establish cluster peering connections on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering). For HCP Consul Central guidance, refer to [Establish cluster peering connections on HCP Consul Central](/hcp/docs/consul/usage/cluster-peering/create-connections). +For Kubernetes guidance, refer to [Establish cluster peering connections on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering). ## Requirements diff --git a/website/content/docs/connect/dataplane/index.mdx b/website/content/docs/connect/dataplane/index.mdx index 30996e347674..2f16014cac60 100644 --- a/website/content/docs/connect/dataplane/index.mdx +++ b/website/content/docs/connect/dataplane/index.mdx @@ -121,7 +121,7 @@ Consul Dataplane on Kubernetes supports the following features: - Running Consul service mesh in AWS Fargate and GKE Autopilot is supported. - xDS load balancing is supported. - Servers running in Kubernetes and servers external to Kubernetes are both supported. -- HCP Consul Dedicated and HCP Consul Central are supported. +- HCP Consul Dedicated is supported. - Consul API Gateway Consul Dataplane on ECS support the following features: diff --git a/website/content/docs/k8s/connect/cluster-peering/usage/create-sameness-groups.mdx b/website/content/docs/k8s/connect/cluster-peering/usage/create-sameness-groups.mdx index 0b3f1d43c29c..2674805e166c 100644 --- a/website/content/docs/k8s/connect/cluster-peering/usage/create-sameness-groups.mdx +++ b/website/content/docs/k8s/connect/cluster-peering/usage/create-sameness-groups.mdx @@ -43,8 +43,6 @@ Mesh gateways are required for cluster peering connections and recommended to se You must establish connections with cluster peers before you can create a sameness group that includes them. A cluster peering connection exists between two admin partitions in different datacenters, and each connection between two partitions must be established separately with each peer. Refer to [establish cluster peering connections](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering) for step-by-step instructions. -You can establish and manage cluster peering relationships between all of your self-managed clusters using [HCP Consul Central](/hcp/docs/consul/concepts/consul-central). For more information, refer to [cluster peering global view](/hcp/docs/consul/monitor/consul-central/global-views#cluster-peering) in the HCP documentation. - To establish cluster peering connections and define a group as part of the same workflow, follow instructions up to [Export services between clusters](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering#export-services-between-clusters). You can use the same exported services and service intention configuration entries to establish the cluster peering connection and create the sameness group. ## Create a sameness group diff --git a/website/content/docs/k8s/helm.mdx b/website/content/docs/k8s/helm.mdx index 42635dc2ca41..9315109464f0 100644 --- a/website/content/docs/k8s/helm.mdx +++ b/website/content/docs/k8s/helm.mdx @@ -689,58 +689,6 @@ Use these links to navigate to a particular top-level stanza. - `consulAPITimeout` ((#v-global-consulapitimeout)) (`string: 5s`) - The time in seconds that the consul API client will wait for a response from the API before cancelling the request. - - `cloud` ((#v-global-cloud)) - Enables installing an HCP Consul Central self-managed cluster. - Requires Consul v1.14+. - - - `enabled` ((#v-global-cloud-enabled)) (`boolean: false`) - If true, the Helm chart will link a [self-managed cluster to HCP](/hcp/docs/consul/self-managed). - This can either be used to [configure a new cluster](/hcp/docs/consul/self-managed/new) - or [link an existing one](/hcp/docs/consul/self-managed/existing). - - Note: this setting should not be enabled for [HCP Consul Dedicated clusters](/hcp/docs/consul/dedicated). - It is strictly for linking self-managed clusters. - - - `resourceId` ((#v-global-cloud-resourceid)) - The resource id of the HCP Consul Central cluster to link to. Eg: - organization/27109cd4-a309-4bf3-9986-e1d071914b18/project/fcef6c24-259d-4510-bb8d-1d812e120e34/hashicorp.consul.global-network-manager.cluster/consul-cluster - This is required when global.cloud.enabled is true. - - - `secretName` ((#v-global-cloud-resourceid-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the resource id. - - - `secretKey` ((#v-global-cloud-resourceid-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the resource id. - - - `clientId` ((#v-global-cloud-clientid)) - The client id portion of a [service principal](/hcp/docs/hcp/admin/iam/service-principals#service-principals) with authorization to link the cluster - in global.cloud.resourceId to HCP Consul Central. - This is required when global.cloud.enabled is true. - - - `secretName` ((#v-global-cloud-clientid-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the client id. - - - `secretKey` ((#v-global-cloud-clientid-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the client id. - - - `clientSecret` ((#v-global-cloud-clientsecret)) - The client secret portion of a [service principal](/hcp/docs/hcp/admin/iam/service-principals#service-principals) with authorization to link the cluster - in global.cloud.resourceId to HCP Consul Central. - This is required when global.cloud.enabled is true. - - - `secretName` ((#v-global-cloud-clientsecret-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the client secret. - - - `secretKey` ((#v-global-cloud-clientsecret-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the client secret. - - - `apiHost` ((#v-global-cloud-apihost)) - The hostname of HCP's API. This setting is used for internal testing and validation. - - - `secretName` ((#v-global-cloud-apihost-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the api hostname. - - - `secretKey` ((#v-global-cloud-apihost-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the api hostname. - - - `authUrl` ((#v-global-cloud-authurl)) - The URL of HCP's auth API. This setting is used for internal testing and validation. - - - `secretName` ((#v-global-cloud-authurl-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the authorization url. - - - `secretKey` ((#v-global-cloud-authurl-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the authorization url. - - - `scadaAddress` ((#v-global-cloud-scadaaddress)) - The address of HCP's scada service. This setting is used for internal testing and validation. - - - `secretName` ((#v-global-cloud-scadaaddress-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the scada address. - - - `secretKey` ((#v-global-cloud-scadaaddress-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the scada address. - - `extraLabels` ((#v-global-extralabels)) (`map`) - Extra labels to attach to all pods, deployments, daemonsets, statefulsets, and jobs. This should be a YAML map. Example: @@ -2843,40 +2791,6 @@ Use these links to navigate to a particular top-level stanza. "sample/annotation2": "bar" ``` - - `cloud` ((#v-telemetrycollector-cloud)) - - - `resourceId` ((#v-telemetrycollector-cloud-resourceid)) - The resource id of the HCP Consul Central cluster to push metrics for. Eg: - `organization/27109cd4-a309-4bf3-9986-e1d071914b18/project/fcef6c24-259d-4510-bb8d-1d812e120e34/hashicorp.consul.global-network-manager.cluster/consul-cluster` - - This is used for HCP Consul Central-linked or HCP Consul Dedicated clusters where global.cloud.resourceId is unset. For example, when using externalServers - with HCP Consul Dedicated clusters or HCP Consul Central-linked clusters in a different admin partition. - - If global.cloud.resourceId is set, this should either be unset (defaulting to global.cloud.resourceId) or be the same as global.cloud.resourceId. - - - `secretName` ((#v-telemetrycollector-cloud-resourceid-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the resource id. - - - `secretKey` ((#v-telemetrycollector-cloud-resourceid-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the resource id. - - - `clientId` ((#v-telemetrycollector-cloud-clientid)) - The client id portion of a [service principal](/hcp/docs/hcp/admin/iam/service-principals#service-principals) with authorization to push metrics to HCP - - This is set in two scenarios: - - the service principal in global.cloud is unset - - the HCP UI provides a service principal with more narrowly scoped permissions that the service principal used in global.cloud - - - `secretName` ((#v-telemetrycollector-cloud-clientid-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the client id. - - - `secretKey` ((#v-telemetrycollector-cloud-clientid-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the client id. - - - `clientSecret` ((#v-telemetrycollector-cloud-clientsecret)) - The client secret portion of a [service principal](/hcp/docs/hcp/admin/iam/service-principals#service-principals) with authorization to push metrics to HCP. - - This is set in two scenarios: - - the service principal in global.cloud is unset - - the HCP UI provides a service principal with more narrowly scoped permissions that the service principal used in global.cloud - - - `secretName` ((#v-telemetrycollector-cloud-clientsecret-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the client secret. - - - `secretKey` ((#v-telemetrycollector-cloud-clientsecret-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the client secret. - - `initContainer` ((#v-telemetrycollector-initcontainer)) - `resources` ((#v-telemetrycollector-initcontainer-resources)) (`map`) - The resource settings for consul-telemetry-collector initContainer. diff --git a/website/data/api-docs-nav-data.json b/website/data/api-docs-nav-data.json index 9f86aa6e9b07..d55357310574 100644 --- a/website/data/api-docs-nav-data.json +++ b/website/data/api-docs-nav-data.json @@ -135,10 +135,6 @@ "title": "Exported Services", "path": "exported-services" }, - { - "title": "HCP Consul Central Link", - "path": "hcp-link" - }, { "title": "Health", "path": "health" diff --git a/website/redirects.js b/website/redirects.js index 605a830f9fed..57590f802528 100644 --- a/website/redirects.js +++ b/website/redirects.js @@ -256,5 +256,10 @@ module.exports = [ source: '/consul/docs/:version(v1\.(?:11|12|13|14|15|16|17|18)\.x)/k8s/dns/enable', destination: '/consul/docs/:version/k8s/dns', permanent: true, - } + }, + { + source: '/consul/api-docs/hcp-link', + destination: '/hcp/docs/consul/concepts/consul-central', + permanent: true, + }, ] From 32515c77f28dd1dcb0e6f010a36a523a29ea6ec3 Mon Sep 17 00:00:00 2001 From: Yasmin Lorin Kaygalak Date: Tue, 5 Nov 2024 10:06:29 -0500 Subject: [PATCH 40/97] Added the docs for all the grafana dashboards. (#21795) * Added the docs for all the grafana dashboards. Author: Yasmin Lorin Kaygalak Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> Co-authored-by: Blake Covarrubias --- .changelog/21795.txt | 3 + .../consuldataplanedashboard.mdx | 133 +++++++++++++ .../grafanadashboards/consulk8sdashboard.mdx | 128 ++++++++++++ .../consulserverdashboard.mdx | 164 ++++++++++++++++ .../observability/grafanadashboards/index.mdx | 91 +++++++++ .../service-to-servicedashboard.mdx | 183 ++++++++++++++++++ .../grafanadashboards/servicedashboard.mdx | 157 +++++++++++++++ website/data/docs-nav-data.json | 31 ++- .../grafana/consul-dataplane-dashboard.png | Bin 0 -> 570470 bytes .../img/grafana/service-dashboard-1.png | Bin 0 -> 694807 bytes .../img/grafana/service-dashboard-2.png | Bin 0 -> 575916 bytes .../img/grafana/service-to-service-1.png | Bin 0 -> 699215 bytes .../img/grafana/service-to-service-2.png | Bin 0 -> 514607 bytes .../img/grafana/service-to-service-3.png | Bin 0 -> 751013 bytes .../img/grafana/service-to-service-4.png | Bin 0 -> 505283 bytes 15 files changed, 889 insertions(+), 1 deletion(-) create mode 100644 .changelog/21795.txt create mode 100644 website/content/docs/connect/observability/grafanadashboards/consuldataplanedashboard.mdx create mode 100644 website/content/docs/connect/observability/grafanadashboards/consulk8sdashboard.mdx create mode 100644 website/content/docs/connect/observability/grafanadashboards/consulserverdashboard.mdx create mode 100644 website/content/docs/connect/observability/grafanadashboards/index.mdx create mode 100644 website/content/docs/connect/observability/grafanadashboards/service-to-servicedashboard.mdx create mode 100644 website/content/docs/connect/observability/grafanadashboards/servicedashboard.mdx create mode 100644 website/public/img/grafana/consul-dataplane-dashboard.png create mode 100644 website/public/img/grafana/service-dashboard-1.png create mode 100644 website/public/img/grafana/service-dashboard-2.png create mode 100644 website/public/img/grafana/service-to-service-1.png create mode 100644 website/public/img/grafana/service-to-service-2.png create mode 100644 website/public/img/grafana/service-to-service-3.png create mode 100644 website/public/img/grafana/service-to-service-4.png diff --git a/.changelog/21795.txt b/.changelog/21795.txt new file mode 100644 index 000000000000..82382255bb6a --- /dev/null +++ b/.changelog/21795.txt @@ -0,0 +1,3 @@ +```release-note:feature +docs: added the docs for the grafana dashboards +``` diff --git a/website/content/docs/connect/observability/grafanadashboards/consuldataplanedashboard.mdx b/website/content/docs/connect/observability/grafanadashboards/consuldataplanedashboard.mdx new file mode 100644 index 000000000000..24436828aa76 --- /dev/null +++ b/website/content/docs/connect/observability/grafanadashboards/consuldataplanedashboard.mdx @@ -0,0 +1,133 @@ +--- +layout: docs +page_title: Dashboard for Consul dataplane metrics +description: >- + This Grafana dashboard provides Consul dataplane metrics on Kubernetes deployments. Learn about the Grafana queries that produce the metrics and visualizations in this dashboard. +--- + +# Consul dataplane monitoring dashboard + +This page provides reference information about the [Grafana dashboard configuration included in the `hashicorp/consul` GitHub repository](https://github.com/hashicorp/consul/blob/main/grafana/consuldataplanedashboard.json). The Consul dataplane dashboard provides a comprehensive view of the service health, performance, and resource utilization within the Consul service mesh. You can monitor key metrics at both the cluster and service levels with this dashboard. It can help you ensure service reliability and performance. + +![Preview of the Consul dataplane dashboard](/public/img/grafana/consul-dataplane-dashboard.png) + +This image provides an example of the dashboard's visual layout and contents. + +## Grafana queries overview + +The Consul dataplane dashboard provides the following information about service mesh operations. + +### Live service count + +**Description:** Displays the total number of live Envoy proxies currently running in the service mesh. It helps track the overall availability of services and identify any outages or other widespread issues in the service mesh. + +```promql +sum(envoy_server_live{app=~"$service"}) +``` + +### Total request success rate + +**Description:** Tracks the percentage of successful requests across the service mesh. It excludes 4xx and 5xx response codes to focus on operational success. Use it to monitor the overall reliability of your services. + +```promql +sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!~"5|4",consul_destination_service=~"$service"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~"$service"}[10m])) +``` + +### Total failed requests + +**Description:** This pie chart shows the total number of failed requests within the service mesh, categorized by service. It provides a visual breakdown of where failures are occurring, allowing operators to focus on problematic services. + +```promql +sum(increase(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~"4|5", consul_destination_service=~"$service"}[10m])) by (local_cluster) +``` + +### Requests per second + +**Description:** This metric shows the rate of incoming HTTP requests per second to the selected services. It helps operators understand the current load on services and how much traffic they are processing. + +```promql +sum(rate(envoy_http_downstream_rq_total{service=~"$service",envoy_http_conn_manager_prefix="public_listener"}[5m])) by (service) +``` + +### Unhealthy clusters + +**Description:** This metric tracks the number of unhealthy clusters in the mesh, helping operators identify services that are experiencing issues and need attention to ensure operational health. + +```promql +(sum(envoy_cluster_membership_healthy{app=~"$service",envoy_cluster_name=~"$cluster"}) - sum(envoy_cluster_membership_total{app=~"$service",envoy_cluster_name=~"$cluster"})) +``` + +### Heap size + +**Description:** This metric displays the total memory heap size of the Envoy proxies. Monitoring heap size is essential to detect memory issues and ensure that services are operating efficiently. + +```promql +SUM(envoy_server_memory_heap_size{app=~"$service"}) +``` + +### Allocated memory + +**Description:** This metric shows the amount of memory allocated by the Envoy proxies. It helps operators monitor the resource usage of services to prevent memory overuse and optimize performance. + +```promql +SUM(envoy_server_memory_allocated{app=~"$service"}) +``` + +### Avg uptime per node + +**Description:** This metric calculates the average uptime of Envoy proxies across all nodes. It helps operators monitor the stability of services and detect potential issues with service restarts or crashes. + +```promql +avg(envoy_server_uptime{app=~"$service"}) +``` + +### Cluster state + +**Description:** This metric indicates whether all clusters are healthy. It provides a quick overview of the cluster state to ensure that there are no issues affecting service performance. + +```promql +(sum(envoy_cluster_membership_total{app=~"$service",envoy_cluster_name=~"$cluster"})-sum(envoy_cluster_membership_healthy{app=~"$service",envoy_cluster_name=~"$cluster"})) == bool 0 +``` + +### CPU throttled seconds by namespace + +**Description:** This metric tracks the number of seconds during which CPU usage was throttled. Monitoring CPU throttling helps operators identify when services are exceeding their allocated CPU limits and may need optimization. + +```promql +rate(container_cpu_cfs_throttled_seconds_total{namespace=~"$namespace"}[5m]) +``` + +### Memory usage by pod limits + +**Description:** This metric shows memory usage as a percentage of the memory limit set for each pod. It helps operators ensure that services are staying within their allocated memory limits to avoid performance degradation. + +```promql +100 * max (container_memory_working_set_bytes{namespace=~"$namespace"} / on(container, pod) label_replace(kube_pod_container_resource_limits{resource="memory"}, "pod", "$1", "exported_pod", "(.+)")) by (pod) +``` + +### CPU usage by pod limits + +**Description:** This metric displays CPU usage as a percentage of the CPU limit set for each pod. Monitoring CPU usage helps operators optimize service performance and prevent CPU exhaustion. + +```promql +100 * max( + container_memory_working_set_bytes{namespace=~"$namespace"} / + on(container, pod) label_replace(kube_pod_container_resource_limits{resource="memory"}, "pod", "$1", "exported_pod", "(.+)") +) by (pod) +``` + +### Total active upstream connections + +**Description:** This metric tracks the total number of active upstream connections to other services in the mesh. It provides insight into service dependencies and network load. + +```promql +sum(envoy_cluster_upstream_cx_active{app=~"$service",envoy_cluster_name=~"$cluster"}) by (app, envoy_cluster_name) +``` + +### Total active downstream connections + +**Description:** This metric tracks the total number of active downstream connections from services to clients. It helps operators monitor service load and ensure that services are able to handle the traffic effectively. + +```promql +sum(envoy_http_downstream_cx_active{app=~"$service"}) +``` diff --git a/website/content/docs/connect/observability/grafanadashboards/consulk8sdashboard.mdx b/website/content/docs/connect/observability/grafanadashboards/consulk8sdashboard.mdx new file mode 100644 index 000000000000..5dc35e40d47d --- /dev/null +++ b/website/content/docs/connect/observability/grafanadashboards/consulk8sdashboard.mdx @@ -0,0 +1,128 @@ +--- +layout: docs +page_title: Dashboard for Consul k8s control plane metrics +description: >- + This documentation provides an overview of the Consul on Kubernetes Grafana Dashboard. Learn about the metrics it displays and the queries that produce the metrics. +--- + +# Consul on Kubernetes control plane monitoring dashboard + +This page provides reference information about the [Grafana dashboard configuration included in the `hashicorp/consul` GitHub repository](https://github.com/hashicorp/consul/blob/main/grafana/consul-k8s-control-plane-monitoring.json). + +## Grafana queries overview + +This dashboard provides the following information about service mesh operations. + +### Number of Consul servers + +**Description:** Displays the number of Consul servers currently active. This metric provides insight into the cluster's health and the number of Consul nodes running in the environment. + +```promql +consul_consul_server_0_consul_members_servers{pod="consul-server-0"} +``` + +### Number of connected Consul dataplanes + +**Description:** Tracks the number of connected Consul dataplanes. This metric helps operators understand how many Envoy sidecars are actively connected to the mesh. + +```promql +count(consul_dataplane_envoy_connected) +``` + +### CPU usage in seconds (Consul servers) + +**Description:** This metric shows the CPU usage of the Consul servers over time, helping operators monitor resource consumption. + +```promql +rate(container_cpu_usage_seconds_total{container="consul", pod=~"consul-server-.*"}[5m]) +``` + +### Memory usage (Consul servers) + +**Description:** Displays the memory usage of the Consul servers. This metric helps ensure that the servers have sufficient memory resources for proper operation. + +```promql +container_memory_working_set_bytes{container="consul", pod=~"consul-server-.*"} +``` + +### Disk read/write total per 5 minutes (Consul servers) + +**Description:** Tracks the total network bytes received by Consul servers within a 5 minute window. This metric helps assess the network load on Consul nodes. + +```promql +sum(rate(container_fs_writes_bytes_total{pod=~"consul-server-.*", container="consul"}[5m])) by (pod, device) +``` + +```promql +sum(rate(container_fs_reads_bytes_total{pod=~"consul-server-.*", container="consul"}[5m])) by (pod, device) +``` + +### Received bytes total per 5 minutes (Consul servers) + +**Description:** Tracks the total network bytes received by Consul servers within a 5 minute window. This metric helps assess the network load on Consul nodes. + +```promql +sum(rate(container_network_receive_bytes_total{pod=~"consul-server-.*"}[5m])) by (pod) +``` + +### Memory limit (Consul servers) + +**Description:** Displays the memory limit for Consul servers. This metric ensures that memory usage stays within the defined limits for each Consul server. + +```promql +kube_pod_container_resource_limits{resource="memory", pod="consul-server-0"} +``` + +### CPU limit in seconds (Consul servers) + +**Description:** Displays the CPU limit for Consul servers. Monitoring CPU limits helps operators ensure that the services are not constrained by resource limitations. + +```promql +kube_pod_container_resource_limits{resource="cpu", pod="consul-server-0"} +``` + +### Disk usage (Consul servers) + +**Description:** Shows the amount of filesystem storage used by Consul servers. This metric helps operators track disk usage and plan for capacity. + +```promql +sum(container_fs_usage_bytes{}) by (pod) +``` + +```promql +sum(container_fs_usage_bytes{pod="consul-server-0"}) +``` + +### CPU usage in seconds (Connect injector) + +**Description:** Tracks the CPU usage of the Connect injector, which is responsible for injecting Envoy sidecars and other operations within the mesh. Monitoring this helps ensure that Connect injector has adequate CPU resources. + +```promql +rate(container_cpu_usage_seconds_total{pod=~".*-connect-injector-.*", container="sidecar-injector"}[5m]) +``` + +### CPU limit in seconds (Connect injector) + +**Description:** Displays the CPU limit for the Connect injector. Monitoring the CPU limits ensures that Connect injector is not constrained by resource limitations. + +```promql +max(kube_pod_container_resource_limits{resource="cpu", container="sidecar-injector"}) +``` + +### Memory usage (Connect injector) + +**Description:** Tracks the memory usage of the Connect injector. Monitoring this helps ensure the Connect injector has sufficient memory resources. + +```promql +container_memory_working_set_bytes{pod=~".*-connect-injector-.*", container="sidecar-injector"} +``` + +### Memory limit (Connect injector) + +**Description:** Displays the memory limit for the Connect injector, helping to monitor if the service is nearing its resource limits. + +```promql +max(kube_pod_container_resource_limits{resource="memory", container="sidecar-injector"}) +``` + + diff --git a/website/content/docs/connect/observability/grafanadashboards/consulserverdashboard.mdx b/website/content/docs/connect/observability/grafanadashboards/consulserverdashboard.mdx new file mode 100644 index 000000000000..e3e2ff49bf9e --- /dev/null +++ b/website/content/docs/connect/observability/grafanadashboards/consulserverdashboard.mdx @@ -0,0 +1,164 @@ +--- +layout: docs +page_title: Dashboard for Consul server metrics +description: >- + This documentation provides an overview of the Consul Server Dashboard. Learn about the metrics it displays and the queries that produce the metrics. +--- + +# Consul server monitoring dashboard + +This page provides reference information about the [Grafana dashboard configuration included in the `hashicorp/consul` GitHub repository](https://github.com/hashicorp/consul/blob/main/grafana/consul-server-monitoring.json). + +## Grafana queries overview + +This dashboard provides the following information about service mesh operations. + +### Raft commit time + +**Description:** This metric measures the time it takes to commit Raft log entries. Stable values are expected for a healthy cluster. High values can indicate issues with resources such as memory, CPU, or disk space. + +```promql +consul_raft_commitTime +``` + +### Raft commits per 5 minutes + +**Description:** This metric tracks the rate of Raft log commits emitted by the leader, showing how quickly changes are being applied across the cluster. + +```promql +rate(consul_raft_apply[5m]) +``` + +### Last contacted leader + +**Description:** Measures the duration since the last contact with the Raft leader. Spikes in this metric can indicate network issues or an unavailable leader, which may affect cluster stability. + +```promql +consul_raft_leader_lastContact != 0 +``` + +### Election events + +**Description:** Tracks Raft state transitions, which indicate leadership elections. Frequent transitions might suggest cluster instability and require investigation. + +```promql +rate(consul_raft_state_candidate[1m]) +``` + +```promql +rate(consul_raft_state_leader[1m]) +``` + +### Autopilot health + +**Description:** A boolean metric that shows a value of 1 when Autopilot is healthy and 0 when issues are detected. Ensures that the cluster has sufficient resources and an operational leader. + +```promql +consul_autopilot_healthy +``` + +### DNS queries per 5 minutes + +**Description:** This metric tracks the rate of DNS queries per node, bucketed into 5 minute intervals. It helps monitor the query load on Consul’s DNS service. + +```promql +rate(consul_dns_domain_query_count[5m]) +``` + +### DNS domain query time + +**Description:** Measures the time spent handling DNS domain queries. Spikes in this metric may indicate high contention in the catalog or too many concurrent queries. + +```promql +consul_dns_domain_query +``` + +### DNS reverse query time + +**Description:** Tracks the time spent processing reverse DNS queries. Spikes in query time may indicate performance bottlenecks or increased workload. + +```promql +consul_dns_ptr_query +``` + +### KV applies per 5 minutes + +**Description:** This metric tracks the rate of key-value store applies over 5 minute intervals, indicating the operational load on Consul’s KV store. + +```promql +rate(consul_kvs_apply_count[5m]) +``` + +### KV apply time + +**Description:** Measures the time taken to apply updates to the key-value store. Spikes in this metric might suggest resource contention or client overload. + +```promql +consul_kvs_apply +``` + +### Transaction apply time + +**Description:** Tracks the time spent applying transaction operations in Consul, providing insights into potential bottlenecks in transaction operations. + +```promql +consul_txn_apply +``` + +### ACL resolves per 5 minutes + +**Description:** This metric tracks the rate of ACL token resolutions over 5 minute intervals. It provides insights into the activity related to ACL tokens within the cluster. + +```promql +rate(consul_acl_ResolveToken_count[5m]) +``` + +### ACL resolve token time + +**Description:** Measures the time taken to resolve ACL tokens into their associated policies. + +```promql +consul_acl_ResolveToken +``` + +### ACL updates per 5 minutes + +**Description:** Tracks the rate of ACL updates over 5 minute intervals. This metric helps monitor changes in ACL configurations over time. + +```promql +rate(consul_acl_apply_count[5m]) +``` + +### ACL apply time + +**Description:** Measures the time spent applying ACL changes. Spikes in apply time might suggest resource constraints or high operational load. + +```promql +consul_acl_apply +``` + +### Catalog operations per 5 minutes + +**Description:** Tracks the rate of register and deregister operations in the Consul catalog, providing insights into the churn of services within the cluster. + +```promql +rate(consul_catalog_register_count[5m]) +``` + +```promql +rate(consul_catalog_deregister_count[5m]) +``` + +### Catalog operation time + +**Description:** Measures the time taken to complete catalog register or deregister operations. Spikes in this metric may indicate performance issues within the catalog. + +```promql +consul_catalog_register +``` + +```promql +consul_catalog_deregister +``` + + diff --git a/website/content/docs/connect/observability/grafanadashboards/index.mdx b/website/content/docs/connect/observability/grafanadashboards/index.mdx new file mode 100644 index 000000000000..2a21ec6f2fcf --- /dev/null +++ b/website/content/docs/connect/observability/grafanadashboards/index.mdx @@ -0,0 +1,91 @@ +--- +layout: docs +page_title: Service Mesh Observability - Dashboards +description: >- + This documentation provides an overview of several dashboards designed for monitoring and managing services within a Consul-managed Envoy service mesh. Learn how to enable access logs and configure key performance and operational metrics to ensure the reliability and performance of services in the service mesh. +--- + +# Dashboards for service mesh observability + +This topic describes the configuration and usage of dashboards for monitoring and managing services within a Consul-managed Envoy service mesh. These dashboards provide critical insights into the health, performance, and resource utilization of services. The dashboards described here are essential tools for ensuring the stability, efficiency, and reliability of your service mesh environment. + +This page provides reference information about the Grafana dashboard configurations included in the [`grafana` directory in the `hashicorp/consul` GitHub repository](https://github.com/hashicorp/consul/tree/main/grafana). + +## Dashboards overview + +The repository includes the following dashboards: + + - **Consul service-to-service dashboard**: Provides a detailed view of service-to-service communications, monitoring key metrics like access logs, HTTP requests, error counts, response code distributions, and request success rates. The dashboard includes customizable filters for focusing on specific services and namespaces. + + - **Consul service dashboard**: Tracks key metrics for Envoy proxies at the cluster and service levels, ensuring the performance and reliability of individual services within the mesh. + + - **Consul dataplane dashboard**: Offers a comprehensive overview of service health and performance, including request success rates, resource utilization (CPU and memory), active connections, and cluster health. It helps operators maintain service reliability and optimize resource usage. + + - **Consul k8s dashboard**: Focuses on monitoring the health and resource usage of the Consul control plane within a Kubernetes environment, ensuring the stability of the control plane. + + - **Consul server dashboard**: Provides detailed monitoring of Consul servers, tracking key metrics like server health, CPU and memory usage, disk I/O, and network performance. This dashboard is critical for ensuring the stability and performance of Consul servers within the service mesh. + +## Enabling prometheus + +Add the following configurations to your Consul Helm chart to enable the prometheus tools. + + + +```yaml +global: + metrics: + enabled: true + provider: "prometheus" + enableAgentMetrics: true + agentMetricsRetentionTime: "10m" + +prometheus: + enabled: true + +ui: + enabled: true + metrics: + enabled: true + provider: "prometheus" + baseURL: http://prometheus-server.consul +``` + + + +## Enable access logs + +Access logs configurations are defined globally in the [`proxy-defaults`](/consul/docs/connect/config-entries/proxy-defaults#accesslogs) configuration entry. + +The following example is a minimal configuration for enabling access logs: + + + +```hcl +Kind = "proxy-defaults" +Name = "global" +AccessLogs { + Enabled = true +} +``` + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ProxyDefaults +metadata: + name: global +spec: + accessLogs: + enabled: true +``` + +```json +{ + "Kind": "proxy-defaults", + "Name": "global", + "AccessLogs": { + "Enabled": true + } +} +``` + + diff --git a/website/content/docs/connect/observability/grafanadashboards/service-to-servicedashboard.mdx b/website/content/docs/connect/observability/grafanadashboards/service-to-servicedashboard.mdx new file mode 100644 index 000000000000..f6abad471e9a --- /dev/null +++ b/website/content/docs/connect/observability/grafanadashboards/service-to-servicedashboard.mdx @@ -0,0 +1,183 @@ +--- +layout: docs +page_title: Dashboard for monitoring Consul service-to-service mesh +description: >- + This documentation provides an overview of the Service-to-service dashboard. Learn about the metrics it displays and the queries that produce the metrics. +--- + +# Service-to-service dashboard + +This page provides reference information about the [Grafana dashboard configuration included in the `hashicorp/consul` GitHub repository](https://github.com/hashicorp/consul/blob/main/grafana/consulservicetoservicedashboard.json). The service-to-service dashboard provides deep visibility into the traffic and interactions between services within the Consul service mesh. It focuses on critical metrics such as logs, error rates, traffic patterns, and success rates, all of which help operators maintain smooth and reliable service-to-service communication. + +![Preview of the service to service mesh dashboard](/public/img/grafana/service-to-service-1.png) + +## Grafana queries overview + +This dashboard provides the following information about service mesh operations. + +### Access logs and errors monitoring + +**Description:** This section provides visibility into logs and errors related to service-to-service communications. It tracks and displays the number of logs generated, errors encountered, and the percentage of logs matching specific patterns. + +### Total logs + +**Description:** This metric counts the total number of log lines produced by Consul dataplane containers. It provides an overview of the volume of logs being generated for a specific namespace. + +```promql +sum(count_over_time(({container="consul-dataplane",namespace=~"$namespace"})[$__interval])) +``` + +### Total logs containing "$searchable_pattern" + +**Description:** This metric tracks the number of logs containing the specified pattern. It is useful for filtering and monitoring specific log events across the service mesh. + +```promql +sum(count_over_time({container="consul-dataplane", namespace=~"$namespace"} |~ (?i)(?i)$searchable_pattern [$__interval])) +``` + +### Percentage of logs containing "$searchable_pattern" + +**Description:** This metric calculates the percentage of logs containing the specified search pattern within the total log volume. It helps gauge the proportion of specific log events. + +```promql +(sum(count_over_time({container="consul-dataplane", namespace=~"$namespace"} |~ (?i)(?i)$searchable_pattern [$__interval])) * 100) / sum(count_over_time({container="consul-dataplane", namespace=~"$namespace"} [$__interval])) +``` + +### Total response code distribution + +**Description:** This pie chart visualizes the distribution of HTTP response codes, helping identify any 4xx and 5xx error codes generated by the services. + +```promql +sum by(response_code) (count_over_time({container="consul-dataplane", namespace="$namespace"} | json | response_code != "0" | __error__= [$__range])) +``` + +### Rate of logs containing "$searchable_pattern" per service + +**Description:** This metric monitors the rate at which specific patterns appear in logs per service, helping to detect trends and anomalies in log data. + +```promql +sum by(app) (rate({container="consul-dataplane", namespace=~"$namespace"} |~ (?i)(?i)$searchable_pattern [$__range])) +``` + +### TCP metrics - service level + +### TCP inbound and outbound bytes + +**Description:** This metric tracks the inbound and outbound TCP bytes transferred between services. It is essential for understanding the network traffic flow between source and destination services. + +```promql +sum(rate(envoy_tcp_downstream_cx_rx_bytes_total{}[10m])) by (service, destination_service) +``` + +### TCP inbound and outbound bytes buffered + +**Description:** This metric monitors the amount of TCP bytes buffered for inbound and outbound traffic between services. It helps identify potential network performance bottlenecks. + +```promql +sum(rate(envoy_tcp_downstream_cx_rx_bytes_buffered{}[10m])) by (service, destination_service) +``` + +### TCP downstream connections + +**Description:** This metric counts the number of active TCP downstream connections from the source service to the destination service, providing visibility into the volume of connections between services. + +```promql +sum(envoy_tcp_downstream_cx_total) by (service, destination_service) +``` + +### Outbound traffic monitoring +![Preview of the outbound traffic monitoring](/public/img/grafana/service-to-service-2.png) + +### Upstream traffic + +**Description:** This metric monitors the upstream traffic from the source service to the destination service. It shows how much traffic is being sent between services. + +```promql +sum(irate(envoy_cluster_upstream_rq_total{local_cluster=~"$source_service",consul_destination_service=~"$destination_service"}[10m])) +``` + +### Upstream request response timeliness + +**Description:** This metric calculates the 95th percentile of upstream request response times between the source and destination services. It helps ensure that service communications are handled promptly. + +```promql +histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{local_cluster=~"$source_service",consul_destination_target!=""}[10m])) by (le, consul_destination_target)) +``` + +### Upstream request success rate + +**Description:** This metric tracks the success rate of requests from the source service to the destination service, excluding 4xx and 5xx errors. It helps assess the reliability of service communications. + +```promql +sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!="5",local_cluster=~"$source_service",consul_destination_service=~"$destination_service"}[10m])) +``` + +### Inbound traffic monitoring +![Preview of the inbound traffic monitoring](/public/img/grafana/service-to-service-3.png) + +### Requests sent + +**Description:** This metric tracks the number of requests sent between the source service and destination service within the service mesh. + +```promql +sum(irate(envoy_cluster_upstream_rq_total{consul_destination_datacenter="dc1",local_cluster=~"$source_service",consul_destination_service=~"$destination_service"}[10m])) by (consul_destination_service, local_cluster) +``` + +### Request success rate + +**Description:** This metric tracks the success rate of requests from the source service to the destination service, helping identify failures or bottlenecks in communication. + +```promql +sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!="5",local_cluster=~"$source_service",consul_destination_service=~"$destination_service"}[10m])) by (local_cluster, consul_destination_service) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~"$destination_service"}[10m])) by (local_cluster, consul_destination_service) +``` + +### Response success by status code + +**Description:** This metric tracks response success by status code for requests sent by the source service to the destination service. + +```promql +sum(increase(envoy_http_downstream_rq_xx{local_cluster=~"$source_service",envoy_http_conn_manager_prefix="public_listener"}[10m])) by (local_cluster, envoy_response_code_class) +``` + +### Request duration + +**Description:** This metric tracks the request duration between the source and destination services, helping monitor performance and response times. + +```promql +histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{consul_destination_datacenter="dc1", consul_destination_service=~"$destination_service",local_cluster=~"$source_service"}[10m])) by (le, cluster, local_cluster, consul_destination_service)) +``` + +### Response success + +**Description:** This metric tracks the success of responses for the source service's requests across the service mesh. + +```promql +sum(increase(envoy_http_downstream_rq_total{local_cluster=~"$source_service",envoy_http_conn_manager_prefix="public_listener"}[10m])) by (local_cluster) +``` + +### Request response rate + +**Description:** This metric tracks the rate at which responses are being generated by the source service, providing insight into service activity and performance. + +```promql +sum(irate(envoy_http_downstream_rq_total{local_cluster=~"$source_service",envoy_http_conn_manager_prefix="public_listener"}[10m])) by (local_cluster) +``` + +## Customization options + +![Preview of the nginx service selection as a customization option on the service to service dashboard](/public/img/grafana/service-to-service-4.png) + +The service-to-service dashboard includes a variety of customization options to help you analyze specific aspects of service-to-service communications, tailor the dashboard for more targeted monitoring, and enhance visibility into the service mesh. + +- **Filter by source service:** You can filter the dashboard to focus on traffic originating from a specific source service, allowing you to analyze interactions from the source service to all destination services. + +- **Filter by destination service:** Similarly, you can filter the dashboard by destination service to track and analyze the traffic received by specific services. This helps pinpoint communication issues or performance bottlenecks related to specific services. + +- **Filter by namespace:** The dashboard can be customized to focus on service interactions within a particular namespace. This is especially useful for isolating issues in multi-tenant environments or clusters that operate with strict namespace isolation. + +- **Log pattern search:** You can apply custom search patterns to logs to filter out specific log events of interest, such as error messages or specific HTTP status codes. This enables you to narrow down on specific log entries and identify patterns that may indicate issues. + +- **Time range selection:** The dashboard supports dynamic time range selection, allowing you to focus on service interactions over specific time intervals. This helps in analyzing traffic trends, troubleshooting incidents, and understanding the timing of service communications. + +By using these customization options, you can tailor the dashboard to your specific needs and ensure they are always monitoring the most relevant data for maintaining a healthy and performant service mesh. + diff --git a/website/content/docs/connect/observability/grafanadashboards/servicedashboard.mdx b/website/content/docs/connect/observability/grafanadashboards/servicedashboard.mdx new file mode 100644 index 000000000000..dfe684c3437a --- /dev/null +++ b/website/content/docs/connect/observability/grafanadashboards/servicedashboard.mdx @@ -0,0 +1,157 @@ +--- +layout: docs +page_title: Dashboard for monitoring Consul service mesh +description: >- + This documentation provides an overview of the Service Dashboard. Learn about the metrics it displays and the queries that produce the metrics. +--- + +# Service dashboard + +This page provides reference information about the [Grafana dashboard configuration included in the `hashicorp/consul` GitHub repository](https://github.com/hashicorp/consul/blob/main/grafana/consulservicedashboard.json). The service dashboard offers an overview of the performance and health of individual services within the Consul service mesh. It provides insights into service availability, request success rates, latency, and connection metrics. This dashboard is essential for maintaining optimal service performance and quickly identifying any issues with service communications. + +![Preview of the service dashboard](/public/img/grafana/service-dashboard-2.png) + +## Grafana queries overview + +This dashboard provides the following information about service mesh operations. + +### Total running services + +**Description:** This gauge tracks the total number of running services within the mesh that are not labeled as `traffic-generator`. It provides an overall view of active services, helping operators maintain visibility into service availability. + +```promql +sum(envoy_server_live{app!="traffic-generator"}) +``` + +### Total request success rate + +**Description:** This stat visualizes the success rate of upstream requests to the selected service. It filters out 4xx and 5xx response codes, providing a clearer picture of how well the service is performing in terms of handling requests successfully. + +```promql +sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!="5", envoy_response_code_class!="4", consul_destination_service=~"$service"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~"$service"}[10m])) +``` + +### Total failed request rate + +**Description:** This stat tracks the rate of failed requests for the selected service according to 4xx and 5xx errors. It helps operators quickly identify if there are issues with client requests or server errors for a specific service. + +```promql +sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~"4|5", consul_destination_service=~"$service"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~"$service"}[10m])) +``` + +### Average request response time in milliseconds + +**Description:** This gauge displays the average response time for requests to the selected service, providing an overview of the service's performance and responsiveness. + +```promql +sum(rate(envoy_cluster_upstream_rq_time_sum{consul_destination_service=~"$service"}[10m])) / sum(rate(envoy_cluster_upstream_rq_total{consul_destination_service=~"$service"}[10m])) +``` + +### Total failed requests + +**Description:** This gauge tracks the total number of failed requests over a 10 minute window, categorized by service. It allows for easy identification of services that are experiencing high failure rates. + +```promql +sum(increase(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~"4|5", consul_destination_service=~"$service"}[10m])) by(local_cluster) +``` + +### Dataplane latency + +**Description:** This stat tracks the dataplane latency percentiles (p50, p75, p90, p99.9) for the selected service. It gives detailed insights into the distribution of latency within the service's request handling, helping identify performance bottlenecks. + +![Preview of the dataplane latency metrics](/public/img/grafana/service-dashboard-1.png) + +```promql +histogram_quantile(0.50, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~"$namespace", local_cluster=~"$service"}[5m]))) +``` + +```promql +histogram_quantile(0.75, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~"$namespace", local_cluster=~"$service"}[5m]))) +``` + +```promql +histogram_quantile(0.90, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~"$namespace", local_cluster=~"$service"}[5m]))) +``` + +```promql +histogram_quantile(0.999, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~"$namespace", local_cluster=~"$service"}[5m]))) +``` + +### Total TCP inbound and outbound bytes + +**Description:** This time series shows the total number of inbound and outbound TCP bytes for services within the mesh. It provides visibility into the data transfer patterns and volume between services. + +```promql +sum(rate(envoy_tcp_downstream_cx_rx_bytes_total{}[10m])) by (local_cluster) +``` + +### Total TCP inbound and outbound bytes buffered + +**Description:** This metric tracks the amount of TCP traffic buffered during inbound and outbound communications. It helps in identifying whether there is any potential latency caused by packet buffering or congestion. + +```promql +sum(rate(envoy_tcp_downstream_cx_rx_bytes_buffered{}[10m])) by (local_cluster) +``` + +### Total TCP downstream active connections + +**Description:** This metric counts the total number of active TCP downstream connections, providing an overview of the current connection load on the services within the mesh. + +```promql +sum(rate(envoy_tcp_downstream_cx_total{}[10m])) by(local_cluster) +``` + +### Total active HTTP upstream connections + +**Description:** This time series tracks the total number of active HTTP upstream connections for the selected service. It helps monitor connection patterns and assess load. + +```promql +sum(envoy_cluster_upstream_cx_active{app=~"$service"}) by (app) +``` + +### Total active HTTP downstream connections + +**Description:** This time series monitors the number of active HTTP downstream connections for the selected service, providing visibility into the current active user or client load on the service. + +```promql +sum(envoy_http_downstream_cx_active{app=~"$service"}) by (app) +``` + +### Upstream requests by status code + +**Description:** This metric tracks the number of upstream requests, grouped by HTTP status codes, giving insight into the health of the requests being made to upstream services from the selected service. + +```promql +sum by(namespace,app,envoy_response_code_class) (rate(envoy_cluster_upstream_rq_xx[5m])) +``` + +### Downstream requests by status code + +**Description:** This time series tracks downstream HTTP requests by status code, showing how well the selected service is responding to downstream requests from clients. + +```promql +sum(rate(envoy_http_downstream_rq_xx{envoy_http_conn_manager_prefix="public_listener"}[5m])) by (namespace, app, envoy_response_code_class) +``` + +### Connections rejected + +**Description:** This metric tracks the number of connections rejected due to overload or overflow conditions on listeners. Monitoring these values helps identify if the service is under too much load or has insufficient capacity to handle the incoming connections. + +```promql +rate(envoy_listener_downstream_cx_overload_reject{}[$__interval]) +``` + +## Customization options + +The service dashboard offers various customization options to help you analyze specific services and metrics. Use these options to tailor the dashboard to your needs and improve your ability to monitor and troubleshoot service health. + +- **Filter by service:** You can filter the dashboard by the service you want to monitor. This helps narrow down the metrics to the service of interest and provides a more targeted view of its performance. + +- **Filter by namespace:** The namespace filter allows operators to focus on a particular namespace in a multi-tenant or multi-namespace environment, isolating the service metrics within that specific context. + +- **Time range selection:** The dashboard supports flexible time range selection, allowing operators to analyze service behavior over different time periods. This is helpful for pinpointing issues that may occur at specific times or during high-traffic periods. + +- **Percentile latency tracking:** The dashboard allows operators to track multiple latency percentiles (p50, p75, p90, p99.9) to get a more detailed view of how the service performs across different levels of traffic load. + + + diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 204303ef9b59..1276feaa025d 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -418,7 +418,7 @@ "title": "Cache DNS lookups", "path": "services/discovery/dns-cache" }, - { + { "title": "Enable dynamic DNS lookups", "path": "services/discovery/dns-dynamic-lookups" } @@ -690,6 +690,35 @@ { "title": "UI Visualization", "path": "connect/observability/ui-visualization" + }, + { + "title": "Grafana Dashboards", + "routes": [ + { + "title": "Overview", + "path": "connect/observability/grafanadashboards" + }, + { + "title": "Service to Service Dashboard", + "path": "connect/observability/grafanadashboards/service-to-servicedashboard" + }, + { + "title": "Service Dashboard", + "path": "connect/observability/grafanadashboards/servicedashboard" + }, + { + "title": "Consul Dataplane Dashboard", + "path": "connect/observability/grafanadashboards/consuldataplanedashboard" + }, + { + "title": "Consul K8s Dashboard", + "path": "connect/observability/grafanadashboards/consulk8sdashboard" + }, + { + "title": "Consul Server Dashboard", + "path": "connect/observability/grafanadashboards/consulserverdashboard" + } + ] } ] }, diff --git a/website/public/img/grafana/consul-dataplane-dashboard.png b/website/public/img/grafana/consul-dataplane-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..fbca984c1149ec56edec9bcb6f660381f7bf9570 GIT binary patch literal 570470 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νG5P2%pNvc9lmxFgff_QbdFJLJnEc$O?-Ly9{WqL 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 FpMXk;GAfW<)T#f8^nH6ddMgI6=mk5pA-K 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

%~*MlUSLQb292mzk>K4@FIL|la7IINv|xED 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