diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md index 2683ec4d33..04032c57a7 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md @@ -1,6 +1,9 @@ --- name: Feature Request about: Suggest an idea for Higress +title: '' +labels: '' +assignees: '' --- @@ -13,4 +16,4 @@ A clear and concise description of what you want to happen. You can explain more ## Other related information -Add any other context or screenshots about the feature request here. \ No newline at end of file +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..eb02f7cf96 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Ask a question 💬 + url: https://github.com/alibaba/higress/discussions + about: Ask a question or request support for using Higress. diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/non--crash-security--bug.md similarity index 59% rename from .github/ISSUE_TEMPLATE/BUG_REPORT.md rename to .github/ISSUE_TEMPLATE/non--crash-security--bug.md index a2e935de5a..c4f6a364aa 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md +++ b/.github/ISSUE_TEMPLATE/non--crash-security--bug.md @@ -1,10 +1,15 @@ --- -name: Bug Report -about: If you would like to report an issue to Higress, please use this template. - +name: Non-{crash,security} bug +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' --- +**If you are reporting *any* crash or *any* potential security issue, *do not* +open an issue in this repo. Please report the issue via [ASRC](https://security.alibaba.com/)(Alibaba Security Response Center) where the issue will be triaged appropriately.** + - [ ] I have searched the [issues](https://github.com/alibaba/higress/issues) of this repository and believe that this is not a duplicate. ### Ⅰ. Issue Description @@ -35,4 +40,4 @@ Just paste your stack trace here! - Higress version: - OS : -- Others: \ No newline at end of file +- Others: diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yaml similarity index 100% rename from .github/workflows/build-and-test.yml rename to .github/workflows/build-and-test.yaml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yaml similarity index 100% rename from .github/workflows/codeql-analysis.yml rename to .github/workflows/codeql-analysis.yaml diff --git a/.github/workflows/latest-release.yaml b/.github/workflows/latest-release.yaml new file mode 100644 index 0000000000..7b53f378de --- /dev/null +++ b/.github/workflows/latest-release.yaml @@ -0,0 +1,68 @@ +name: Latest Release + +on: + push: + branches: + - "main" + +jobs: + latest-release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Build hgctl latest multiarch binaries + run: | + GOPROXY="https://proxy.golang.org,direct" make build-hgctl-multiarch + tar -zcvf hgctl_latest_linux_amd64.tar.gz out/linux_amd64/ + tar -zcvf hgctl_latest_linux_arm64.tar.gz out/linux_arm64/ + tar -zcvf hgctl_latest_darwin_amd64.tar.gz out/darwin_amd64/ + tar -zcvf hgctl_latest_darwin_arm64.tar.gz out/darwin_arm64/ + + # Ignore the error when we delete the latest release, it might not exist. + + # GitHub APIs take sometime to make effect, we should make sure before Recreate the Latest Release and Tag, + # tag and release all get deleted. So we sleep sometime after deleting tag and release to wait for it taking effect. + + - name: Delete the Latest Release + continue-on-error: true + run: | + gh release delete latest --repo $GITHUB_REPOSITORY + sleep 4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: ${{ github.repository_owner }}/${{ github.event.repository.name }} + + # Ignore the error when we delete the latest tag, it might not exist. + - name: Delete the Latest Tag + continue-on-error: true + run: | + gh api --method DELETE /repos/$GITHUB_REPOSITORY/git/refs/tags/latest + sleep 4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: ${{ github.repository_owner }}/${{ github.event.repository.name }} + + - name: Recreate the Latest Release and Tag + uses: softprops/action-gh-release@v1 + with: + draft: false + prerelease: true + tag_name: latest + files: | + hgctl_latest_linux_amd64.tar.gz + hgctl_latest_linux_arm64.tar.gz + hgctl_latest_darwin_amd64.tar.gz + hgctl_latest_darwin_arm64.tar.gz + body: | + This is the "latest" release of **Higress**, which contains the most recent commits from the main branch. + + This release **might not be stable**. + + It is only intended for developers wishing to try out the latest features in Higress, some of which may not be fully implemented. + + Try latest version of `hgctl` with: + + ``` shell + curl -Ls https://raw.githubusercontent.com/alibaba/higress/main/tools/hack/get-hgctl.sh | VERSION=latest bash + ``` diff --git a/.licenserc.yaml b/.licenserc.yaml index 10b7bac456..b3e053936d 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -26,6 +26,7 @@ header: - 'VERSION' - 'tools/' - 'test/README.md' + - 'pkg/cmd/hgctl/testdata/config' comment: on-failure dependency: diff --git a/Makefile.core.mk b/Makefile.core.mk index 38a58da2cd..6291525038 100644 --- a/Makefile.core.mk +++ b/Makefile.core.mk @@ -6,13 +6,20 @@ export HUB ?= higress-registry.cn-hangzhou.cr.aliyuncs.com/higress export CHARTS ?= higress-registry.cn-hangzhou.cr.aliyuncs.com/charts +VERSION_PACKAGE := github.com/alibaba/higress/pkg/cmd/version + +GIT_COMMIT:=$(shell git rev-parse HEAD) + +GO_LDFLAGS += -X $(VERSION_PACKAGE).higressVersion=$(shell cat VERSION) \ + -X $(VERSION_PACKAGE).gitCommitID=$(GIT_COMMIT) + GO ?= go export GOPROXY ?= https://proxy.golang.com.cn,direct GOARCH_LOCAL := $(TARGET_ARCH) GOOS_LOCAL := $(TARGET_OS) -RELEASE_LDFLAGS='-extldflags -static -s -w' +RELEASE_LDFLAGS='$(GO_LDFLAGS) -extldflags -static -s -w' export OUT:=$(TARGET_OUT) export OUT_LINUX:=$(TARGET_OUT_LINUX) @@ -32,7 +39,9 @@ endif HIGRESS_DOCKER_BUILD_TOP:=${OUT_LINUX}/docker_build -BINARIES:=./cmd/higress +HIGRESS_BINARIES:=./cmd/higress + +HGCTL_BINARIES:=./cmd/hgctl $(OUT): @mkdir -p $@ @@ -52,11 +61,26 @@ go.test.coverage: prebuild .PHONY: build build: prebuild $(OUT) - GOPROXY=$(GOPROXY) GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT)/ $(BINARIES) + GOPROXY=$(GOPROXY) GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT)/ $(HIGRESS_BINARIES) .PHONY: build-linux build-linux: prebuild $(OUT) - GOPROXY=$(GOPROXY) GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT_LINUX)/ $(BINARIES) + GOPROXY=$(GOPROXY) GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT_LINUX)/ $(HIGRESS_BINARIES) + +.PHONY: build-hgctl +build-hgctl: $(OUT) + GOPROXY=$(GOPROXY) GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT)/ $(HGCTL_BINARIES) + +.PHONY: build-linux-hgctl +build-linux-hgctl: $(OUT) + GOPROXY=$(GOPROXY) GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT_LINUX)/ $(HGCTL_BINARIES) + +.PHONY: build-hgctl-multiarch +build-hgctl-multiarch: $(OUT) + GOPROXY=$(GOPROXY) GOOS=linux GOARCH=amd64 LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh ./out/linux_amd64/ $(HGCTL_BINARIES) + GOPROXY=$(GOPROXY) GOOS=linux GOARCH=arm64 LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh ./out/linux_arm64/ $(HGCTL_BINARIES) + GOPROXY=$(GOPROXY) GOOS=darwin GOARCH=amd64 LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh ./out/darwin_amd64/ $(HGCTL_BINARIES) + GOPROXY=$(GOPROXY) GOOS=darwin GOARCH=arm64 LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh ./out/darwin_arm64/ $(HGCTL_BINARIES) # Create targets for OUT_LINUX/binary # There are two use cases here: @@ -73,14 +97,14 @@ $(OUT_LINUX)/$(shell basename $(1)): $(OUT_LINUX) endif endef -$(foreach bin,$(BINARIES),$(eval $(call build-linux,$(bin),""))) +$(foreach bin,$(HIGRESS_BINARIES),$(eval $(call build-linux,$(bin),""))) # Create helper targets for each binary, like "pilot-discovery" # As an optimization, these still build everything -$(foreach bin,$(BINARIES),$(shell basename $(bin))): build +$(foreach bin,$(HIGRESS_BINARIES),$(shell basename $(bin))): build ifneq ($(OUT_LINUX),$(LOCAL_OUT)) # if we are on linux already, then this rule is handled by build-linux above, which handles BUILD_ALL variable -$(foreach bin,$(BINARIES),${LOCAL_OUT}/$(shell basename $(bin))): build +$(foreach bin,$(HIGRESS_BINARIES),${LOCAL_OUT}/$(shell basename $(bin))): build endif .PHONY: push @@ -113,20 +137,20 @@ endef install: pre-install cd helm/higress; helm dependency build - helm install higress helm/higress -n higress-system --create-namespace --set 'global.kind=true' + helm install higress helm/higress -n higress-system --create-namespace --set 'global.local=true' -ENVOY_LATEST_IMAGE_TAG ?= 0.7.0 -ISTIO_LATEST_IMAGE_TAG ?= 0.7.0 +ENVOY_LATEST_IMAGE_TAG ?= 1.0.0-rc +ISTIO_LATEST_IMAGE_TAG ?= 1.0.0-rc install-dev: pre-install - helm install higress helm/core -n higress-system --create-namespace --set 'controller.tag=$(TAG)' --set 'gateway.replicas=1' --set 'gateway.tag=$(ENVOY_LATEST_IMAGE_TAG)' --set 'global.kind=true' + helm install higress helm/core -n higress-system --create-namespace --set 'controller.tag=$(TAG)' --set 'gateway.replicas=1' --set 'gateway.tag=$(ENVOY_LATEST_IMAGE_TAG)' --set 'global.local=true' uninstall: helm uninstall higress -n higress-system upgrade: pre-install cd helm/higress; helm dependency build - helm upgrade higress helm/higress -n higress-system --set 'global.kind=true' + helm upgrade higress helm/higress -n higress-system --set 'global.local=true' helm-push: cp api/kubernetes/customresourcedefinitions.gen.yaml helm/core/crds @@ -185,7 +209,7 @@ delete-cluster: $(tools/kind) ## Delete kind cluster. # kube-load-image loads a local built docker image into kube cluster. .PHONY: kube-load-image -kube-load-image: $(tools/kind) ## Install the EG image to a kind cluster using the provided $IMAGE and $TAG. +kube-load-image: $(tools/kind) ## Install the Higress image to a kind cluster using the provided $IMAGE and $TAG. tools/hack/kind-load-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/higress $(TAG) # run-ingress-e2e-test starts to run ingress e2e tests. @@ -193,7 +217,7 @@ kube-load-image: $(tools/kind) ## Install the EG image to a kind cluster using t run-ingress-e2e-test: @echo -e "\n\033[36mRunning higress conformance tests...\033[0m" @echo -e "\n\033[36mWaiting higress-controller to be ready...\033[0m\n" - kubectl wait --timeout=5m -n higress-system deployment/higress-controller --for=condition=Available + kubectl wait --timeout=10m -n higress-system deployment/higress-controller --for=condition=Available @echo -e "\n\033[36mWaiting higress-gateway to be ready...\033[0m\n" - kubectl wait --timeout=5m -n higress-system deployment/higress-gateway --for=condition=Available + kubectl wait --timeout=10m -n higress-system deployment/higress-gateway --for=condition=Available go test -v -tags conformance ./test/ingress/e2e_test.go --ingress-class=higress --debug=true diff --git a/README.md b/README.md index e73fd6fe45..cafca6c946 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,14 @@ Higress 是基于阿里内部两年多的 Envoy Gateway 实践沉淀,以开源 ![arch](https://img.alicdn.com/imgextra/i4/O1CN01OgGP1728t0xeRfRYJ_!!6000000007989-0-tps-1726-1366.jpg) ## Summary - + +- [**功能展示**](#功能展示) - [**使用场景**](#使用场景) - [**核心优势**](#核心优势) - [**Quick Start**](https://higress.io/zh-cn/docs/user/quickstart) - [**社区**](#社区) + ## 使用场景 - **Kubernetes Ingress 网关**: @@ -73,6 +75,42 @@ Higress 是基于阿里内部两年多的 Envoy Gateway 实践沉淀,以开源 插件支持热更新,变更插件逻辑和配置都对流量无损。 +## 功能展示 + +- **丰富的可观测** + + 提供开箱即用的可观测,Grafana&Prometheus 可以使用内置的也可对接自建的 + + ![](./docs/images/monitor.gif) + + +- **插件扩展机制** + + 官方提供了多种插件,用户也可以[开发](./plugins/wasm-go)自己的插件,构建成 docker/oci 镜像后在控制台配置,可以实时变更插件逻辑,对流量完全无损。 + + ![](./docs/images/plugin.gif) + + +- **多种服务发现** + + 默认提供 K8s Service 服务发现,通过配置可以对接 Nacos/ZooKeeper 等注册中心实现服务发现,也可以基于静态 IP 或者 DNS 来发现 + + ![](./docs/images/service-source.gif) + + +- **域名和证书** + + 可以创建管理 TLS 证书,并配置域名的 HTTP/HTTPS 行为,域名策略里支持对特定域名生效插件 + + ![](./docs/images/domain.gif) + + +- **丰富的路由能力** + + 通过上面定义的服务发现机制,发现的服务会出现在服务列表中;创建路由时,选择域名,定义路由匹配机制,再选择目标服务进行路由;路由策略里支持对特定路由生效插件 + + ![](./docs/images/route-service.gif) + ## 社区 diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..e4f906b953 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,14 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 1.x.x | :white_check_mark: | +| < 1.0.0 | :x: | + +## Reporting a Vulnerability + +Please report any security issue or Higress crash report to [ASRC](https://security.alibaba.com/)(Alibaba Security Response Center) where the issue will be triaged appropriately. + +Thank you in advance for helping to keep Higress secure. diff --git a/VERSION b/VERSION index 8b20e48523..ff0ad4c24c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.7.0 +v1.0.0-rc diff --git a/cmd/hgctl/main.go b/cmd/hgctl/main.go new file mode 100644 index 0000000000..eb3e3c17f6 --- /dev/null +++ b/cmd/hgctl/main.go @@ -0,0 +1,29 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "os" + + "github.com/alibaba/higress/pkg/cmd/hgctl" +) + +func main() { + if err := hgctl.GetRootCommand().Execute(); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/cmd/higress/main.go b/cmd/higress/main.go index cc0357cb73..3c78b8991e 100644 --- a/cmd/higress/main.go +++ b/cmd/higress/main.go @@ -17,119 +17,13 @@ package main import ( "fmt" "os" - "time" - "github.com/spf13/cobra" - "istio.io/istio/pilot/pkg/features" - "istio.io/istio/pkg/cmd" - "istio.io/istio/pkg/config/constants" - "istio.io/istio/pkg/keepalive" - "istio.io/pkg/log" - "istio.io/pkg/version" - - "github.com/alibaba/higress/pkg/bootstrap" - innerconstants "github.com/alibaba/higress/pkg/config/constants" + "github.com/alibaba/higress/pkg/cmd" ) -var ( - serverArgs *bootstrap.ServerArgs - loggingOptions = log.DefaultOptions() - - serverProvider = func(args *bootstrap.ServerArgs) (bootstrap.ServerInterface, error) { - return bootstrap.NewServer(serverArgs) - } - - waitForMonitorSignal = func(stop chan struct{}) { - cmd.WaitSignal(stop) - } - - rootCmd = &cobra.Command{ - Use: "higress", - } - - serveCmd = &cobra.Command{ - Use: "serve", - Aliases: []string{"serve"}, - Short: "Starts the higress ingress controller", - Example: "higress serve", - PreRunE: func(c *cobra.Command, args []string) error { - return log.Configure(loggingOptions) - }, - RunE: func(c *cobra.Command, args []string) error { - cmd.PrintFlags(c.Flags()) - log.Infof("Version %s", version.Info.String()) - - stop := make(chan struct{}) - - server, err := serverProvider(serverArgs) - if err != nil { - return fmt.Errorf("fail to create higress server: %v", err) - } - - if err := server.Start(stop); err != nil { - return fmt.Errorf("fail to start higress server: %v", err) - } - - waitForMonitorSignal(stop) - - server.WaitUntilCompletion() - return nil - }, - } -) - -func init() { - serverArgs = &bootstrap.ServerArgs{ - Debug: true, - NativeIstio: true, - HttpAddress: ":8888", - GrpcAddress: ":15051", - GrpcKeepAliveOptions: keepalive.DefaultOption(), - XdsOptions: bootstrap.XdsOptions{ - DebounceAfter: features.DebounceAfter, - DebounceMax: features.DebounceMax, - EnableEDSDebounce: features.EnableEDSDebounce, - }, - } - - serveCmd.PersistentFlags().StringVar(&serverArgs.GatewaySelectorKey, "gatewaySelectorKey", "higress", "gateway resource selector label key") - serveCmd.PersistentFlags().StringVar(&serverArgs.GatewaySelectorValue, "gatewaySelectorValue", "higress-gateway", "gateway resource selector label value") - serveCmd.PersistentFlags().BoolVar(&serverArgs.EnableStatus, "enableStatus", true, "enable the ingress status syncer which use to update the ip in ingress's status") - serveCmd.PersistentFlags().StringVar(&serverArgs.IngressClass, "ingressClass", innerconstants.DefaultIngressClass, "if not empty, only watch the ingresses have the specified class, otherwise watch all ingresses") - serveCmd.PersistentFlags().StringVar(&serverArgs.WatchNamespace, "watchNamespace", "", "if not empty, only wath the ingresses in the specified namespace, otherwise watch in all namespacees") - serveCmd.PersistentFlags().BoolVar(&serverArgs.Debug, "debug", serverArgs.Debug, "if true, enables more debug http api") - serveCmd.PersistentFlags().StringVar(&serverArgs.HttpAddress, "httpAddress", serverArgs.HttpAddress, "the http address") - serveCmd.PersistentFlags().StringVar(&serverArgs.GrpcAddress, "grpcAddress", serverArgs.GrpcAddress, "the grpc address") - serveCmd.PersistentFlags().BoolVar(&serverArgs.KeepStaleWhenEmpty, "keepStaleWhenEmpty", false, "keep the stale service entry when there are no endpoints in the service") - serveCmd.PersistentFlags().StringVar(&serverArgs.RegistryOptions.ClusterRegistriesNamespace, "clusterRegistriesNamespace", - serverArgs.RegistryOptions.ClusterRegistriesNamespace, "Namespace for ConfigMap which stores clusters configs") - serveCmd.PersistentFlags().StringVar(&serverArgs.RegistryOptions.KubeConfig, "kubeconfig", "", - "Use a Kubernetes configuration file instead of in-cluster configuration") - // RegistryOptions Controller options - serveCmd.PersistentFlags().DurationVar(&serverArgs.RegistryOptions.KubeOptions.ResyncPeriod, "resync", 60*time.Second, - "Controller resync interval") - serveCmd.PersistentFlags().StringVar(&serverArgs.RegistryOptions.KubeOptions.DomainSuffix, "domain", constants.DefaultKubernetesDomain, - "DNS domain suffix") - serveCmd.PersistentFlags().StringVar((*string)(&serverArgs.RegistryOptions.KubeOptions.ClusterID), "clusterID", "Kubernetes", - "The ID of the cluster that this instance resides") - serveCmd.PersistentFlags().StringToStringVar(&serverArgs.RegistryOptions.KubeOptions.ClusterAliases, "clusterAliases", map[string]string{}, - "Alias names for clusters") - serveCmd.PersistentFlags().Float32Var(&serverArgs.RegistryOptions.KubeOptions.KubernetesAPIQPS, "kubernetesApiQPS", 80.0, - "Maximum QPS when communicating with the kubernetes API") - - serveCmd.PersistentFlags().IntVar(&serverArgs.RegistryOptions.KubeOptions.KubernetesAPIBurst, "kubernetesApiBurst", 160, - "Maximum burst for throttle when communicating with the kubernetes API") - - loggingOptions.AttachCobraFlags(serveCmd) - serverArgs.GrpcKeepAliveOptions.AttachCobraFlags(serveCmd) - - rootCmd.AddCommand(serveCmd) -} - func main() { - log.EnableKlogWithCobra() - if err := rootCmd.Execute(); err != nil { - log.Error(err) - os.Exit(-1) + if err := cmd.GetRootCommand().Execute(); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) } } diff --git a/docs/images/domain.gif b/docs/images/domain.gif new file mode 100644 index 0000000000..34007ce65b Binary files /dev/null and b/docs/images/domain.gif differ diff --git a/docs/images/monitor.gif b/docs/images/monitor.gif new file mode 100644 index 0000000000..226e6eef10 Binary files /dev/null and b/docs/images/monitor.gif differ diff --git a/docs/images/plugin.gif b/docs/images/plugin.gif new file mode 100644 index 0000000000..f6754a61da Binary files /dev/null and b/docs/images/plugin.gif differ diff --git a/docs/images/route-service.gif b/docs/images/route-service.gif new file mode 100644 index 0000000000..64a5203022 Binary files /dev/null and b/docs/images/route-service.gif differ diff --git a/docs/images/service-source.gif b/docs/images/service-source.gif new file mode 100644 index 0000000000..7b5a10a04a Binary files /dev/null and b/docs/images/service-source.gif differ diff --git a/envoy/1.20/patches/envoy/20230408-basic-auth.patch b/envoy/1.20/patches/envoy/20230408-basic-auth.patch new file mode 100644 index 0000000000..75a68322d2 --- /dev/null +++ b/envoy/1.20/patches/envoy/20230408-basic-auth.patch @@ -0,0 +1,55 @@ +diff -Naur envoy/bazel/envoy_binary.bzl envoy-new/bazel/envoy_binary.bzl +--- envoy/bazel/envoy_binary.bzl 2023-04-08 20:52:57.041729111 +0800 ++++ envoy-new/bazel/envoy_binary.bzl 2023-04-08 20:50:53.657603065 +0800 +@@ -80,7 +80,7 @@ + "@envoy//bazel:boringssl_fips": [], + "@envoy//bazel:windows_x86_64": [], + "//conditions:default": ["-pie"], +- }) + _envoy_select_exported_symbols(["-Wl,-E"]) ++ }) + _envoy_select_exported_symbols(["-Wl,-E"]) + envoy_select_alimesh(["-lcrypt"]) + + def _envoy_stamped_deps(): + return select({ +diff -Naur envoy/bazel/repositories.bzl envoy-new/bazel/repositories.bzl +--- envoy/bazel/repositories.bzl 2023-04-08 20:52:57.085730582 +0800 ++++ envoy-new/bazel/repositories.bzl 2023-04-08 20:27:20.110335884 +0800 +@@ -272,6 +272,8 @@ + actual = "@bazel_tools//tools/cpp/runfiles", + ) + ++ _com_github_higress_wasm_extensions() ++ + def _boringssl(): + external_http_archive( + name = "boringssl", +@@ -1066,6 +1068,17 @@ + actual = "@com_github_wasm_c_api//:wasmtime_lib", + ) + ++def _com_github_higress_wasm_extensions(): ++ native.local_repository( ++ name = "com_github_higress_wasm_extensions", ++ path = "../../wasm-cpp", ++ ) ++ ++ native.bind( ++ name = "basic_auth_lib", ++ actual = "@com_github_higress_wasm_extensions//extensions/basic_auth:basic_auth_lib", ++ ) ++ + def _rules_fuzzing(): + external_http_archive( + name = "rules_fuzzing", +diff -Naur envoy/source/exe/BUILD envoy-new/source/exe/BUILD +--- envoy/source/exe/BUILD 2023-04-08 20:52:57.053729512 +0800 ++++ envoy-new/source/exe/BUILD 2023-04-08 19:48:37.420667254 +0800 +@@ -43,6 +43,9 @@ + "//bazel:darwin": envoy_all_extensions(DARWIN_SKIP_TARGETS), + "//conditions:default": envoy_all_extensions(), + }), ++ alimesh_deps = [ ++ "//external:basic_auth_lib", ++ ], + ) + + envoy_cc_library( diff --git a/go.mod b/go.mod index 1c62c7c9bc..9aa6ada9e0 100644 --- a/go.mod +++ b/go.mod @@ -27,11 +27,14 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/nacos-group/nacos-sdk-go v1.0.8 github.com/nacos-group/nacos-sdk-go/v2 v2.1.2 + github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.2.1 + github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.1 go.uber.org/atomic v1.9.0 google.golang.org/grpc v1.48.0 google.golang.org/protobuf v1.28.0 + gopkg.in/yaml.v2 v2.4.0 istio.io/api v0.0.0-20211122181927-8da52c66ff23 istio.io/client-go v1.12.0-rc.1.0.20211118171212-b744b6f111e4 istio.io/gogo-genproto v0.0.0-20211115195057-0e34bdd2be67 @@ -39,8 +42,11 @@ require ( istio.io/pkg v0.0.0-20211115195056-e379f31ee62a k8s.io/api v0.22.2 k8s.io/apimachinery v0.22.2 + k8s.io/cli-runtime v0.22.2 k8s.io/client-go v0.22.2 + k8s.io/kubectl v0.22.2 sigs.k8s.io/controller-runtime v0.10.2 + sigs.k8s.io/yaml v1.3.0 ) require ( @@ -142,7 +148,6 @@ require ( github.com/opencontainers/runc v1.0.2 // indirect github.com/openshift/api v0.0.0-20200713203337-b2494ecb17dd // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_model v0.2.0 // indirect @@ -154,7 +159,6 @@ require ( github.com/sirupsen/logrus v1.8.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/cast v1.3.1 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 // indirect github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect github.com/yl2chen/cidranger v1.0.2 // indirect @@ -181,21 +185,17 @@ require ( gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.22.2 // indirect - k8s.io/cli-runtime v0.22.2 // indirect k8s.io/component-base v0.22.2 // indirect k8s.io/klog/v2 v2.10.0 // indirect k8s.io/kube-openapi v0.0.0-20211020163157-7327e2aaee2b // indirect - k8s.io/kubectl v0.22.2 // indirect k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect sigs.k8s.io/gateway-api v0.4.0 // indirect sigs.k8s.io/kustomize/api v0.8.11 // indirect sigs.k8s.io/kustomize/kyaml v0.11.0 // indirect sigs.k8s.io/mcs-api v0.1.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect ) replace github.com/dubbogo/gost => github.com/johnlanni/gost v1.11.23-0.20220713132522-0967a24036c6 diff --git a/helm/core/Chart.yaml b/helm/core/Chart.yaml index 8bbf970da5..17ab3356ea 100644 --- a/helm/core/Chart.yaml +++ b/helm/core/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: 0.7.0 +appVersion: 1.0.0-rc description: Helm chart for deploying higress gateways icon: https://higress.io/img/higress_logo_small.png keywords: @@ -9,4 +9,4 @@ name: higress-core sources: - http://github.com/alibaba/higress type: application -version: 0.7.0 +version: 1.0.0-rc diff --git a/helm/core/templates/_helpers.tpl b/helm/core/templates/_helpers.tpl index 8a10b6c6de..ceb713dad9 100644 --- a/helm/core/templates/_helpers.tpl +++ b/helm/core/templates/_helpers.tpl @@ -86,4 +86,12 @@ higress: {{ include "controller.name" . }} {{- else }} {{- .Values.controller.serviceAccount.name | default "default" }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} + +{{- define "controller.jwtPolicy" -}} +{{- if semverCompare ">=1.21-0" .Capabilities.KubeVersion.GitVersion }} +{{- .Values.global.jwtPolicy | default "third-party-jwt" }} +{{- else }} +{{- print "first-party-jwt" }} +{{- end }} +{{- end }} diff --git a/helm/core/templates/configmap.yaml b/helm/core/templates/configmap.yaml index 8c1696f5bc..1eb9775e78 100644 --- a/helm/core/templates/configmap.yaml +++ b/helm/core/templates/configmap.yaml @@ -4,6 +4,7 @@ trustDomain: "cluster.local" accessLogEncoding: TEXT accessLogFile: "/dev/stdout" + ingressControllerMode: "OFF" accessLogFormat: '{"authority":"%REQ(:AUTHORITY)%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","duration":"%DURATION%","istio_policy_status":"%DYNAMIC_METADATA(istio.mixer:status)%","method":"%REQ(:METHOD)%","path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","request_id":"%REQ(X-REQUEST-ID)%","requested_server_name":"%REQUESTED_SERVER_NAME%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","route_name":"%ROUTE_NAME%","start_time":"%START_TIME%","trace_id":"%REQ(X-B3-TRACEID)%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_host":"%UPSTREAM_HOST%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","upstream_service_time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","user_agent":"%REQ(USER-AGENT)%","x_forwarded_for":"%REQ(X-FORWARDED-FOR)%"} ' @@ -28,6 +29,9 @@ {{- end }} defaultConfig: + {{- if .Values.global.disableAlpnH2 }} + disableAlpnH2: true + {{- end }} {{- if .Values.global.meshID }} meshId: {{ .Values.global.meshID }} {{- end }} diff --git a/helm/core/templates/controller-deployment.yaml b/helm/core/templates/controller-deployment.yaml index 9c1827d39c..f2907d9638 100644 --- a/helm/core/templates/controller-deployment.yaml +++ b/helm/core/templates/controller-deployment.yaml @@ -80,7 +80,7 @@ spec: - name: REVISION value: "{{ .Values.revision | default `default` }}" - name: JWT_POLICY - value: {{ .Values.global.jwtPolicy }} + value: {{ include "controller.jwtPolicy" . }} - name: PILOT_CERT_PROVIDER value: "istiod" - name: POD_NAME @@ -128,7 +128,7 @@ spec: - name: CUSTOM_CA_CERT_NAME value: "higress-ca-root-cert" {{- end }} - {{- if not .Values.global.kind }} + {{- if not (or .Values.global.local .Values.global.kind) }} resources: {{- if .Values.pilot.resources }} {{ toYaml .Values.pilot.resources | trim | indent 12 }} @@ -147,7 +147,7 @@ spec: volumeMounts: - name: config mountPath: /etc/istio/config - {{- if eq .Values.global.jwtPolicy "third-party-jwt" }} + {{- if eq (include "controller.jwtPolicy" .) "third-party-jwt" }} - name: istio-token mountPath: /var/run/secrets/tokens readOnly: true @@ -173,12 +173,12 @@ spec: - "serve" - --gatewaySelectorKey=higress - --gatewaySelectorValue={{ .Release.Namespace }}-{{ include "gateway.name" . }} - {{- if not .Values.enableStatus }} - - --enableStatus={{ .Values.enableStatus }} + {{- if not .Values.global.enableStatus }} + - --enableStatus={{ .Values.global.enableStatus }} {{- end }} - - --ingressClass={{ .Values.ingressClass }} - {{- if .Values.watchNamespace }} - - --watchNamespace={{ .Values.watchNamespace }} + - --ingressClass={{ .Values.global.ingressClass }} + {{- if .Values.global.watchNamespace }} + - --watchNamespace={{ .Values.global.watchNamespace }} {{- end }} env: - name: POD_NAME @@ -210,7 +210,7 @@ spec: {{- end }} readinessProbe: {{- toYaml .Values.controller.probe | nindent 12 }} - {{- if not .Values.global.kind }} + {{- if not (or .Values.global.local .Values.global.kind) }} resources: {{- toYaml .Values.controller.resources | nindent 12 }} {{- end }} @@ -241,7 +241,7 @@ spec: - emptyDir: medium: Memory name: local-certs - {{- if eq .Values.global.jwtPolicy "third-party-jwt" }} + {{- if eq (include "controller.jwtPolicy" .) "third-party-jwt" }} - name: istio-token projected: sources: @@ -249,6 +249,7 @@ spec: audience: {{ .Values.global.sds.token.aud }} expirationSeconds: 43200 path: istio-token + {{- end }} # Optional: user-generated root - name: cacerts secret: @@ -264,4 +265,3 @@ spec: name: pilot-jwks-extra-cacerts{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} {{- end }} {{- end }} - {{- end }} diff --git a/helm/core/templates/deployment.yaml b/helm/core/templates/deployment.yaml index 933bc7ce0a..4f66c276cf 100644 --- a/helm/core/templates/deployment.yaml +++ b/helm/core/templates/deployment.yaml @@ -9,7 +9,7 @@ metadata: {{- .Values.gateway.annotations | toYaml | nindent 4 }} spec: {{- if not .Values.gateway.autoscaling.enabled }} - {{- if not .Values.global.kind }} + {{- if not (or .Values.global.local .Values.global.kind) }} replicas: {{ .Values.gateway.replicas }} {{- else }} replicas: 1 @@ -21,7 +21,7 @@ spec: strategy: rollingUpdate: maxSurge: {{ .Values.gateway.rollingMaxSurge }} - {{- if .Values.global.kind }} + {{- if or .Values.global.local .Values.global.kind }} maxUnavailable: 100% {{- else }} maxUnavailable: {{ .Values.gateway.rollingMaxUnavailable }} @@ -129,7 +129,7 @@ spec: - name: ENABLE_INGRESS_GATEWAY_SDS value: "false" - name: JWT_POLICY - value: {{ .Values.global.jwtPolicy }} + value: {{ include "controller.jwtPolicy" . }} - name: ISTIO_META_HTTP10 value: "1" - name: ISTIO_META_CLUSTER_ID @@ -152,7 +152,7 @@ spec: - containerPort: 15090 protocol: TCP name: http-envoy-prom - {{- if .Values.global.kind }} + {{- if or .Values.global.local .Values.global.kind }} - containerPort: 80 hostPort: 80 name: http @@ -172,12 +172,12 @@ spec: periodSeconds: 2 successThreshold: 1 timeoutSeconds: 3 - {{- if not .Values.global.kind }} + {{- if not (or .Values.global.local .Values.global.kind) }} resources: {{- toYaml .Values.gateway.resources | nindent 12 }} {{- end }} volumeMounts: - {{- if eq .Values.global.jwtPolicy "third-party-jwt" }} + {{- if eq (include "controller.jwtPolicy" .) "third-party-jwt" }} - name: istio-token mountPath: /var/run/secrets/tokens readOnly: true @@ -213,7 +213,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} volumes: - {{- if eq .Values.global.jwtPolicy "third-party-jwt" }} + {{- if eq (include "controller.jwtPolicy" .) "third-party-jwt" }} - name: istio-token projected: sources: diff --git a/helm/core/values.yaml b/helm/core/values.yaml index 6c44900196..42e0cb7226 100644 --- a/helm/core/values.yaml +++ b/helm/core/values.yaml @@ -1,9 +1,21 @@ revision: "" global: + # IngressClass filters which ingress resources the higress controller watches. + # The default ingress class is higress. + # There are some special cases for special ingress class. + # 1. When the ingress class is set as nginx, the higress controller will watch ingress + # resources with the nginx ingress class or without any ingress class. + # 2. When the ingress class is set empty, the higress controller will watch all ingress + # resources in the k8s cluster. + ingressClass: "higress" + watchNamespace: "" + disableAlpnH2: true + enableStatus: true # whether to use autoscaling/v2 template for HPA settings # for internal usage only, not to be configured by users. autoscalingv2API: true - kind: false + local: false # When deploying to a local cluster (e.g.: kind cluster), set this to true. + kind: false # Deprecated. Please use "global.local" instead. Will be removed later. enableIstioAPI: false # Deprecated enableHigressIstio: false @@ -33,7 +45,7 @@ global: # Dev builds from prow are on gcr.io hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress # Default tag for Istio images. - tag: 0.7.0 + tag: 1.0.0-rc # Specify image pull policy if default behavior isn't desired. # Default behavior: latest images will be Always else IfNotPresent. @@ -322,16 +334,6 @@ global: caName: "" hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress -# IngressClass filters which ingress resources the higress controller watches. -# The default ingress class is higress. -# There are some special cases for special ingress class. -# 1. When the ingress class is set as nginx, the higress controller will watch ingress -# resources with the nginx ingress class or without any ingress class. -# 2. When the ingress class is set empty, the higress controller will watch all ingress -# resources in the k8s cluster. -ingressClass: "higress" -watchNamespace: "" -enableStatus: true clusterName: "" # meshConfig defines runtime configuration of components, including Istiod and istio-agent behavior # See https://istio.io/docs/reference/config/istio.mesh.v1alpha1/ for all available options @@ -367,7 +369,7 @@ gateway: name: "higress-gateway" replicas: 2 image: gateway - tag: "0.7.0" + tag: "1.0.0-rc" # revision declares which revision this gateway is a part of revision: "" @@ -455,7 +457,7 @@ controller: name: "higress-controller" replicas: 1 image: higress - tag: "0.7.0" + tag: "1.0.0-rc" env: {} labels: {} @@ -545,7 +547,7 @@ pilot: rollingMaxUnavailable: 25% hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress - tag: 0.7.0 + tag: 1.0.0-rc # Can be a full hub/image:tag image: pilot diff --git a/helm/higress/Chart.lock b/helm/higress/Chart.lock index 33a2b53222..7270dfa185 100644 --- a/helm/higress/Chart.lock +++ b/helm/higress/Chart.lock @@ -1,9 +1,9 @@ dependencies: - name: higress-core repository: file://../core - version: 0.7.0 + version: 1.0.0-rc - name: higress-console repository: https://higress.io/helm-charts/ - version: 0.1.0 -digest: sha256:3fd6cfb0fd10178927569d57e0cbff5250870dd677cbf30995c49ced83e38f7c -generated: "2023-03-15T15:09:02.878072+08:00" + version: 0.2.0 +digest: sha256:0a34765ab2125ccf397e81566b4d81a8dc0742a2477d225aad77d9450e4add94 +generated: "2023-04-08T23:17:37.193119+08:00" diff --git a/helm/higress/Chart.yaml b/helm/higress/Chart.yaml index 09cbf24a01..05bff7ae37 100644 --- a/helm/higress/Chart.yaml +++ b/helm/higress/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: 0.7.0 +appVersion: 1.0.0-rc description: Helm chart for deploying higress gateways icon: https://higress.io/img/higress_logo_small.png keywords: @@ -11,9 +11,9 @@ sources: dependencies: - name: higress-core repository: "file://../core" - version: 0.7.0 + version: 1.0.0-rc - name: higress-console repository: "https://higress.io/helm-charts/" - version: 0.1.0 + version: 0.2.0 type: application -version: 0.7.0 +version: 1.0.0-rc diff --git a/istio/1.12/patches/istio/20230408-ignore-ns.patch b/istio/1.12/patches/istio/20230408-ignore-ns.patch new file mode 100644 index 0000000000..940ad5790d --- /dev/null +++ b/istio/1.12/patches/istio/20230408-ignore-ns.patch @@ -0,0 +1,54 @@ +diff -Naur istio/pilot/pkg/networking/core/v1alpha3/route/route.go istio-new/pilot/pkg/networking/core/v1alpha3/route/route.go +--- istio/pilot/pkg/networking/core/v1alpha3/route/route.go 2023-04-08 16:02:02.000000000 +0800 ++++ istio-new/pilot/pkg/networking/core/v1alpha3/route/route.go 2023-04-07 18:19:20.000000000 +0800 +@@ -1049,6 +1049,10 @@ + out.QueryParameterMatchSpecifier = &route.QueryParameterMatcher_StringMatch{ + StringMatch: &matcher.StringMatcher{MatchPattern: &matcher.StringMatcher_Exact{Exact: m.Exact}}, + } ++ case *networking.StringMatch_Prefix: ++ out.QueryParameterMatchSpecifier = &route.QueryParameterMatcher_StringMatch{ ++ StringMatch: &matcher.StringMatcher{MatchPattern: &matcher.StringMatcher_Prefix{Prefix: m.Prefix}}, ++ } + case *networking.StringMatch_Regex: + out.QueryParameterMatchSpecifier = &route.QueryParameterMatcher_StringMatch{ + StringMatch: &matcher.StringMatcher{ +diff -Naur istio/pilot/pkg/serviceregistry/kube/controller/namespacecontroller.go istio-new/pilot/pkg/serviceregistry/kube/controller/namespacecontroller.go +--- istio/pilot/pkg/serviceregistry/kube/controller/namespacecontroller.go 2023-04-08 16:02:02.000000000 +0800 ++++ istio-new/pilot/pkg/serviceregistry/kube/controller/namespacecontroller.go 2023-04-08 14:35:57.000000000 +0800 +@@ -16,6 +16,7 @@ + + import ( + "fmt" ++ "os" + "time" + + v1 "k8s.io/api/core/v1" +@@ -171,9 +172,16 @@ + return k8s.InsertDataToConfigMap(nc.client, nc.configmapLister, meta, nc.caBundleWatcher.GetCABundle()) + } + ++var podNs = os.Getenv("POD_NAMESPACE") ++ + // On namespace change, update the config map. + // If terminating, this will be skipped + func (nc *NamespaceController) namespaceChange(ns *v1.Namespace) { ++ // Added by ingress ++ if ns.Name != podNs { ++ return ++ } ++ // End added by ingress + if ns.Status.Phase != v1.NamespaceTerminating { + nc.syncNamespace(ns.Name) + } +@@ -186,6 +194,11 @@ + log.Errorf("failed to convert to configmap: %v", err) + return + } ++ // Added by ingress ++ if cm.Namespace != podNs { ++ return ++ } ++ // End added by ingress + // This is a change to a configmap we don't watch, ignore it + if cm.Name != dynamicCACertNamespaceConfigMap { + return diff --git a/istio/1.12/patches/proxy/20230408-build-extensions.patch b/istio/1.12/patches/proxy/20230408-build-extensions.patch new file mode 100644 index 0000000000..10f199eeca --- /dev/null +++ b/istio/1.12/patches/proxy/20230408-build-extensions.patch @@ -0,0 +1,19 @@ +diff -Naur proxy/common/scripts/run.sh proxy-new/common/scripts/run.sh +--- proxy/common/scripts/run.sh 2023-04-08 21:12:05.896147208 +0800 ++++ proxy-new/common/scripts/run.sh 2023-04-08 20:33:51.935437889 +0800 +@@ -40,6 +40,7 @@ + MOUNT_ENVOY_SOURCE="${MOUNT_ENVOY_SOURCE:-`cd $MOUNT_SOURCE/../envoy;pwd`}" + MOUNT_PACKAGE_SOURCE="${MOUNT_PACKAGE_SOURCE:-`cd $MOUNT_SOURCE/../package;pwd`}" + MOUNT_ROOT_SOURCE="${MOUNT_ROOT_SOURCE:-`cd $MOUNT_SOURCE/..;pwd`}" ++MOUNT_PLUGINS_SOURCE="${MOUNT_PLUGINS_SOURCE:-`cd $MOUNT_SOURCE/../../plugins/wasm-cpp;pwd`}" + + read -ra DOCKER_RUN_OPTIONS <<< "${DOCKER_RUN_OPTIONS:-}" + +@@ -64,6 +65,7 @@ + --mount "type=bind,source=${MOUNT_SOURCE},destination=/work" \ + --mount "type=bind,source=${MOUNT_ROOT_SOURCE}/..,destination=/parent" \ + --mount "type=bind,source=${MOUNT_ENVOY_SOURCE},destination=/envoy" \ ++ --mount "type=bind,source=${MOUNT_PLUGINS_SOURCE},destination=/wasm-cpp" \ + --mount "type=volume,source=go,destination=/go" \ + --mount "type=volume,source=gocache,destination=/gocache" \ + --mount "type=volume,source=cache,destination=/home/.cache" \ diff --git a/pkg/cmd/hgctl/configBootstrap.go b/pkg/cmd/hgctl/configBootstrap.go new file mode 100644 index 0000000000..23111fe641 --- /dev/null +++ b/pkg/cmd/hgctl/configBootstrap.go @@ -0,0 +1,65 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "fmt" + + "github.com/spf13/cobra" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func bootstrapConfigCmd() *cobra.Command { + configCmd := &cobra.Command{ + Use: "bootstrap ", + Aliases: []string{"b"}, + Short: "Retrieves bootstrap Envoy xDS resources from the specified Higress Gateway Pod", + Long: `Retrieves information about bootstrap Envoy xDS resources from the specified Higress Gateway Pod`, + Example: ` # Retrieve summary about bootstrap configuration for a given pod from Envoy. + hgctl gateway-config bootstrap -n + + # Retrieve full configuration dump as YAML + hgctl gateway-config bootstrap -n -o yaml + + # Retrieve full configuration dump with short syntax + hgctl gc b -n +`, + Run: func(c *cobra.Command, args []string) { + cmdutil.CheckErr(runBootstrapConfig(c, args)) + }, + } + + return configCmd +} + +func runBootstrapConfig(c *cobra.Command, args []string) error { + configDump, err := retrieveConfigDump(args, false) + if err != nil { + return err + } + + bootstrap, err := GetXDSResource(BootstrapEnvoyConfigType, configDump) + if err != nil { + return err + } + + out, err := formatGatewayConfig(bootstrap, output) + if err != nil { + return err + } + + _, err = fmt.Fprintln(c.OutOrStdout(), string(out)) + return err +} diff --git a/pkg/cmd/hgctl/configCluster.go b/pkg/cmd/hgctl/configCluster.go new file mode 100644 index 0000000000..3df8fb048f --- /dev/null +++ b/pkg/cmd/hgctl/configCluster.go @@ -0,0 +1,64 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package hgctl + +import ( + "fmt" + + "github.com/spf13/cobra" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func clusterConfigCmd() *cobra.Command { + configCmd := &cobra.Command{ + Use: "cluster ", + Short: "Retrieves cluster Envoy xDS resources from the specified Higress Gateway Pod", + Aliases: []string{"c"}, + Long: `Retrieves information about cluster Envoy xDS resources from the specified Higress Gateway Pod`, + Example: ` # Retrieve summary about cluster configuration for a given pod from Envoy. + hgctl gateway-config cluster -n + + # Retrieve full configuration dump as YAML + hgctl gateway-config cluster -n -o yaml + + # Retrieve full configuration dump with short syntax + hgctl gc c -n +`, + Run: func(c *cobra.Command, args []string) { + cmdutil.CheckErr(runClusterConfig(c, args)) + }, + } + + return configCmd +} + +func runClusterConfig(c *cobra.Command, args []string) error { + configDump, err := retrieveConfigDump(args, false) + if err != nil { + return err + } + + cluster, err := GetXDSResource(ClusterEnvoyConfigType, configDump) + if err != nil { + return err + } + + out, err := formatGatewayConfig(cluster, output) + if err != nil { + return err + } + + _, err = fmt.Fprintln(c.OutOrStdout(), string(out)) + return err +} diff --git a/pkg/cmd/hgctl/configCmd.go b/pkg/cmd/hgctl/configCmd.go new file mode 100644 index 0000000000..0075546447 --- /dev/null +++ b/pkg/cmd/hgctl/configCmd.go @@ -0,0 +1,79 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "fmt" + + "github.com/alibaba/higress/pkg/cmd/options" + "github.com/spf13/cobra" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func newConfigCommand() *cobra.Command { + cfgCommand := &cobra.Command{ + Use: "gateway-config", + Aliases: []string{"gc"}, + Short: "Retrieve Higress Gateway configuration.", + Long: "Retrieve information about Higress Gateway Configuration.", + } + + cfgCommand.AddCommand(allConfigCmd()) + cfgCommand.AddCommand(bootstrapConfigCmd()) + cfgCommand.AddCommand(clusterConfigCmd()) + cfgCommand.AddCommand(endpointConfigCmd()) + cfgCommand.AddCommand(listenerConfigCmd()) + cfgCommand.AddCommand(routeConfigCmd()) + + flags := cfgCommand.Flags() + options.AddKubeConfigFlags(flags) + + cfgCommand.PersistentFlags().StringVarP(&output, "output", "o", "json", "One of 'yaml' or 'json'") + cfgCommand.PersistentFlags().StringVarP(&podNamespace, "namespace", "n", "higress-system", "Namespace where envoy proxy pod are installed.") + + return cfgCommand +} + +func allConfigCmd() *cobra.Command { + configCmd := &cobra.Command{ + Use: "all ", + Short: "Retrieves all Envoy xDS resources from the specified Higress Gateway Pod", + Long: `Retrieves information about all Envoy xDS resources from the specified Higress Gateway Pod`, + Example: ` # Retrieve summary about all configuration for a given pod from Envoy. + hgctl gateway-config all -n + + # Retrieve full configuration dump as YAML + hgctl gateway-config all -n -o yaml + + # Retrieve full configuration dump with short syntax + hgctl gc all -n +`, + Run: func(c *cobra.Command, args []string) { + cmdutil.CheckErr(runAllConfig(c, args)) + }, + } + + return configCmd +} + +func runAllConfig(c *cobra.Command, args []string) error { + configDump, err := retrieveConfigDump(args, true) + if err != nil { + return err + } + + _, err = fmt.Fprintln(c.OutOrStdout(), string(configDump)) + return err +} diff --git a/pkg/cmd/hgctl/configEndpoint.go b/pkg/cmd/hgctl/configEndpoint.go new file mode 100644 index 0000000000..80666e878c --- /dev/null +++ b/pkg/cmd/hgctl/configEndpoint.go @@ -0,0 +1,65 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "fmt" + + "github.com/spf13/cobra" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func endpointConfigCmd() *cobra.Command { + configCmd := &cobra.Command{ + Use: "endpoint ", + Short: "Retrieves endpoint Envoy xDS resources from the specified Higress Gateway Pod", + Aliases: []string{"e"}, + Long: `Retrieves information about endpoint Envoy xDS resources from the specified Higress Gateway Pod`, + Example: ` # Retrieve summary about endpoint configuration for a given pod from Envoy. + hgctl gateway-config endpoint -n + + # Retrieve configuration dump as YAML + hgctl gateway-config endpoint -n -o yaml + + # Retrieve configuration dump with short syntax + hgctl gc e -n +`, + Run: func(c *cobra.Command, args []string) { + cmdutil.CheckErr(runEndpointConfig(c, args)) + }, + } + + return configCmd +} + +func runEndpointConfig(c *cobra.Command, args []string) error { + configDump, err := retrieveConfigDump(args, true) + if err != nil { + return err + } + + endpoint, err := GetXDSResource(EndpointEnvoyConfigType, configDump) + if err != nil { + return err + } + + out, err := formatGatewayConfig(endpoint, output) + if err != nil { + return err + } + + _, err = fmt.Fprintln(c.OutOrStdout(), string(out)) + return err +} diff --git a/pkg/cmd/hgctl/configListener.go b/pkg/cmd/hgctl/configListener.go new file mode 100644 index 0000000000..22978fdec1 --- /dev/null +++ b/pkg/cmd/hgctl/configListener.go @@ -0,0 +1,65 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "fmt" + + "github.com/spf13/cobra" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func listenerConfigCmd() *cobra.Command { + configCmd := &cobra.Command{ + Use: "listener ", + Aliases: []string{"l"}, + Short: "Retrieves listener Envoy xDS resources from the specified Higress Gateway Pod", + Long: `Retrieves information about listener Envoy xDS resources from the specified Higress Gateway Pod`, + Example: ` # Retrieve summary about listener configuration for a given pod from Envoy. + hgctl gateway-config listener -n + + # Retrieve full configuration dump as YAML + hgctl gateway-config listener -n -o yaml + + # Retrieve full configuration dump with short syntax + hgctl gc l -n +`, + Run: func(c *cobra.Command, args []string) { + cmdutil.CheckErr(runListenerConfig(c, args)) + }, + } + + return configCmd +} + +func runListenerConfig(c *cobra.Command, args []string) error { + configDump, err := retrieveConfigDump(args, false) + if err != nil { + return err + } + + listener, err := GetXDSResource(ListenerEnvoyConfigType, configDump) + if err != nil { + return err + } + + out, err := formatGatewayConfig(listener, output) + if err != nil { + return err + } + + _, err = fmt.Fprintln(c.OutOrStdout(), string(out)) + return err +} diff --git a/pkg/cmd/hgctl/configRetriever.go b/pkg/cmd/hgctl/configRetriever.go new file mode 100644 index 0000000000..41a3176f07 --- /dev/null +++ b/pkg/cmd/hgctl/configRetriever.go @@ -0,0 +1,151 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/alibaba/higress/pkg/cmd/hgctl/kubernetes" + "github.com/alibaba/higress/pkg/cmd/options" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/yaml" +) + +var ( + output string + podName string + podNamespace string +) + +const ( + adminPort = 15000 + containerName = "envoy" +) + +func retrieveConfigDump(args []string, includeEds bool) ([]byte, error) { + if len(args) != 0 { + podName = args[0] + } + + if podNamespace == "" { + return nil, fmt.Errorf("pod namespace is required") + } + + if podName == "" || len(args) == 0 { + c, err := kubernetes.NewCLIClient(options.DefaultConfigFlags.ToRawKubeConfigLoader()) + if err != nil { + return nil, fmt.Errorf("failed to build kubernetes client: %w", err) + } + podList, err := c.PodsForSelector(podNamespace, "app=higress-gateway") + if err != nil { + return nil, err + } + if len(podList.Items) == 0 { + return nil, fmt.Errorf("higress gateway pod is not existed in namespace %s", podNamespace) + } + + podName = podList.Items[0].GetName() + } + + fw, err := portForwarder(types.NamespacedName{ + Namespace: podNamespace, + Name: podName, + }) + if err != nil { + return nil, err + } + if err := fw.Start(); err != nil { + return nil, err + } + defer fw.Stop() + + configDump, err := fetchGatewayConfig(fw, includeEds) + if err != nil { + return nil, err + } + + return configDump, nil +} + +func portForwarder(nn types.NamespacedName) (kubernetes.PortForwarder, error) { + c, err := kubernetes.NewCLIClient(options.DefaultConfigFlags.ToRawKubeConfigLoader()) + if err != nil { + return nil, fmt.Errorf("build CLI client fail: %w", err) + } + + pod, err := c.Pod(nn) + if err != nil { + return nil, fmt.Errorf("get pod %s fail: %w", nn, err) + } + if pod.Status.Phase != "Running" { + return nil, fmt.Errorf("pod %s is not running", nn) + } + + fw, err := kubernetes.NewLocalPortForwarder(c, nn, 0, adminPort) + if err != nil { + return nil, err + } + + return fw, nil +} + +func formatGatewayConfig(configDump any, output string) ([]byte, error) { + out, err := json.MarshalIndent(configDump, "", " ") + if err != nil { + return nil, err + } + + if output == "yaml" { + out, err = yaml.JSONToYAML(out) + if err != nil { + return nil, err + } + } + + return out, nil +} + +func fetchGatewayConfig(fw kubernetes.PortForwarder, includeEds bool) ([]byte, error) { + out, err := configDumpRequest(fw.Address(), includeEds) + if err != nil { + return nil, err + } + + return out, nil +} + +func configDumpRequest(address string, includeEds bool) ([]byte, error) { + url := fmt.Sprintf("http://%s/config_dump", address) + if includeEds { + url = fmt.Sprintf("%s?include_eds", url) + } + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer func() { + _ = resp.Body.Close() + }() + + return io.ReadAll(resp.Body) +} diff --git a/pkg/cmd/hgctl/configRoute.go b/pkg/cmd/hgctl/configRoute.go new file mode 100644 index 0000000000..15f8bfc5d2 --- /dev/null +++ b/pkg/cmd/hgctl/configRoute.go @@ -0,0 +1,65 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "fmt" + + "github.com/spf13/cobra" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +func routeConfigCmd() *cobra.Command { + configCmd := &cobra.Command{ + Use: "route ", + Aliases: []string{"r"}, + Short: "Retrieves route Envoy xDS resources from the specified Higress Gateway Pod", + Long: `Retrieves information about route Envoy xDS resources from the specified Higress Gateway Pod`, + Example: ` # Retrieve summary about route configuration for a given pod from Envoy. + hgctl gateway-config route -n + + # Retrieve full configuration dump as YAML + hgctl gateway-config route -n -o yaml + + # Retrieve full configuration dump with short syntax + hgctl gc r -n +`, + Run: func(c *cobra.Command, args []string) { + cmdutil.CheckErr(runRouteConfig(c, args)) + }, + } + + return configCmd +} + +func runRouteConfig(c *cobra.Command, args []string) error { + configDump, err := retrieveConfigDump(args, false) + if err != nil { + return err + } + + route, err := GetXDSResource(RouteEnvoyConfigType, configDump) + if err != nil { + return err + } + + out, err := formatGatewayConfig(route, output) + if err != nil { + return err + } + + _, err = fmt.Fprintln(c.OutOrStdout(), string(out)) + return err +} diff --git a/pkg/cmd/hgctl/config_test.go b/pkg/cmd/hgctl/config_test.go new file mode 100644 index 0000000000..7a63b7e553 --- /dev/null +++ b/pkg/cmd/hgctl/config_test.go @@ -0,0 +1,220 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "fmt" + "log" + "net" + "net/http" + "os" + "path" + "testing" + + "github.com/alibaba/higress/pkg/cmd/hgctl/kubernetes" + "github.com/stretchr/testify/assert" +) + +var _ kubernetes.PortForwarder = &fakePortForwarder{} + +type fakePortForwarder struct { + responseBody []byte + localPort int + l net.Listener + mux *http.ServeMux +} + +func newFakePortForwarder(b []byte) (kubernetes.PortForwarder, error) { + p, err := kubernetes.LocalAvailablePort() + if err != nil { + return nil, err + } + + fw := &fakePortForwarder{ + responseBody: b, + localPort: p, + mux: http.NewServeMux(), + } + fw.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write(fw.responseBody) + }) + + return fw, nil +} + +func (fw *fakePortForwarder) Start() error { + l, err := net.Listen("tcp", fw.Address()) + if err != nil { + return err + } + fw.l = l + + go func() { + if err := http.Serve(l, fw.mux); err != nil { + log.Fatal(err) + } + }() + + return nil +} + +func (fw *fakePortForwarder) Stop() {} + +func (fw *fakePortForwarder) Address() string { + return fmt.Sprintf("localhost:%d", fw.localPort) +} + +func TestExtractAllConfigDump(t *testing.T) { + input, err := readInputConfig("in.all.json") + assert.NoError(t, err) + fw, err := newFakePortForwarder(input) + assert.NoError(t, err) + err = fw.Start() + assert.NoError(t, err) + + cases := []struct { + output string + expected string + resourceType string + }{ + { + output: "json", + expected: "out.all.json", + }, + { + output: "yaml", + expected: "out.all.yaml", + }, + } + + for _, tc := range cases { + t.Run(tc.output, func(t *testing.T) { + configDump, err := fetchGatewayConfig(fw, true) + assert.NoError(t, err) + data, err := GetXDSResource(AllEnvoyConfigType, configDump) + assert.NoError(t, err) + got, err := formatGatewayConfig(data, tc.output) + assert.NoError(t, err) + out, err := readOutputConfig(tc.expected) + assert.NoError(t, err) + if tc.output == "yaml" { + assert.YAMLEq(t, string(out), string(got)) + } else { + assert.JSONEq(t, string(out), string(got)) + } + }) + } + + fw.Stop() +} + +func TestExtractSubResourcesConfigDump(t *testing.T) { + input, err := readInputConfig("in.all.json") + assert.NoError(t, err) + fw, err := newFakePortForwarder(input) + assert.NoError(t, err) + err = fw.Start() + assert.NoError(t, err) + + cases := []struct { + output string + expected string + resourceType envoyConfigType + }{ + { + output: "json", + resourceType: BootstrapEnvoyConfigType, + expected: "out.bootstrap.json", + }, + { + output: "yaml", + resourceType: BootstrapEnvoyConfigType, + expected: "out.bootstrap.yaml", + }, { + output: "json", + resourceType: ClusterEnvoyConfigType, + expected: "out.cluster.json", + }, + { + output: "yaml", + resourceType: ClusterEnvoyConfigType, + expected: "out.cluster.yaml", + }, { + output: "json", + resourceType: ListenerEnvoyConfigType, + expected: "out.listener.json", + }, + { + output: "yaml", + resourceType: ListenerEnvoyConfigType, + expected: "out.listener.yaml", + }, { + output: "json", + resourceType: RouteEnvoyConfigType, + expected: "out.route.json", + }, + { + output: "yaml", + resourceType: RouteEnvoyConfigType, + expected: "out.route.yaml", + }, + { + output: "json", + resourceType: EndpointEnvoyConfigType, + expected: "out.endpoints.json", + }, + { + output: "yaml", + resourceType: EndpointEnvoyConfigType, + expected: "out.endpoints.yaml", + }, + } + + for _, tc := range cases { + t.Run(tc.output, func(t *testing.T) { + configDump, err := fetchGatewayConfig(fw, false) + assert.NoError(t, err) + resource, err := GetXDSResource(tc.resourceType, configDump) + assert.NoError(t, err) + got, err := formatGatewayConfig(resource, tc.output) + assert.NoError(t, err) + out, err := readOutputConfig(tc.expected) + assert.NoError(t, err) + if tc.output == "yaml" { + assert.YAMLEq(t, string(out), string(got)) + } else { + assert.JSONEq(t, string(out), string(got)) + } + }) + } + + fw.Stop() +} + +func readInputConfig(filename string) ([]byte, error) { + b, err := os.ReadFile(path.Join("testdata", "config", "input", filename)) + if err != nil { + return nil, err + } + return b, nil +} + +func readOutputConfig(filename string) ([]byte, error) { + b, err := os.ReadFile(path.Join("testdata", "config", "output", filename)) + if err != nil { + return nil, err + } + return b, nil +} diff --git a/pkg/cmd/hgctl/kubernetes/client.go b/pkg/cmd/hgctl/kubernetes/client.go new file mode 100644 index 0000000000..2093190e68 --- /dev/null +++ b/pkg/cmd/hgctl/kubernetes/client.go @@ -0,0 +1,172 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kubernetes + +import ( + "bytes" + "context" + "fmt" + "strings" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + kubescheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/remotecommand" +) + +type CLIClient interface { + // RESTConfig returns the Kubernetes rest.Config used to configure the clients. + RESTConfig() *rest.Config + + // Pod returns the pod for the given namespaced name. + Pod(namespacedName types.NamespacedName) (*corev1.Pod, error) + + // PodsForSelector finds pods matching selector. + PodsForSelector(namespace string, labelSelectors ...string) (*corev1.PodList, error) + + // PodExec takes a command and the pod data to run the command in the specified pod. + PodExec(namespacedName types.NamespacedName, container string, command string) (stdout string, stderr string, err error) +} + +var _ CLIClient = &client{} + +type client struct { + config *rest.Config + restClient *rest.RESTClient + kube kubernetes.Interface +} + +func NewCLIClient(clientConfig clientcmd.ClientConfig) (CLIClient, error) { + return newClientInternal(clientConfig) +} + +func newClientInternal(clientConfig clientcmd.ClientConfig) (*client, error) { + var ( + c client + err error + ) + + c.config, err = clientConfig.ClientConfig() + if err != nil { + return nil, err + } + setRestDefaults(c.config) + + c.restClient, err = rest.RESTClientFor(c.config) + if err != nil { + return nil, err + } + + c.kube, err = kubernetes.NewForConfig(c.config) + if err != nil { + return nil, err + } + + return &c, err +} + +func setRestDefaults(config *rest.Config) *rest.Config { + if config.GroupVersion == nil || config.GroupVersion.Empty() { + config.GroupVersion = &corev1.SchemeGroupVersion + } + if len(config.APIPath) == 0 { + if len(config.GroupVersion.Group) == 0 { + config.APIPath = "/api" + } else { + config.APIPath = "/apis" + } + } + if len(config.ContentType) == 0 { + config.ContentType = runtime.ContentTypeJSON + } + if config.NegotiatedSerializer == nil { + // This codec factory ensures the resources are not converted. Therefore, resources + // will not be round-tripped through internal versions. Defaulting does not happen + // on the client. + config.NegotiatedSerializer = serializer.NewCodecFactory(kubescheme.Scheme).WithoutConversion() + } + + return config +} + +func (c *client) RESTConfig() *rest.Config { + if c.config == nil { + return nil + } + cpy := *c.config + return &cpy +} + +func (c *client) PodsForSelector(namespace string, podSelectors ...string) (*corev1.PodList, error) { + return c.kube.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{ + LabelSelector: strings.Join(podSelectors, ","), + }) +} + +func (c *client) Pod(namespacedName types.NamespacedName) (*corev1.Pod, error) { + return c.kube.CoreV1().Pods(namespacedName.Namespace).Get(context.TODO(), namespacedName.Name, metav1.GetOptions{}) +} + +func (c *client) PodExec(namespacedName types.NamespacedName, container string, command string) (stdout string, stderr string, err error) { + defer func() { + if err != nil { + if len(stderr) > 0 { + err = fmt.Errorf("error exec into %s/%s container %s: %v\n%s", + namespacedName.Namespace, namespacedName.Name, container, err, stderr) + } else { + err = fmt.Errorf("error exec into %s/%s container %s: %v", + namespacedName.Namespace, namespacedName.Name, container, err) + } + } + }() + + req := c.restClient.Post(). + Resource("pods"). + Namespace(namespacedName.Namespace). + Name(namespacedName.Name). + SubResource("exec"). + Param("container", container). + VersionedParams(&corev1.PodExecOptions{ + Container: container, + Command: strings.Fields(command), + Stdin: false, + Stdout: true, + Stderr: true, + TTY: false, + }, kubescheme.ParameterCodec) + + exec, err := remotecommand.NewSPDYExecutor(c.config, "POST", req.URL()) + if err != nil { + return "", "", err + } + + var stdoutBuf, stderrBuf bytes.Buffer + err = exec.Stream(remotecommand.StreamOptions{ + Stdin: nil, + Stdout: &stdoutBuf, + Stderr: &stderrBuf, + Tty: false, + }) + + stdout = stdoutBuf.String() + stderr = stderrBuf.String() + return +} diff --git a/pkg/cmd/hgctl/kubernetes/port-forwarder.go b/pkg/cmd/hgctl/kubernetes/port-forwarder.go new file mode 100644 index 0000000000..5d40935655 --- /dev/null +++ b/pkg/cmd/hgctl/kubernetes/port-forwarder.go @@ -0,0 +1,155 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kubernetes + +import ( + "fmt" + "io" + "net" + "net/http" + "os" + + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/portforward" + "k8s.io/client-go/transport/spdy" +) + +const ( + DefaultLocalAddress = "localhost" +) + +func LocalAvailablePort() (int, error) { + l, err := net.Listen("tcp", fmt.Sprintf("%s:0", DefaultLocalAddress)) + if err != nil { + return 0, err + } + + return l.Addr().(*net.TCPAddr).Port, l.Close() +} + +type PortForwarder interface { + Start() error + + Stop() + + // Address returns the address of the local forwarded address. + Address() string +} + +var _ PortForwarder = &localForwarder{} + +type localForwarder struct { + types.NamespacedName + CLIClient + + localPort int + podPort int + + stopCh chan struct{} +} + +func NewLocalPortForwarder(client CLIClient, namespacedName types.NamespacedName, localPort, podPort int) (PortForwarder, error) { + f := &localForwarder{ + stopCh: make(chan struct{}), + CLIClient: client, + NamespacedName: namespacedName, + localPort: localPort, + podPort: podPort, + } + if f.localPort == 0 { + // get a random port + p, err := LocalAvailablePort() + if err != nil { + return nil, errors.Wrapf(err, "failed to get a local available port") + } + f.localPort = p + } + + return f, nil +} + +func (f *localForwarder) Start() error { + errCh := make(chan error, 1) + readyCh := make(chan struct{}, 1) + go func() { + for { + select { + case <-f.stopCh: + return + default: + } + + fw, err := f.buildKubernetesPortForwarder(readyCh) + if err != nil { + errCh <- err + return + } + + if err := fw.ForwardPorts(); err != nil { + errCh <- err + return + } + + readyCh = nil + } + + }() + + select { + case err := <-errCh: + return errors.Wrap(err, "failed to start port forwarder") + case <-readyCh: + return nil + } +} + +func (f *localForwarder) buildKubernetesPortForwarder(readyCh chan struct{}) (*portforward.PortForwarder, error) { + restClient, err := rest.RESTClientFor(f.RESTConfig()) + if err != nil { + return nil, err + } + + req := restClient.Post().Resource("pods").Namespace(f.Namespace).Name(f.Name).SubResource("portforward") + serverURL := req.URL() + + roundTripper, upgrader, err := spdy.RoundTripperFor(f.RESTConfig()) + if err != nil { + return nil, fmt.Errorf("failure creating roundtripper: %v", err) + } + + dialer := spdy.NewDialer(upgrader, &http.Client{Transport: roundTripper}, http.MethodPost, serverURL) + fw, err := portforward.NewOnAddresses(dialer, + []string{DefaultLocalAddress}, + []string{fmt.Sprintf("%d:%d", f.localPort, f.podPort)}, + f.stopCh, + readyCh, + io.Discard, + os.Stderr) + if err != nil { + return nil, fmt.Errorf("failed establishing portforward: %v", err) + } + + return fw, nil +} + +func (f *localForwarder) Stop() { + close(f.stopCh) +} + +func (f *localForwarder) Address() string { + return fmt.Sprintf("%s:%d", DefaultLocalAddress, f.localPort) +} diff --git a/pkg/cmd/hgctl/root.go b/pkg/cmd/hgctl/root.go new file mode 100644 index 0000000000..374ca58f5e --- /dev/null +++ b/pkg/cmd/hgctl/root.go @@ -0,0 +1,33 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import "github.com/spf13/cobra" + +// GetRootCommand returns the root cobra command to be executed +// by hgctl main. +func GetRootCommand() *cobra.Command { + rootCmd := &cobra.Command{ + Use: "hgctl", + Long: "A command line utility for operating Higress", + SilenceUsage: true, + DisableAutoGenTag: true, + } + + rootCmd.AddCommand(newVersionCommand()) + rootCmd.AddCommand(newConfigCommand()) + + return rootCmd +} diff --git a/pkg/cmd/hgctl/testdata/config/input/in.all.json b/pkg/cmd/hgctl/testdata/config/input/in.all.json new file mode 100644 index 0000000000..5c851a2847 --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/input/in.all.json @@ -0,0 +1,2247 @@ +{ + "configs": [{ + "@type": "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump", + "bootstrap": { + "node": { + "user_agent_name": "envoy", + "user_agent_build_version": { + "version": { + "major_number": 1, + "minor_number": 26 + }, + "metadata": { + "revision.status": "Clean", + "revision.sha": "14111e3c62d3d38b0c921cb7011fd0a94e880aed", + "ssl.version": "BoringSSL", + "build.label": "dev", + "build.type": "RELEASE" + } + }, + "extensions": [{ + "name": "envoy.filters.connection_pools.tcp.generic", + "category": "envoy.upstreams", + "type_urls": [ + "envoy.extensions.upstreams.tcp.generic.v3.GenericConnectionPoolProto" + ] + }, + { + "name": "envoy.rate_limit_descriptors.expr", + "category": "envoy.rate_limit_descriptors", + "type_urls": [ + "envoy.extensions.rate_limit_descriptors.expr.v3.Descriptor" + ] + }, + { + "name": "envoy.matching.inputs.destination_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_port", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput" + ] + }, + { + "name": "envoy.matching.inputs.direct_source_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.dns_san", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput" + ] + }, + { + "name": "envoy.matching.inputs.request_headers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestHeaderMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.request_trailers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestTrailerMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.response_headers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseHeaderMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.response_trailers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseTrailerMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.server_name", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ServerNameInput" + ] + }, + { + "name": "envoy.matching.inputs.source_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.source_port", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourcePortInput" + ] + }, + { + "name": "envoy.matching.inputs.source_type", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput" + ] + }, + { + "name": "envoy.matching.inputs.status_code_class_input", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseStatusCodeClassMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.status_code_input", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseStatusCodeMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.subject", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput" + ] + }, + { + "name": "envoy.matching.inputs.uri_san", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput" + ] + }, + { + "name": "query_params", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestQueryParamMatchInput" + ] + }, + { + "name": "envoy.tls.cert_validator.default", + "category": "envoy.tls.cert_validator" + }, + { + "name": "envoy.tls.cert_validator.spiffe", + "category": "envoy.tls.cert_validator" + }, + { + "name": "envoy.path.match.uri_template.uri_template_matcher", + "category": "envoy.path.match", + "type_urls": [ + "envoy.extensions.path.match.uri_template.v3.UriTemplateMatchConfig" + ] + }, + { + "name": "envoy.http.original_ip_detection.custom_header", + "category": "envoy.http.original_ip_detection", + "type_urls": [ + "envoy.extensions.http.original_ip_detection.custom_header.v3.CustomHeaderConfig" + ] + }, + { + "name": "envoy.http.original_ip_detection.xff", + "category": "envoy.http.original_ip_detection", + "type_urls": [ + "envoy.extensions.http.original_ip_detection.xff.v3.XffConfig" + ] + }, + { + "name": "envoy.buffer", + "category": "envoy.filters.http.upstream" + }, + { + "name": "envoy.filters.http.admission_control", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.admission_control.v3.AdmissionControl" + ] + }, + { + "name": "envoy.filters.http.buffer", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.buffer.v3.Buffer", + "envoy.extensions.filters.http.buffer.v3.BufferPerRoute" + ] + }, + { + "name": "envoy.filters.http.upstream_codec", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec" + ] + }, + { + "name": "envoy.route.early_data_policy.default", + "category": "envoy.route.early_data_policy", + "type_urls": [ + "envoy.extensions.early_data.v3.DefaultEarlyDataPolicy" + ] + }, + { + "name": "envoy.compression.brotli.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.brotli.compressor.v3.Brotli" + ] + }, + { + "name": "envoy.compression.gzip.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.gzip.compressor.v3.Gzip" + ] + }, + { + "name": "envoy.compression.zstd.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.zstd.compressor.v3.Zstd" + ] + }, + { + "name": "envoy.compression.brotli.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.brotli.decompressor.v3.Brotli" + ] + }, + { + "name": "envoy.compression.gzip.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.gzip.decompressor.v3.Gzip" + ] + }, + { + "name": "envoy.compression.zstd.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.zstd.decompressor.v3.Zstd" + ] + }, + { + "name": "envoy.wasm.runtime.null", + "category": "envoy.wasm.runtime" + }, + { + "name": "envoy.wasm.runtime.v8", + "category": "envoy.wasm.runtime" + }, + { + "name": "envoy.dog_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.graphite_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.metrics_service", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.dog_statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.DogStatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.graphite_statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.extensions.stat_sinks.graphite_statsd.v3.GraphiteStatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.hystrix", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.HystrixSink" + ] + }, + { + "name": "envoy.stat_sinks.metrics_service", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.MetricsServiceConfig" + ] + }, + { + "name": "envoy.stat_sinks.statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.StatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.wasm", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.extensions.stat_sinks.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.path.rewrite.uri_template.uri_template_rewriter", + "category": "envoy.path.rewrite", + "type_urls": [ + "envoy.extensions.path.rewrite.uri_template.v3.UriTemplateRewriteConfig" + ] + }, + { + "name": "envoy.extensions.http.custom_response.local_response_policy", + "category": "envoy.http.custom_response", + "type_urls": [ + "envoy.extensions.http.custom_response.local_response_policy.v3.LocalResponsePolicy" + ] + }, + { + "name": "envoy.extensions.http.custom_response.redirect_policy", + "category": "envoy.http.custom_response", + "type_urls": [ + "envoy.extensions.http.custom_response.redirect_policy.v3.RedirectPolicy" + ] + }, + { + "name": "envoy.matching.actions.format_string", + "category": "envoy.matching.action", + "type_urls": [ + "envoy.config.core.v3.SubstitutionFormatString" + ] + }, + { + "name": "filter-chain-name", + "category": "envoy.matching.action", + "type_urls": [ + "google.protobuf.StringValue" + ] + }, + { + "name": "envoy.quic.deterministic_connection_id_generator", + "category": "envoy.quic.connection_id_generator", + "type_urls": [ + "envoy.extensions.quic.connection_id_generator.v3.DeterministicConnectionIdGeneratorConfig" + ] + }, + { + "name": "envoy.network.dns_resolver.cares", + "category": "envoy.network.dns_resolver", + "type_urls": [ + "envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig" + ] + }, + { + "name": "envoy.network.dns_resolver.getaddrinfo", + "category": "envoy.network.dns_resolver", + "type_urls": [ + "envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig" + ] + }, + { + "name": "envoy.bootstrap.internal_listener", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.bootstrap.internal_listener.v3.InternalListener" + ] + }, + { + "name": "envoy.bootstrap.wasm", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.wasm.v3.WasmService" + ] + }, + { + "name": "envoy.extensions.network.socket_interface.default_socket_interface", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.network.socket_interface.v3.DefaultSocketInterface" + ] + }, + { + "name": "envoy.filters.listener.http_inspector", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.http_inspector.v3.HttpInspector" + ] + }, + { + "name": "envoy.filters.listener.original_dst", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.original_dst.v3.OriginalDst" + ] + }, + { + "name": "envoy.filters.listener.original_src", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.original_src.v3.OriginalSrc" + ] + }, + { + "name": "envoy.filters.listener.proxy_protocol", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol" + ] + }, + { + "name": "envoy.filters.listener.tls_inspector", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + ] + }, + { + "name": "envoy.listener.http_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.original_dst", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.original_src", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.proxy_protocol", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.tls_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.matching.common_inputs.environment_variable", + "category": "envoy.matching.common_inputs", + "type_urls": [ + "envoy.extensions.matching.common_inputs.environment_variable.v3.Config" + ] + }, + { + "name": "envoy.matching.matchers.consistent_hashing", + "category": "envoy.matching.input_matchers", + "type_urls": [ + "envoy.extensions.matching.input_matchers.consistent_hashing.v3.ConsistentHashing" + ] + }, + { + "name": "envoy.matching.matchers.ip", + "category": "envoy.matching.input_matchers", + "type_urls": [ + "envoy.extensions.matching.input_matchers.ip.v3.Ip" + ] + }, + { + "name": "envoy.grpc_credentials.aws_iam", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.grpc_credentials.default", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.grpc_credentials.file_based_metadata", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.request_id.uuid", + "category": "envoy.request_id", + "type_urls": [ + "envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig" + ] + }, + { + "name": "envoy.load_balancing_policies.least_request", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest" + ] + }, + { + "name": "envoy.load_balancing_policies.maglev", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.maglev.v3.Maglev" + ] + }, + { + "name": "envoy.load_balancing_policies.random", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.random.v3.Random" + ] + }, + { + "name": "envoy.load_balancing_policies.ring_hash", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash" + ] + }, + { + "name": "envoy.load_balancing_policies.round_robin", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin" + ] + }, + { + "name": "envoy.ip", + "category": "envoy.resolvers" + }, + { + "name": "envoy.bandwidth_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.buffer", + "category": "envoy.filters.http" + }, + { + "name": "envoy.cors", + "category": "envoy.filters.http" + }, + { + "name": "envoy.csrf", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ext_authz", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ext_proc", + "category": "envoy.filters.http" + }, + { + "name": "envoy.fault", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.adaptive_concurrency", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.adaptive_concurrency.v3.AdaptiveConcurrency" + ] + }, + { + "name": "envoy.filters.http.admission_control", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.admission_control.v3.AdmissionControl" + ] + }, + { + "name": "envoy.filters.http.alternate_protocols_cache", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.aws_lambda", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.aws_lambda.v3.Config", + "envoy.extensions.filters.http.aws_lambda.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.aws_request_signing", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning" + ] + }, + { + "name": "envoy.filters.http.bandwidth_limit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.bandwidth_limit.v3.BandwidthLimit" + ] + }, + { + "name": "envoy.filters.http.buffer", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.buffer.v3.Buffer", + "envoy.extensions.filters.http.buffer.v3.BufferPerRoute" + ] + }, + { + "name": "envoy.filters.http.cache", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cache.v3.CacheConfig" + ] + }, + { + "name": "envoy.filters.http.cdn_loop", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cdn_loop.v3.CdnLoopConfig" + ] + }, + { + "name": "envoy.filters.http.composite", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.composite.v3.Composite" + ] + }, + { + "name": "envoy.filters.http.compressor", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.compressor.v3.Compressor", + "envoy.extensions.filters.http.compressor.v3.CompressorPerRoute" + ] + }, + { + "name": "envoy.filters.http.connect_grpc_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.connect_grpc_bridge.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.cors", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cors.v3.Cors", + "envoy.extensions.filters.http.cors.v3.CorsPolicy" + ] + }, + { + "name": "envoy.filters.http.csrf", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.csrf.v3.CsrfPolicy" + ] + }, + { + "name": "envoy.filters.http.custom_response", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.custom_response.v3.CustomResponse" + ] + }, + { + "name": "envoy.filters.http.decompressor", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.decompressor.v3.Decompressor" + ] + }, + { + "name": "envoy.filters.http.dynamic_forward_proxy", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig", + "envoy.extensions.filters.http.dynamic_forward_proxy.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.ext_authz", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ext_authz.v3.ExtAuthz", + "envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute" + ] + }, + { + "name": "envoy.filters.http.ext_proc", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute", + "envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor" + ] + }, + { + "name": "envoy.filters.http.fault", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.fault.v3.HTTPFault" + ] + }, + { + "name": "envoy.filters.http.file_system_buffer", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.file_system_buffer.v3.FileSystemBufferFilterConfig" + ] + }, + { + "name": "envoy.filters.http.gcp_authn", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig" + ] + }, + { + "name": "envoy.filters.http.grpc_http1_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" + ] + }, + { + "name": "envoy.filters.http.grpc_http1_reverse_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfig", + "envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfigPerRoute" + ] + }, + { + "name": "envoy.filters.http.grpc_json_transcoder", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder" + ] + }, + { + "name": "envoy.filters.http.grpc_stats", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_stats.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.grpc_web", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_web.v3.GrpcWeb" + ] + }, + { + "name": "envoy.filters.http.header_to_metadata", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.header_to_metadata.v3.Config" + ] + }, + { + "name": "envoy.filters.http.health_check", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.health_check.v3.HealthCheck" + ] + }, + { + "name": "envoy.filters.http.ip_tagging", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ip_tagging.v3.IPTagging" + ] + }, + { + "name": "envoy.filters.http.jwt_authn", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication", + "envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.local_ratelimit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit" + ] + }, + { + "name": "envoy.filters.http.lua", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.lua.v3.Lua", + "envoy.extensions.filters.http.lua.v3.LuaPerRoute" + ] + }, + { + "name": "envoy.filters.http.match_delegate", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.common.matching.v3.ExtensionWithMatcher" + ] + }, + { + "name": "envoy.filters.http.oauth2", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.oauth2.v3.OAuth2" + ] + }, + { + "name": "envoy.filters.http.on_demand", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.on_demand.v3.OnDemand", + "envoy.extensions.filters.http.on_demand.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.original_src", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.original_src.v3.OriginalSrc" + ] + }, + { + "name": "envoy.filters.http.rate_limit_quota", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaFilterConfig", + "envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaOverride" + ] + }, + { + "name": "envoy.filters.http.ratelimit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ratelimit.v3.RateLimit", + "envoy.extensions.filters.http.ratelimit.v3.RateLimitPerRoute" + ] + }, + { + "name": "envoy.filters.http.rbac", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.rbac.v3.RBAC", + "envoy.extensions.filters.http.rbac.v3.RBACPerRoute" + ] + }, + { + "name": "envoy.filters.http.router", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.router.v3.Router" + ] + }, + { + "name": "envoy.filters.http.set_metadata", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.set_metadata.v3.Config" + ] + }, + { + "name": "envoy.filters.http.stateful_session", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.stateful_session.v3.StatefulSession", + "envoy.extensions.filters.http.stateful_session.v3.StatefulSessionPerRoute" + ] + }, + { + "name": "envoy.filters.http.tap", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.tap.v3.Tap" + ] + }, + { + "name": "envoy.filters.http.wasm", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.grpc_http1_bridge", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_json_transcoder", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_web", + "category": "envoy.filters.http" + }, + { + "name": "envoy.health_check", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ip_tagging", + "category": "envoy.filters.http" + }, + { + "name": "envoy.local_rate_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.lua", + "category": "envoy.filters.http" + }, + { + "name": "envoy.rate_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.router", + "category": "envoy.filters.http" + }, + { + "name": "envoy.access_loggers.file", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.file.v3.FileAccessLog" + ] + }, + { + "name": "envoy.access_loggers.http_grpc", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.open_telemetry", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.open_telemetry.v3.OpenTelemetryAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.stderr", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.stream.v3.StderrAccessLog" + ] + }, + { + "name": "envoy.access_loggers.stdout", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.stream.v3.StdoutAccessLog" + ] + }, + { + "name": "envoy.access_loggers.tcp_grpc", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.grpc.v3.TcpGrpcAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.wasm", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.wasm.v3.WasmAccessLog" + ] + }, + { + "name": "envoy.file_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.http_grpc_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.open_telemetry_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.stderr_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.stdout_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.tcp_grpc_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.wasm_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.config.validators.minimum_clusters", + "category": "envoy.config.validators" + }, + { + "name": "envoy.config.validators.minimum_clusters_validator", + "category": "envoy.config.validators", + "type_urls": [ + "envoy.extensions.config.validators.minimum_clusters.v3.MinimumClustersValidator" + ] + }, + { + "name": "envoy.http.header_validators.envoy_default", + "category": "envoy.http.header_validators", + "type_urls": [ + "envoy.extensions.http.header_validators.envoy_default.v3.HeaderValidatorConfig" + ] + }, + { + "name": "dubbo.hessian2", + "category": "envoy.dubbo_proxy.serializers" + }, + { + "name": "quic.http_server_connection.default", + "category": "quic.http_server_connection" + }, + { + "name": "envoy.transport_sockets.alts", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.alts.v3.Alts" + ] + }, + { + "name": "envoy.transport_sockets.quic", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.quic.v3.QuicDownstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.raw_buffer", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer" + ] + }, + { + "name": "envoy.transport_sockets.starttls", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.starttls.v3.StartTlsConfig" + ] + }, + { + "name": "envoy.transport_sockets.tap", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tap.v3.Tap" + ] + }, + { + "name": "envoy.transport_sockets.tcp_stats", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tcp_stats.v3.Config" + ] + }, + { + "name": "envoy.transport_sockets.tls", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext" + ] + }, + { + "name": "raw_buffer", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "starttls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "tls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.rbac.matchers.upstream_ip_port", + "category": "envoy.rbac.matchers", + "type_urls": [ + "envoy.extensions.rbac.matchers.upstream_ip_port.v3.UpstreamIpPortMatcher" + ] + }, + { + "name": "envoy.key_value.file_based", + "category": "envoy.common.key_value", + "type_urls": [ + "envoy.extensions.key_value.file_based.v3.FileBasedKeyValueStoreConfig" + ] + }, + { + "name": "envoy.matching.inputs.application_protocol", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_port", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput" + ] + }, + { + "name": "envoy.matching.inputs.direct_source_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.dns_san", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput" + ] + }, + { + "name": "envoy.matching.inputs.server_name", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ServerNameInput" + ] + }, + { + "name": "envoy.matching.inputs.source_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.source_port", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourcePortInput" + ] + }, + { + "name": "envoy.matching.inputs.source_type", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput" + ] + }, + { + "name": "envoy.matching.inputs.subject", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput" + ] + }, + { + "name": "envoy.matching.inputs.transport_protocol", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput" + ] + }, + { + "name": "envoy.matching.inputs.uri_san", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput" + ] + }, + { + "name": "dubbo", + "category": "envoy.dubbo_proxy.protocols" + }, + { + "name": "envoy.watchdog.abort_action", + "category": "envoy.guarddog_actions", + "type_urls": [ + "envoy.watchdog.v3.AbortActionConfig" + ] + }, + { + "name": "envoy.watchdog.profile_action", + "category": "envoy.guarddog_actions", + "type_urls": [ + "envoy.extensions.watchdog.profile_action.v3.ProfileActionConfig" + ] + }, + { + "name": "envoy.quic.crypto_stream.server.quiche", + "category": "envoy.quic.server.crypto_stream", + "type_urls": [ + "envoy.extensions.quic.crypto_stream.v3.CryptoServerStreamConfig" + ] + }, + { + "name": "envoy.regex_engines.google_re2", + "category": "envoy.regex_engines", + "type_urls": [ + "envoy.extensions.regex_engines.v3.GoogleRE2" + ] + }, + { + "name": "envoy.http.stateful_session.cookie", + "category": "envoy.http.stateful_session", + "type_urls": [ + "envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState" + ] + }, + { + "name": "envoy.http.stateful_session.header", + "category": "envoy.http.stateful_session", + "type_urls": [ + "envoy.extensions.http.stateful_session.header.v3.HeaderBasedSessionState" + ] + }, + { + "name": "envoy.matching.custom_matchers.trie_matcher", + "category": "envoy.matching.network.custom_matchers", + "type_urls": [ + "xds.type.matcher.v3.IPMatcher" + ] + }, + { + "name": "envoy.udp_packet_writer.default", + "category": "envoy.udp_packet_writer", + "type_urls": [ + "envoy.extensions.udp_packet_writer.v3.UdpDefaultWriterFactory" + ] + }, + { + "name": "envoy.udp_packet_writer.gso", + "category": "envoy.udp_packet_writer", + "type_urls": [ + "envoy.extensions.udp_packet_writer.v3.UdpGsoBatchWriterFactory" + ] + }, + { + "name": "envoy.quic.proof_source.filter_chain", + "category": "envoy.quic.proof_source", + "type_urls": [ + "envoy.extensions.quic.proof_source.v3.ProofSourceConfig" + ] + }, + { + "name": "envoy.resource_monitors.fixed_heap", + "category": "envoy.resource_monitors", + "type_urls": [ + "envoy.extensions.resource_monitors.fixed_heap.v3.FixedHeapConfig" + ] + }, + { + "name": "envoy.resource_monitors.injected_resource", + "category": "envoy.resource_monitors", + "type_urls": [ + "envoy.extensions.resource_monitors.injected_resource.v3.InjectedResourceConfig" + ] + }, + { + "name": "envoy.http.stateful_header_formatters.preserve_case", + "category": "envoy.http.stateful_header_formatters", + "type_urls": [ + "envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig" + ] + }, + { + "name": "preserve_case", + "category": "envoy.http.stateful_header_formatters" + }, + { + "name": "envoy.filters.thrift.header_to_metadata", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.header_to_metadata.v3.HeaderToMetadata" + ] + }, + { + "name": "envoy.filters.thrift.payload_to_metadata", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.payload_to_metadata.v3.PayloadToMetadata" + ] + }, + { + "name": "envoy.filters.thrift.rate_limit", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.ratelimit.v3.RateLimit" + ] + }, + { + "name": "envoy.filters.thrift.router", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.router.v3.Router" + ] + }, + { + "name": "envoy.tracers.datadog", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.DatadogConfig" + ] + }, + { + "name": "envoy.tracers.dynamic_ot", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.DynamicOtConfig" + ] + }, + { + "name": "envoy.tracers.opencensus", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.OpenCensusConfig" + ] + }, + { + "name": "envoy.tracers.opentelemetry", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.OpenTelemetryConfig" + ] + }, + { + "name": "envoy.tracers.skywalking", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.SkyWalkingConfig" + ] + }, + { + "name": "envoy.tracers.xray", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.XRayConfig" + ] + }, + { + "name": "envoy.tracers.zipkin", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.ZipkinConfig" + ] + }, + { + "name": "envoy.zipkin", + "category": "envoy.tracers" + }, + { + "name": "envoy.retry_priorities.previous_priorities", + "category": "envoy.retry_priorities", + "type_urls": [ + "envoy.extensions.retry.priority.previous_priorities.v3.PreviousPrioritiesConfig" + ] + }, + { + "name": "envoy.http.early_header_mutation.header_mutation", + "category": "envoy.http.early_header_mutation", + "type_urls": [ + "envoy.extensions.http.early_header_mutation.header_mutation.v3.HeaderMutation" + ] + }, + { + "name": "envoy.connection_handler.default", + "category": "envoy.connection_handler" + }, + { + "name": "envoy.transport_sockets.alts", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.alts.v3.Alts" + ] + }, + { + "name": "envoy.transport_sockets.http_11_proxy", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.http_11_proxy.v3.Http11ProxyUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.internal_upstream", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.internal_upstream.v3.InternalUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.quic", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.quic.v3.QuicUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.raw_buffer", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer" + ] + }, + { + "name": "envoy.transport_sockets.starttls", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.starttls.v3.UpstreamStartTlsConfig" + ] + }, + { + "name": "envoy.transport_sockets.tap", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tap.v3.Tap" + ] + }, + { + "name": "envoy.transport_sockets.tcp_stats", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tcp_stats.v3.Config" + ] + }, + { + "name": "envoy.transport_sockets.tls", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext" + ] + }, + { + "name": "envoy.transport_sockets.upstream_proxy_protocol", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport" + ] + }, + { + "name": "raw_buffer", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "starttls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "tls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "auto", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "framed", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "header", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "unframed", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "envoy.cluster.eds", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.logical_dns", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.original_dst", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.static", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.strict_dns", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.aggregate", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.dynamic_forward_proxy", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.redis", + "category": "envoy.clusters" + }, + { + "name": "envoy.access_loggers.extension_filters.cel", + "category": "envoy.access_loggers.extension_filters", + "type_urls": [ + "envoy.extensions.access_loggers.filters.cel.v3.ExpressionFilter" + ] + }, + { + "name": "auto", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "binary", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "binary/non-strict", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "compact", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "twitter", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "category": "envoy.upstream_options", + "type_urls": [ + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + ] + }, + { + "name": "envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions", + "category": "envoy.upstream_options", + "type_urls": [ + "envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions" + ] + }, + { + "name": "envoy.upstreams.http.http_protocol_options", + "category": "envoy.upstream_options" + }, + { + "name": "envoy.upstreams.tcp.tcp_protocol_options", + "category": "envoy.upstream_options" + }, + { + "name": "envoy.listener_manager_impl.default", + "category": "envoy.listener_manager_impl", + "type_urls": [ + "envoy.config.listener.v3.ListenerManager" + ] + }, + { + "name": "default", + "category": "network.connection.client" + }, + { + "name": "envoy_internal", + "category": "network.connection.client" + }, + { + "name": "envoy.filters.udp.dns_filter", + "category": "envoy.filters.udp_listener", + "type_urls": [ + "envoy.extensions.filters.udp.dns_filter.v3.DnsFilterConfig" + ] + }, + { + "name": "envoy.filters.udp_listener.udp_proxy", + "category": "envoy.filters.udp_listener", + "type_urls": [ + "envoy.extensions.filters.udp.udp_proxy.v3.UdpProxyConfig" + ] + }, + { + "name": "envoy.extensions.http.cache.file_system_http_cache", + "category": "envoy.http.cache", + "type_urls": [ + "envoy.extensions.http.cache.file_system_http_cache.v3.FileSystemHttpCacheConfig" + ] + }, + { + "name": "envoy.extensions.http.cache.simple", + "category": "envoy.http.cache", + "type_urls": [ + "envoy.extensions.http.cache.simple_http_cache.v3.SimpleHttpCacheConfig" + ] + }, + { + "name": "envoy.retry_host_predicates.omit_canary_hosts", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.omit_canary_hosts.v3.OmitCanaryHostsPredicate" + ] + }, + { + "name": "envoy.retry_host_predicates.omit_host_metadata", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.omit_host_metadata.v3.OmitHostMetadataConfig" + ] + }, + { + "name": "envoy.retry_host_predicates.previous_hosts", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate" + ] + }, + { + "name": "envoy.formatter.metadata", + "category": "envoy.formatter", + "type_urls": [ + "envoy.extensions.formatter.metadata.v3.Metadata" + ] + }, + { + "name": "envoy.formatter.req_without_query", + "category": "envoy.formatter", + "type_urls": [ + "envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery" + ] + }, + { + "name": "envoy.internal_redirect_predicates.allow_listed_routes", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.allow_listed_routes.v3.AllowListedRoutesConfig" + ] + }, + { + "name": "envoy.internal_redirect_predicates.previous_routes", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.previous_routes.v3.PreviousRoutesConfig" + ] + }, + { + "name": "envoy.internal_redirect_predicates.safe_cross_scheme", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.safe_cross_scheme.v3.SafeCrossSchemeConfig" + ] + }, + { + "name": "envoy.matching.custom_matchers.trie_matcher", + "category": "envoy.matching.http.custom_matchers", + "type_urls": [ + "xds.type.matcher.v3.IPMatcher" + ] + }, + { + "name": "envoy.filters.dubbo.router", + "category": "envoy.dubbo_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.dubbo_proxy.router.v3.Router" + ] + }, + { + "name": "envoy.echo", + "category": "envoy.filters.network" + }, + { + "name": "envoy.ext_authz", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.connection_limit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit" + ] + }, + { + "name": "envoy.filters.network.direct_response", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.direct_response.v3.Config" + ] + }, + { + "name": "envoy.filters.network.dubbo_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.dubbo_proxy.v3.DubboProxy" + ] + }, + { + "name": "envoy.filters.network.echo", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.echo.v3.Echo" + ] + }, + { + "name": "envoy.filters.network.ext_authz", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + ] + }, + { + "name": "envoy.filters.network.http_connection_manager", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager" + ] + }, + { + "name": "envoy.filters.network.local_ratelimit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.local_ratelimit.v3.LocalRateLimit" + ] + }, + { + "name": "envoy.filters.network.mongo_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy" + ] + }, + { + "name": "envoy.filters.network.ratelimit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.ratelimit.v3.RateLimit" + ] + }, + { + "name": "envoy.filters.network.rbac", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.rbac.v3.RBAC" + ] + }, + { + "name": "envoy.filters.network.redis_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.redis_proxy.v3.RedisProxy" + ] + }, + { + "name": "envoy.filters.network.sni_cluster", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + ] + }, + { + "name": "envoy.filters.network.sni_dynamic_forward_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.sni_dynamic_forward_proxy.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.network.tcp_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy" + ] + }, + { + "name": "envoy.filters.network.thrift_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.v3.ThriftProxy" + ] + }, + { + "name": "envoy.filters.network.wasm", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.filters.network.zookeeper_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.zookeeper_proxy.v3.ZooKeeperProxy" + ] + }, + { + "name": "envoy.http_connection_manager", + "category": "envoy.filters.network" + }, + { + "name": "envoy.mongo_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.ratelimit", + "category": "envoy.filters.network" + }, + { + "name": "envoy.redis_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.tcp_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.health_checkers.redis", + "category": "envoy.health_checkers", + "type_urls": [ + "envoy.extensions.health_checkers.redis.v3.Redis" + ] + }, + { + "name": "envoy.health_checkers.thrift", + "category": "envoy.health_checkers", + "type_urls": [ + "envoy.extensions.health_checkers.thrift.v3.Thrift" + ] + } + ] + }, + "static_resources": { + "clusters": [{ + "name": "xds_cluster", + "type": "STRICT_DNS", + "connect_timeout": "1s", + "transport_socket": { + "name": "envoy.transport_sockets.tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": { + "tls_maximum_protocol_version": "TLSv1_3" + }, + "tls_certificate_sds_secret_configs": [{ + "name": "xds_certificate", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-certificate.json" + } + } + }], + "validation_context_sds_secret_config": { + "name": "xds_trusted_ca", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-trusted-ca.json" + } + } + } + } + } + }, + "load_assignment": { + "cluster_name": "xds_cluster", + "endpoints": [{ + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "higress", + "port_value": 18000 + } + } + } + }] + }] + }, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + } + }] + }, + "dynamic_resources": { + "lds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + }, + "cds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + } + }, + "admin": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 15000 + } + }, + "access_log": [{ + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + }] + }, + "layered_runtime": { + "layers": [{ + "name": "runtime-0", + "rtds_layer": { + "name": "runtime-0", + "rtds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + } + } + }] + } + }, + "last_updated": "2023-02-23T09:05:23.422Z" + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ClustersConfigDump", + "version_info": "2", + "static_clusters": [{ + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "xds_cluster", + "type": "STRICT_DNS", + "connect_timeout": "1s", + "transport_socket": { + "name": "envoy.transport_sockets.tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": { + "tls_maximum_protocol_version": "TLSv1_3" + }, + "tls_certificate_sds_secret_configs": [{ + "name": "xds_certificate", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-certificate.json" + } + } + }], + "validation_context_sds_secret_config": { + "name": "xds_trusted_ca", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-trusted-ca.json" + } + } + } + } + } + }, + "load_assignment": { + "cluster_name": "xds_cluster", + "endpoints": [{ + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "higress", + "port_value": 18000 + } + } + } + }] + }] + }, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + } + }, + "last_updated": "2023-02-23T09:05:23.436Z" + }], + "dynamic_active_clusters": [{ + "version_info": "2a0a1698a9d3e05b802047b0cd36b52a070afa49042e1ba267168c5265c7cabf", + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "default-backend-rule-0-match-0-www.example.com", + "type": "STATIC", + "connect_timeout": "5s", + "dns_lookup_family": "V4_ONLY", + "outlier_detection": {}, + "common_lb_config": { + "locality_weighted_lb_config": {} + }, + "load_assignment": { + "cluster_name": "default-backend-rule-0-match-0-www.example.com", + "endpoints": [{ + "locality": {}, + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 3000 + } + } + }, + "load_balancing_weight": 1 + }], + "load_balancing_weight": 1 + }] + } + }, + "last_updated": "2023-02-23T09:05:38.443Z" + }] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ListenersConfigDump", + "version_info": "2", + "dynamic_listeners": [{ + "name": "default-higress-http", + "active_state": { + "version_info": "42c71fb50c315ee3a32b327da69f8cc0baf420bc84b747e82d9c38e1b0c33eb2", + "listener": { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "default-higress-http", + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 10080 + } + }, + "access_log": [{ + "name": "envoy.access_loggers.file", + "filter": { + "response_flag_filter": { + "flags": [ + "NR" + ] + } + }, + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/stdout" + } + }], + "default_filter_chain": { + "filters": [{ + "name": "envoy.filters.network.http_connection_manager", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "http", + "rds": { + "config_source": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + }, + "route_config_name": "default-higress-http" + }, + "http_filters": [{ + "name": "envoy.filters.http.router", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + }], + "access_log": [{ + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/stdout" + } + }], + "use_remote_address": true, + "upgrade_configs": [{ + "upgrade_type": "websocket" + }] + } + }] + } + }, + "last_updated": "2023-02-23T09:05:38.446Z" + } + }] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ScopedRoutesConfigDump" + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.RoutesConfigDump", + "dynamic_route_configs": [{ + "version_info": "cb1e51997a9c3aa6f4d920f39fd5bdbd966e9382b7b6bdf42efca8c22c6c3442", + "route_config": { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "default-higress-http", + "virtual_hosts": [{ + "name": "default-higress-http", + "domains": [ + "*" + ], + "routes": [{ + "match": { + "prefix": "/", + "headers": [{ + "name": ":authority", + "string_match": { + "exact": "www.example.com" + } + }] + }, + "route": { + "cluster": "default-backend-rule-0-match-0-www.example.com" + } + }] + }] + }, + "last_updated": "2023-02-23T09:05:38.448Z" + }] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.SecretsConfigDump", + "dynamic_active_secrets": [{ + "name": "xds_certificate", + "last_updated": "2023-02-23T09:05:23.442Z", + "secret": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "name": "xds_certificate", + "tls_certificate": { + "certificate_chain": { + "inline_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLekNDQWhPZ0F3SUJBZ0lFTnJRVi9qQU5CZ2txaGtpRzl3MEJBUXNGQURBc01SWXdGQVlEVlFRREV3MWwKYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEVlFRRkV3azFOalE0TXpRek9EVXdIaGNOTWpNd01qRTNNRE0wTVRJNApXaGNOTWpRd01qRTRNRE0wTVRJNFdqQU1NUW93Q0FZRFZRUUREQUVxTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGCkFBT0NBUThBTUlJQkNnS0NBUUVBNmdNSTJSNElEeE5mQ2o1YmZHU1hVUjF4YkVjRjE5VXlhVC9VUEZZcFltM0gKN2c4T3Z6YWRlelFyRkt3dG9PWWFDN0hjam8zVnVHSmhqSDQ1Z3lVbWFzSEg1Q1gzaWFlRlhxQXdVQjRqVTZQSgpBbElCZWlMRVdZVjN1VjMwcGlKK09DWFhrUEQzSFFVb0ZYbnljcHM3OE9PbjZoS0wwNUY0YkJsT2UrMFdIUHdECll2dFQ4TEdpVmcrSkxhR2lxaGgxOXY5endwQUd2akI2Z09kN1BjdkNQNFExUHdkMWdMSnNXVFNweGhDUEVPb2kKV2ZSOG56RERVUHU5aXc2QTJObW1XQ1FxSVNYcDlZUmJMTEdjZnV4VURjcFVYMHpqY0xvcE1sajBnM0RkYVpWRwpzNm9JcW9BSjZ6MFhvdWwrM0ZZdUtJYy8rT1V3VkR1VkI4K0ZRZzlYdlFJREFRQUJvM1V3Y3pBT0JnTlZIUThCCkFmOEVCQU1DQlBBd0hRWURWUjBPQkJZRUZKaUJ3cytVaFRlT2p1L1ZXT29LQWNTSmZBeXVNQjhHQTFVZEl3UVkKTUJhQUZCT3kvOGkxeVMxRWxpN0tNK0gyeXZEM1BJMG1NQ0VHQTFVZEVRUWFNQmlDRmlvdVpXNTJiM2t0WjJGMApaWGRoZVMxemVYTjBaVzB3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUZraHdIakZtQWxqdEpheU54WitodURGCm5UdWd0REZvSTBFT2J0cUhLYnloWU9sdlNFdkhxbFNQSHNRUUhmQnQwbHpOOEtGUTd2YWxTSHRBZStlNzBETHkKaGY3TDQ3eklST3NLcmtmb0tjMjRqaUhNQkVwbCtJdjllU1RWVG9WemxzazVZUGxET2lrMzZpRUY3WDVVZ0RheApsVllZZnpSYzRUb0poODMwT285Wm9pai9LM295dVNXcTVGRzVFWExmeW9tQzZPQ3dxRm5GNzRSM21FTjVheDRlCnppVm5QVDNxVmFZdytzNngwSVhHU282U2M3Q2lUbmMrckFNa3FJNVNsK2p5RHhKTkZBQlIvRllCcTQzK1B1UGkKN0YxOEw0N2l3aVFFYU82NUJzU2hlYmg1Qk1VbytDdzIyM3JsMGRpTldwY3FrdVhtT1BWNDlrWkZkdHpFNytVPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==" + }, + "private_key": { + "inline_bytes": "W3JlZGFjdGVkXQ==" + } + } + } + }, + { + "name": "xds_trusted_ca", + "last_updated": "2023-02-23T09:05:23.447Z", + "secret": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "name": "xds_trusted_ca", + "validation_context": { + "trusted_ca": { + "inline_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHRENDQWdDZ0F3SUJBZ0lFSWFxd1VUQU5CZ2txaGtpRzl3MEJBUXNGQURBc01SWXdGQVlEVlFRREV3MWwKYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEVlFRRkV3azFOalE0TXpRek9EVXdIaGNOTWpNd01qRTNNRE0wTVRJNApXaGNOTWpRd01qRTRNRE0wTVRJNFdqQXNNUll3RkFZRFZRUURFdzFsYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEClZRUUZFd2sxTmpRNE16UXpPRFV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRDIKeFMrNkRWY2FvbHFkVVBzTHZwNUtQMEQyV0hrTkVEY0tPeml3bzZNYm9wczFLYWJnNXVYSVl5T21JRWNTTXNKNwpHbVAxMlJjK0J3V1dFWXRrTHVPU3BwQm1lSjN3aDRrUlVRVTRTemRFU1dDcU40RTNpcTJib3FFVm53SkFGQ1ZpCldldGVjZkZsODZFalliQUxxSnRCbGJCbFFQM1ZMZ1hva0VVamJ4QmFobE1wZitUWkVJNFBuam1zUWN5a21LeXIKaDJwdmM3cnZYb29HTlhTM0Q0eFc1VDY3dmxLYi94UlM3c2gwTkJEU0dtTE1jY2pxWFZXazVOR2lBWVB3dXBWSwpTWG02dnZXUFZCdEd1bkZhS0JSRGx4TlJrb0wzRUN6UkNtenoxR2ZYMGJkSm1leElOM2VIUFBRdkd0M0txeUlnCkgrYnc0OXpqdlVUb2dNcXFpTlcvQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQQmdOVkhSTUIKQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJRVHN2L0l0Y2t0UkpZdXlqUGg5c3J3OXp5TkpqQU5CZ2txaGtpRwo5dzBCQVFzRkFBT0NBUUVBd2dvZEsxalhVWFZDVXBTSjE0cEo3S3ZobWZPT1hkaVNISmNSSzlIUzI1c2xwOWN2CkJDSndmWUZmanJ4Rmc5TnV4aVpiM01oVXk5MDBqenBPdk1QWStEeUxFWFVxTGd5ZlBMUzYveVliem8yZHdwdzMKOCtrTXlsQUFlZmtaSW9oT0VhYSsvNFFBVVVGZVp1a1B6bmF6RzZIWnZKQkNxWVdRNXBaSSt3WTI1dzhEU0VOMgpkOCswVkpzWU5IdUk4aXhneGZhUkRycW5LRHBMUGJ3Z3VaRDl6ZkV3dVFaNG1oeEd0Vk1wR0NLSndscWFhdXJ0CkF5aGhzOXBHNERndkpSY1BLeFY4bndRdzZtSm55dkIxcExxTW1aQTVqZWhxbFNvUGVpWUlBMk1neU83cTVPYmMKL040bzBNTVdvZ1piRWR6aTBnTXJRT2lpNE41Q0ZlakVrYStIMmc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==" + }, + "match_typed_subject_alt_names": [{ + "san_type": "DNS", + "matcher": { + "exact": "higress" + } + }] + } + } + } + ] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump", + "staticEndpointConfigs": [{ + "endpointConfig": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "xds_cluster", + "endpoints": [{ + "locality": {}, + "lbEndpoints": [{ + "endpoint": { + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 18000 + } + }, + "healthCheckConfig": {}, + "hostname": "higress" + }, + "healthStatus": "HEALTHY", + "metadata": {}, + "loadBalancingWeight": 1 + }] + }], + "policy": { + "overprovisioningFactor": 140 + } + } + }] + } + ] +} diff --git a/pkg/cmd/hgctl/testdata/config/output/out.all.json b/pkg/cmd/hgctl/testdata/config/output/out.all.json new file mode 100644 index 0000000000..5c851a2847 --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.all.json @@ -0,0 +1,2247 @@ +{ + "configs": [{ + "@type": "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump", + "bootstrap": { + "node": { + "user_agent_name": "envoy", + "user_agent_build_version": { + "version": { + "major_number": 1, + "minor_number": 26 + }, + "metadata": { + "revision.status": "Clean", + "revision.sha": "14111e3c62d3d38b0c921cb7011fd0a94e880aed", + "ssl.version": "BoringSSL", + "build.label": "dev", + "build.type": "RELEASE" + } + }, + "extensions": [{ + "name": "envoy.filters.connection_pools.tcp.generic", + "category": "envoy.upstreams", + "type_urls": [ + "envoy.extensions.upstreams.tcp.generic.v3.GenericConnectionPoolProto" + ] + }, + { + "name": "envoy.rate_limit_descriptors.expr", + "category": "envoy.rate_limit_descriptors", + "type_urls": [ + "envoy.extensions.rate_limit_descriptors.expr.v3.Descriptor" + ] + }, + { + "name": "envoy.matching.inputs.destination_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_port", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput" + ] + }, + { + "name": "envoy.matching.inputs.direct_source_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.dns_san", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput" + ] + }, + { + "name": "envoy.matching.inputs.request_headers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestHeaderMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.request_trailers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestTrailerMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.response_headers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseHeaderMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.response_trailers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseTrailerMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.server_name", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ServerNameInput" + ] + }, + { + "name": "envoy.matching.inputs.source_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.source_port", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourcePortInput" + ] + }, + { + "name": "envoy.matching.inputs.source_type", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput" + ] + }, + { + "name": "envoy.matching.inputs.status_code_class_input", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseStatusCodeClassMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.status_code_input", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseStatusCodeMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.subject", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput" + ] + }, + { + "name": "envoy.matching.inputs.uri_san", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput" + ] + }, + { + "name": "query_params", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestQueryParamMatchInput" + ] + }, + { + "name": "envoy.tls.cert_validator.default", + "category": "envoy.tls.cert_validator" + }, + { + "name": "envoy.tls.cert_validator.spiffe", + "category": "envoy.tls.cert_validator" + }, + { + "name": "envoy.path.match.uri_template.uri_template_matcher", + "category": "envoy.path.match", + "type_urls": [ + "envoy.extensions.path.match.uri_template.v3.UriTemplateMatchConfig" + ] + }, + { + "name": "envoy.http.original_ip_detection.custom_header", + "category": "envoy.http.original_ip_detection", + "type_urls": [ + "envoy.extensions.http.original_ip_detection.custom_header.v3.CustomHeaderConfig" + ] + }, + { + "name": "envoy.http.original_ip_detection.xff", + "category": "envoy.http.original_ip_detection", + "type_urls": [ + "envoy.extensions.http.original_ip_detection.xff.v3.XffConfig" + ] + }, + { + "name": "envoy.buffer", + "category": "envoy.filters.http.upstream" + }, + { + "name": "envoy.filters.http.admission_control", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.admission_control.v3.AdmissionControl" + ] + }, + { + "name": "envoy.filters.http.buffer", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.buffer.v3.Buffer", + "envoy.extensions.filters.http.buffer.v3.BufferPerRoute" + ] + }, + { + "name": "envoy.filters.http.upstream_codec", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec" + ] + }, + { + "name": "envoy.route.early_data_policy.default", + "category": "envoy.route.early_data_policy", + "type_urls": [ + "envoy.extensions.early_data.v3.DefaultEarlyDataPolicy" + ] + }, + { + "name": "envoy.compression.brotli.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.brotli.compressor.v3.Brotli" + ] + }, + { + "name": "envoy.compression.gzip.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.gzip.compressor.v3.Gzip" + ] + }, + { + "name": "envoy.compression.zstd.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.zstd.compressor.v3.Zstd" + ] + }, + { + "name": "envoy.compression.brotli.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.brotli.decompressor.v3.Brotli" + ] + }, + { + "name": "envoy.compression.gzip.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.gzip.decompressor.v3.Gzip" + ] + }, + { + "name": "envoy.compression.zstd.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.zstd.decompressor.v3.Zstd" + ] + }, + { + "name": "envoy.wasm.runtime.null", + "category": "envoy.wasm.runtime" + }, + { + "name": "envoy.wasm.runtime.v8", + "category": "envoy.wasm.runtime" + }, + { + "name": "envoy.dog_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.graphite_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.metrics_service", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.dog_statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.DogStatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.graphite_statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.extensions.stat_sinks.graphite_statsd.v3.GraphiteStatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.hystrix", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.HystrixSink" + ] + }, + { + "name": "envoy.stat_sinks.metrics_service", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.MetricsServiceConfig" + ] + }, + { + "name": "envoy.stat_sinks.statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.StatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.wasm", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.extensions.stat_sinks.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.path.rewrite.uri_template.uri_template_rewriter", + "category": "envoy.path.rewrite", + "type_urls": [ + "envoy.extensions.path.rewrite.uri_template.v3.UriTemplateRewriteConfig" + ] + }, + { + "name": "envoy.extensions.http.custom_response.local_response_policy", + "category": "envoy.http.custom_response", + "type_urls": [ + "envoy.extensions.http.custom_response.local_response_policy.v3.LocalResponsePolicy" + ] + }, + { + "name": "envoy.extensions.http.custom_response.redirect_policy", + "category": "envoy.http.custom_response", + "type_urls": [ + "envoy.extensions.http.custom_response.redirect_policy.v3.RedirectPolicy" + ] + }, + { + "name": "envoy.matching.actions.format_string", + "category": "envoy.matching.action", + "type_urls": [ + "envoy.config.core.v3.SubstitutionFormatString" + ] + }, + { + "name": "filter-chain-name", + "category": "envoy.matching.action", + "type_urls": [ + "google.protobuf.StringValue" + ] + }, + { + "name": "envoy.quic.deterministic_connection_id_generator", + "category": "envoy.quic.connection_id_generator", + "type_urls": [ + "envoy.extensions.quic.connection_id_generator.v3.DeterministicConnectionIdGeneratorConfig" + ] + }, + { + "name": "envoy.network.dns_resolver.cares", + "category": "envoy.network.dns_resolver", + "type_urls": [ + "envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig" + ] + }, + { + "name": "envoy.network.dns_resolver.getaddrinfo", + "category": "envoy.network.dns_resolver", + "type_urls": [ + "envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig" + ] + }, + { + "name": "envoy.bootstrap.internal_listener", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.bootstrap.internal_listener.v3.InternalListener" + ] + }, + { + "name": "envoy.bootstrap.wasm", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.wasm.v3.WasmService" + ] + }, + { + "name": "envoy.extensions.network.socket_interface.default_socket_interface", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.network.socket_interface.v3.DefaultSocketInterface" + ] + }, + { + "name": "envoy.filters.listener.http_inspector", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.http_inspector.v3.HttpInspector" + ] + }, + { + "name": "envoy.filters.listener.original_dst", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.original_dst.v3.OriginalDst" + ] + }, + { + "name": "envoy.filters.listener.original_src", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.original_src.v3.OriginalSrc" + ] + }, + { + "name": "envoy.filters.listener.proxy_protocol", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol" + ] + }, + { + "name": "envoy.filters.listener.tls_inspector", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + ] + }, + { + "name": "envoy.listener.http_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.original_dst", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.original_src", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.proxy_protocol", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.tls_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.matching.common_inputs.environment_variable", + "category": "envoy.matching.common_inputs", + "type_urls": [ + "envoy.extensions.matching.common_inputs.environment_variable.v3.Config" + ] + }, + { + "name": "envoy.matching.matchers.consistent_hashing", + "category": "envoy.matching.input_matchers", + "type_urls": [ + "envoy.extensions.matching.input_matchers.consistent_hashing.v3.ConsistentHashing" + ] + }, + { + "name": "envoy.matching.matchers.ip", + "category": "envoy.matching.input_matchers", + "type_urls": [ + "envoy.extensions.matching.input_matchers.ip.v3.Ip" + ] + }, + { + "name": "envoy.grpc_credentials.aws_iam", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.grpc_credentials.default", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.grpc_credentials.file_based_metadata", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.request_id.uuid", + "category": "envoy.request_id", + "type_urls": [ + "envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig" + ] + }, + { + "name": "envoy.load_balancing_policies.least_request", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest" + ] + }, + { + "name": "envoy.load_balancing_policies.maglev", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.maglev.v3.Maglev" + ] + }, + { + "name": "envoy.load_balancing_policies.random", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.random.v3.Random" + ] + }, + { + "name": "envoy.load_balancing_policies.ring_hash", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash" + ] + }, + { + "name": "envoy.load_balancing_policies.round_robin", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin" + ] + }, + { + "name": "envoy.ip", + "category": "envoy.resolvers" + }, + { + "name": "envoy.bandwidth_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.buffer", + "category": "envoy.filters.http" + }, + { + "name": "envoy.cors", + "category": "envoy.filters.http" + }, + { + "name": "envoy.csrf", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ext_authz", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ext_proc", + "category": "envoy.filters.http" + }, + { + "name": "envoy.fault", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.adaptive_concurrency", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.adaptive_concurrency.v3.AdaptiveConcurrency" + ] + }, + { + "name": "envoy.filters.http.admission_control", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.admission_control.v3.AdmissionControl" + ] + }, + { + "name": "envoy.filters.http.alternate_protocols_cache", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.aws_lambda", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.aws_lambda.v3.Config", + "envoy.extensions.filters.http.aws_lambda.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.aws_request_signing", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning" + ] + }, + { + "name": "envoy.filters.http.bandwidth_limit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.bandwidth_limit.v3.BandwidthLimit" + ] + }, + { + "name": "envoy.filters.http.buffer", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.buffer.v3.Buffer", + "envoy.extensions.filters.http.buffer.v3.BufferPerRoute" + ] + }, + { + "name": "envoy.filters.http.cache", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cache.v3.CacheConfig" + ] + }, + { + "name": "envoy.filters.http.cdn_loop", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cdn_loop.v3.CdnLoopConfig" + ] + }, + { + "name": "envoy.filters.http.composite", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.composite.v3.Composite" + ] + }, + { + "name": "envoy.filters.http.compressor", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.compressor.v3.Compressor", + "envoy.extensions.filters.http.compressor.v3.CompressorPerRoute" + ] + }, + { + "name": "envoy.filters.http.connect_grpc_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.connect_grpc_bridge.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.cors", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cors.v3.Cors", + "envoy.extensions.filters.http.cors.v3.CorsPolicy" + ] + }, + { + "name": "envoy.filters.http.csrf", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.csrf.v3.CsrfPolicy" + ] + }, + { + "name": "envoy.filters.http.custom_response", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.custom_response.v3.CustomResponse" + ] + }, + { + "name": "envoy.filters.http.decompressor", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.decompressor.v3.Decompressor" + ] + }, + { + "name": "envoy.filters.http.dynamic_forward_proxy", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig", + "envoy.extensions.filters.http.dynamic_forward_proxy.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.ext_authz", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ext_authz.v3.ExtAuthz", + "envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute" + ] + }, + { + "name": "envoy.filters.http.ext_proc", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute", + "envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor" + ] + }, + { + "name": "envoy.filters.http.fault", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.fault.v3.HTTPFault" + ] + }, + { + "name": "envoy.filters.http.file_system_buffer", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.file_system_buffer.v3.FileSystemBufferFilterConfig" + ] + }, + { + "name": "envoy.filters.http.gcp_authn", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig" + ] + }, + { + "name": "envoy.filters.http.grpc_http1_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" + ] + }, + { + "name": "envoy.filters.http.grpc_http1_reverse_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfig", + "envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfigPerRoute" + ] + }, + { + "name": "envoy.filters.http.grpc_json_transcoder", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder" + ] + }, + { + "name": "envoy.filters.http.grpc_stats", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_stats.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.grpc_web", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_web.v3.GrpcWeb" + ] + }, + { + "name": "envoy.filters.http.header_to_metadata", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.header_to_metadata.v3.Config" + ] + }, + { + "name": "envoy.filters.http.health_check", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.health_check.v3.HealthCheck" + ] + }, + { + "name": "envoy.filters.http.ip_tagging", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ip_tagging.v3.IPTagging" + ] + }, + { + "name": "envoy.filters.http.jwt_authn", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication", + "envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.local_ratelimit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit" + ] + }, + { + "name": "envoy.filters.http.lua", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.lua.v3.Lua", + "envoy.extensions.filters.http.lua.v3.LuaPerRoute" + ] + }, + { + "name": "envoy.filters.http.match_delegate", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.common.matching.v3.ExtensionWithMatcher" + ] + }, + { + "name": "envoy.filters.http.oauth2", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.oauth2.v3.OAuth2" + ] + }, + { + "name": "envoy.filters.http.on_demand", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.on_demand.v3.OnDemand", + "envoy.extensions.filters.http.on_demand.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.original_src", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.original_src.v3.OriginalSrc" + ] + }, + { + "name": "envoy.filters.http.rate_limit_quota", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaFilterConfig", + "envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaOverride" + ] + }, + { + "name": "envoy.filters.http.ratelimit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ratelimit.v3.RateLimit", + "envoy.extensions.filters.http.ratelimit.v3.RateLimitPerRoute" + ] + }, + { + "name": "envoy.filters.http.rbac", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.rbac.v3.RBAC", + "envoy.extensions.filters.http.rbac.v3.RBACPerRoute" + ] + }, + { + "name": "envoy.filters.http.router", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.router.v3.Router" + ] + }, + { + "name": "envoy.filters.http.set_metadata", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.set_metadata.v3.Config" + ] + }, + { + "name": "envoy.filters.http.stateful_session", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.stateful_session.v3.StatefulSession", + "envoy.extensions.filters.http.stateful_session.v3.StatefulSessionPerRoute" + ] + }, + { + "name": "envoy.filters.http.tap", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.tap.v3.Tap" + ] + }, + { + "name": "envoy.filters.http.wasm", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.grpc_http1_bridge", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_json_transcoder", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_web", + "category": "envoy.filters.http" + }, + { + "name": "envoy.health_check", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ip_tagging", + "category": "envoy.filters.http" + }, + { + "name": "envoy.local_rate_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.lua", + "category": "envoy.filters.http" + }, + { + "name": "envoy.rate_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.router", + "category": "envoy.filters.http" + }, + { + "name": "envoy.access_loggers.file", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.file.v3.FileAccessLog" + ] + }, + { + "name": "envoy.access_loggers.http_grpc", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.open_telemetry", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.open_telemetry.v3.OpenTelemetryAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.stderr", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.stream.v3.StderrAccessLog" + ] + }, + { + "name": "envoy.access_loggers.stdout", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.stream.v3.StdoutAccessLog" + ] + }, + { + "name": "envoy.access_loggers.tcp_grpc", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.grpc.v3.TcpGrpcAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.wasm", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.wasm.v3.WasmAccessLog" + ] + }, + { + "name": "envoy.file_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.http_grpc_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.open_telemetry_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.stderr_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.stdout_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.tcp_grpc_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.wasm_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.config.validators.minimum_clusters", + "category": "envoy.config.validators" + }, + { + "name": "envoy.config.validators.minimum_clusters_validator", + "category": "envoy.config.validators", + "type_urls": [ + "envoy.extensions.config.validators.minimum_clusters.v3.MinimumClustersValidator" + ] + }, + { + "name": "envoy.http.header_validators.envoy_default", + "category": "envoy.http.header_validators", + "type_urls": [ + "envoy.extensions.http.header_validators.envoy_default.v3.HeaderValidatorConfig" + ] + }, + { + "name": "dubbo.hessian2", + "category": "envoy.dubbo_proxy.serializers" + }, + { + "name": "quic.http_server_connection.default", + "category": "quic.http_server_connection" + }, + { + "name": "envoy.transport_sockets.alts", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.alts.v3.Alts" + ] + }, + { + "name": "envoy.transport_sockets.quic", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.quic.v3.QuicDownstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.raw_buffer", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer" + ] + }, + { + "name": "envoy.transport_sockets.starttls", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.starttls.v3.StartTlsConfig" + ] + }, + { + "name": "envoy.transport_sockets.tap", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tap.v3.Tap" + ] + }, + { + "name": "envoy.transport_sockets.tcp_stats", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tcp_stats.v3.Config" + ] + }, + { + "name": "envoy.transport_sockets.tls", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext" + ] + }, + { + "name": "raw_buffer", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "starttls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "tls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.rbac.matchers.upstream_ip_port", + "category": "envoy.rbac.matchers", + "type_urls": [ + "envoy.extensions.rbac.matchers.upstream_ip_port.v3.UpstreamIpPortMatcher" + ] + }, + { + "name": "envoy.key_value.file_based", + "category": "envoy.common.key_value", + "type_urls": [ + "envoy.extensions.key_value.file_based.v3.FileBasedKeyValueStoreConfig" + ] + }, + { + "name": "envoy.matching.inputs.application_protocol", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_port", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput" + ] + }, + { + "name": "envoy.matching.inputs.direct_source_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.dns_san", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput" + ] + }, + { + "name": "envoy.matching.inputs.server_name", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ServerNameInput" + ] + }, + { + "name": "envoy.matching.inputs.source_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.source_port", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourcePortInput" + ] + }, + { + "name": "envoy.matching.inputs.source_type", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput" + ] + }, + { + "name": "envoy.matching.inputs.subject", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput" + ] + }, + { + "name": "envoy.matching.inputs.transport_protocol", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput" + ] + }, + { + "name": "envoy.matching.inputs.uri_san", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput" + ] + }, + { + "name": "dubbo", + "category": "envoy.dubbo_proxy.protocols" + }, + { + "name": "envoy.watchdog.abort_action", + "category": "envoy.guarddog_actions", + "type_urls": [ + "envoy.watchdog.v3.AbortActionConfig" + ] + }, + { + "name": "envoy.watchdog.profile_action", + "category": "envoy.guarddog_actions", + "type_urls": [ + "envoy.extensions.watchdog.profile_action.v3.ProfileActionConfig" + ] + }, + { + "name": "envoy.quic.crypto_stream.server.quiche", + "category": "envoy.quic.server.crypto_stream", + "type_urls": [ + "envoy.extensions.quic.crypto_stream.v3.CryptoServerStreamConfig" + ] + }, + { + "name": "envoy.regex_engines.google_re2", + "category": "envoy.regex_engines", + "type_urls": [ + "envoy.extensions.regex_engines.v3.GoogleRE2" + ] + }, + { + "name": "envoy.http.stateful_session.cookie", + "category": "envoy.http.stateful_session", + "type_urls": [ + "envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState" + ] + }, + { + "name": "envoy.http.stateful_session.header", + "category": "envoy.http.stateful_session", + "type_urls": [ + "envoy.extensions.http.stateful_session.header.v3.HeaderBasedSessionState" + ] + }, + { + "name": "envoy.matching.custom_matchers.trie_matcher", + "category": "envoy.matching.network.custom_matchers", + "type_urls": [ + "xds.type.matcher.v3.IPMatcher" + ] + }, + { + "name": "envoy.udp_packet_writer.default", + "category": "envoy.udp_packet_writer", + "type_urls": [ + "envoy.extensions.udp_packet_writer.v3.UdpDefaultWriterFactory" + ] + }, + { + "name": "envoy.udp_packet_writer.gso", + "category": "envoy.udp_packet_writer", + "type_urls": [ + "envoy.extensions.udp_packet_writer.v3.UdpGsoBatchWriterFactory" + ] + }, + { + "name": "envoy.quic.proof_source.filter_chain", + "category": "envoy.quic.proof_source", + "type_urls": [ + "envoy.extensions.quic.proof_source.v3.ProofSourceConfig" + ] + }, + { + "name": "envoy.resource_monitors.fixed_heap", + "category": "envoy.resource_monitors", + "type_urls": [ + "envoy.extensions.resource_monitors.fixed_heap.v3.FixedHeapConfig" + ] + }, + { + "name": "envoy.resource_monitors.injected_resource", + "category": "envoy.resource_monitors", + "type_urls": [ + "envoy.extensions.resource_monitors.injected_resource.v3.InjectedResourceConfig" + ] + }, + { + "name": "envoy.http.stateful_header_formatters.preserve_case", + "category": "envoy.http.stateful_header_formatters", + "type_urls": [ + "envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig" + ] + }, + { + "name": "preserve_case", + "category": "envoy.http.stateful_header_formatters" + }, + { + "name": "envoy.filters.thrift.header_to_metadata", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.header_to_metadata.v3.HeaderToMetadata" + ] + }, + { + "name": "envoy.filters.thrift.payload_to_metadata", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.payload_to_metadata.v3.PayloadToMetadata" + ] + }, + { + "name": "envoy.filters.thrift.rate_limit", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.ratelimit.v3.RateLimit" + ] + }, + { + "name": "envoy.filters.thrift.router", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.router.v3.Router" + ] + }, + { + "name": "envoy.tracers.datadog", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.DatadogConfig" + ] + }, + { + "name": "envoy.tracers.dynamic_ot", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.DynamicOtConfig" + ] + }, + { + "name": "envoy.tracers.opencensus", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.OpenCensusConfig" + ] + }, + { + "name": "envoy.tracers.opentelemetry", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.OpenTelemetryConfig" + ] + }, + { + "name": "envoy.tracers.skywalking", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.SkyWalkingConfig" + ] + }, + { + "name": "envoy.tracers.xray", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.XRayConfig" + ] + }, + { + "name": "envoy.tracers.zipkin", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.ZipkinConfig" + ] + }, + { + "name": "envoy.zipkin", + "category": "envoy.tracers" + }, + { + "name": "envoy.retry_priorities.previous_priorities", + "category": "envoy.retry_priorities", + "type_urls": [ + "envoy.extensions.retry.priority.previous_priorities.v3.PreviousPrioritiesConfig" + ] + }, + { + "name": "envoy.http.early_header_mutation.header_mutation", + "category": "envoy.http.early_header_mutation", + "type_urls": [ + "envoy.extensions.http.early_header_mutation.header_mutation.v3.HeaderMutation" + ] + }, + { + "name": "envoy.connection_handler.default", + "category": "envoy.connection_handler" + }, + { + "name": "envoy.transport_sockets.alts", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.alts.v3.Alts" + ] + }, + { + "name": "envoy.transport_sockets.http_11_proxy", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.http_11_proxy.v3.Http11ProxyUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.internal_upstream", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.internal_upstream.v3.InternalUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.quic", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.quic.v3.QuicUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.raw_buffer", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer" + ] + }, + { + "name": "envoy.transport_sockets.starttls", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.starttls.v3.UpstreamStartTlsConfig" + ] + }, + { + "name": "envoy.transport_sockets.tap", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tap.v3.Tap" + ] + }, + { + "name": "envoy.transport_sockets.tcp_stats", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tcp_stats.v3.Config" + ] + }, + { + "name": "envoy.transport_sockets.tls", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext" + ] + }, + { + "name": "envoy.transport_sockets.upstream_proxy_protocol", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport" + ] + }, + { + "name": "raw_buffer", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "starttls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "tls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "auto", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "framed", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "header", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "unframed", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "envoy.cluster.eds", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.logical_dns", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.original_dst", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.static", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.strict_dns", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.aggregate", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.dynamic_forward_proxy", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.redis", + "category": "envoy.clusters" + }, + { + "name": "envoy.access_loggers.extension_filters.cel", + "category": "envoy.access_loggers.extension_filters", + "type_urls": [ + "envoy.extensions.access_loggers.filters.cel.v3.ExpressionFilter" + ] + }, + { + "name": "auto", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "binary", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "binary/non-strict", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "compact", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "twitter", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "category": "envoy.upstream_options", + "type_urls": [ + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + ] + }, + { + "name": "envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions", + "category": "envoy.upstream_options", + "type_urls": [ + "envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions" + ] + }, + { + "name": "envoy.upstreams.http.http_protocol_options", + "category": "envoy.upstream_options" + }, + { + "name": "envoy.upstreams.tcp.tcp_protocol_options", + "category": "envoy.upstream_options" + }, + { + "name": "envoy.listener_manager_impl.default", + "category": "envoy.listener_manager_impl", + "type_urls": [ + "envoy.config.listener.v3.ListenerManager" + ] + }, + { + "name": "default", + "category": "network.connection.client" + }, + { + "name": "envoy_internal", + "category": "network.connection.client" + }, + { + "name": "envoy.filters.udp.dns_filter", + "category": "envoy.filters.udp_listener", + "type_urls": [ + "envoy.extensions.filters.udp.dns_filter.v3.DnsFilterConfig" + ] + }, + { + "name": "envoy.filters.udp_listener.udp_proxy", + "category": "envoy.filters.udp_listener", + "type_urls": [ + "envoy.extensions.filters.udp.udp_proxy.v3.UdpProxyConfig" + ] + }, + { + "name": "envoy.extensions.http.cache.file_system_http_cache", + "category": "envoy.http.cache", + "type_urls": [ + "envoy.extensions.http.cache.file_system_http_cache.v3.FileSystemHttpCacheConfig" + ] + }, + { + "name": "envoy.extensions.http.cache.simple", + "category": "envoy.http.cache", + "type_urls": [ + "envoy.extensions.http.cache.simple_http_cache.v3.SimpleHttpCacheConfig" + ] + }, + { + "name": "envoy.retry_host_predicates.omit_canary_hosts", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.omit_canary_hosts.v3.OmitCanaryHostsPredicate" + ] + }, + { + "name": "envoy.retry_host_predicates.omit_host_metadata", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.omit_host_metadata.v3.OmitHostMetadataConfig" + ] + }, + { + "name": "envoy.retry_host_predicates.previous_hosts", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate" + ] + }, + { + "name": "envoy.formatter.metadata", + "category": "envoy.formatter", + "type_urls": [ + "envoy.extensions.formatter.metadata.v3.Metadata" + ] + }, + { + "name": "envoy.formatter.req_without_query", + "category": "envoy.formatter", + "type_urls": [ + "envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery" + ] + }, + { + "name": "envoy.internal_redirect_predicates.allow_listed_routes", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.allow_listed_routes.v3.AllowListedRoutesConfig" + ] + }, + { + "name": "envoy.internal_redirect_predicates.previous_routes", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.previous_routes.v3.PreviousRoutesConfig" + ] + }, + { + "name": "envoy.internal_redirect_predicates.safe_cross_scheme", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.safe_cross_scheme.v3.SafeCrossSchemeConfig" + ] + }, + { + "name": "envoy.matching.custom_matchers.trie_matcher", + "category": "envoy.matching.http.custom_matchers", + "type_urls": [ + "xds.type.matcher.v3.IPMatcher" + ] + }, + { + "name": "envoy.filters.dubbo.router", + "category": "envoy.dubbo_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.dubbo_proxy.router.v3.Router" + ] + }, + { + "name": "envoy.echo", + "category": "envoy.filters.network" + }, + { + "name": "envoy.ext_authz", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.connection_limit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit" + ] + }, + { + "name": "envoy.filters.network.direct_response", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.direct_response.v3.Config" + ] + }, + { + "name": "envoy.filters.network.dubbo_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.dubbo_proxy.v3.DubboProxy" + ] + }, + { + "name": "envoy.filters.network.echo", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.echo.v3.Echo" + ] + }, + { + "name": "envoy.filters.network.ext_authz", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + ] + }, + { + "name": "envoy.filters.network.http_connection_manager", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager" + ] + }, + { + "name": "envoy.filters.network.local_ratelimit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.local_ratelimit.v3.LocalRateLimit" + ] + }, + { + "name": "envoy.filters.network.mongo_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy" + ] + }, + { + "name": "envoy.filters.network.ratelimit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.ratelimit.v3.RateLimit" + ] + }, + { + "name": "envoy.filters.network.rbac", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.rbac.v3.RBAC" + ] + }, + { + "name": "envoy.filters.network.redis_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.redis_proxy.v3.RedisProxy" + ] + }, + { + "name": "envoy.filters.network.sni_cluster", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + ] + }, + { + "name": "envoy.filters.network.sni_dynamic_forward_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.sni_dynamic_forward_proxy.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.network.tcp_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy" + ] + }, + { + "name": "envoy.filters.network.thrift_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.v3.ThriftProxy" + ] + }, + { + "name": "envoy.filters.network.wasm", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.filters.network.zookeeper_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.zookeeper_proxy.v3.ZooKeeperProxy" + ] + }, + { + "name": "envoy.http_connection_manager", + "category": "envoy.filters.network" + }, + { + "name": "envoy.mongo_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.ratelimit", + "category": "envoy.filters.network" + }, + { + "name": "envoy.redis_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.tcp_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.health_checkers.redis", + "category": "envoy.health_checkers", + "type_urls": [ + "envoy.extensions.health_checkers.redis.v3.Redis" + ] + }, + { + "name": "envoy.health_checkers.thrift", + "category": "envoy.health_checkers", + "type_urls": [ + "envoy.extensions.health_checkers.thrift.v3.Thrift" + ] + } + ] + }, + "static_resources": { + "clusters": [{ + "name": "xds_cluster", + "type": "STRICT_DNS", + "connect_timeout": "1s", + "transport_socket": { + "name": "envoy.transport_sockets.tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": { + "tls_maximum_protocol_version": "TLSv1_3" + }, + "tls_certificate_sds_secret_configs": [{ + "name": "xds_certificate", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-certificate.json" + } + } + }], + "validation_context_sds_secret_config": { + "name": "xds_trusted_ca", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-trusted-ca.json" + } + } + } + } + } + }, + "load_assignment": { + "cluster_name": "xds_cluster", + "endpoints": [{ + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "higress", + "port_value": 18000 + } + } + } + }] + }] + }, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + } + }] + }, + "dynamic_resources": { + "lds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + }, + "cds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + } + }, + "admin": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 15000 + } + }, + "access_log": [{ + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + }] + }, + "layered_runtime": { + "layers": [{ + "name": "runtime-0", + "rtds_layer": { + "name": "runtime-0", + "rtds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + } + } + }] + } + }, + "last_updated": "2023-02-23T09:05:23.422Z" + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ClustersConfigDump", + "version_info": "2", + "static_clusters": [{ + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "xds_cluster", + "type": "STRICT_DNS", + "connect_timeout": "1s", + "transport_socket": { + "name": "envoy.transport_sockets.tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": { + "tls_maximum_protocol_version": "TLSv1_3" + }, + "tls_certificate_sds_secret_configs": [{ + "name": "xds_certificate", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-certificate.json" + } + } + }], + "validation_context_sds_secret_config": { + "name": "xds_trusted_ca", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-trusted-ca.json" + } + } + } + } + } + }, + "load_assignment": { + "cluster_name": "xds_cluster", + "endpoints": [{ + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "higress", + "port_value": 18000 + } + } + } + }] + }] + }, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + } + }, + "last_updated": "2023-02-23T09:05:23.436Z" + }], + "dynamic_active_clusters": [{ + "version_info": "2a0a1698a9d3e05b802047b0cd36b52a070afa49042e1ba267168c5265c7cabf", + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "default-backend-rule-0-match-0-www.example.com", + "type": "STATIC", + "connect_timeout": "5s", + "dns_lookup_family": "V4_ONLY", + "outlier_detection": {}, + "common_lb_config": { + "locality_weighted_lb_config": {} + }, + "load_assignment": { + "cluster_name": "default-backend-rule-0-match-0-www.example.com", + "endpoints": [{ + "locality": {}, + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 3000 + } + } + }, + "load_balancing_weight": 1 + }], + "load_balancing_weight": 1 + }] + } + }, + "last_updated": "2023-02-23T09:05:38.443Z" + }] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ListenersConfigDump", + "version_info": "2", + "dynamic_listeners": [{ + "name": "default-higress-http", + "active_state": { + "version_info": "42c71fb50c315ee3a32b327da69f8cc0baf420bc84b747e82d9c38e1b0c33eb2", + "listener": { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "default-higress-http", + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 10080 + } + }, + "access_log": [{ + "name": "envoy.access_loggers.file", + "filter": { + "response_flag_filter": { + "flags": [ + "NR" + ] + } + }, + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/stdout" + } + }], + "default_filter_chain": { + "filters": [{ + "name": "envoy.filters.network.http_connection_manager", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "http", + "rds": { + "config_source": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + }, + "route_config_name": "default-higress-http" + }, + "http_filters": [{ + "name": "envoy.filters.http.router", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + }], + "access_log": [{ + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/stdout" + } + }], + "use_remote_address": true, + "upgrade_configs": [{ + "upgrade_type": "websocket" + }] + } + }] + } + }, + "last_updated": "2023-02-23T09:05:38.446Z" + } + }] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ScopedRoutesConfigDump" + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.RoutesConfigDump", + "dynamic_route_configs": [{ + "version_info": "cb1e51997a9c3aa6f4d920f39fd5bdbd966e9382b7b6bdf42efca8c22c6c3442", + "route_config": { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "default-higress-http", + "virtual_hosts": [{ + "name": "default-higress-http", + "domains": [ + "*" + ], + "routes": [{ + "match": { + "prefix": "/", + "headers": [{ + "name": ":authority", + "string_match": { + "exact": "www.example.com" + } + }] + }, + "route": { + "cluster": "default-backend-rule-0-match-0-www.example.com" + } + }] + }] + }, + "last_updated": "2023-02-23T09:05:38.448Z" + }] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.SecretsConfigDump", + "dynamic_active_secrets": [{ + "name": "xds_certificate", + "last_updated": "2023-02-23T09:05:23.442Z", + "secret": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "name": "xds_certificate", + "tls_certificate": { + "certificate_chain": { + "inline_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLekNDQWhPZ0F3SUJBZ0lFTnJRVi9qQU5CZ2txaGtpRzl3MEJBUXNGQURBc01SWXdGQVlEVlFRREV3MWwKYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEVlFRRkV3azFOalE0TXpRek9EVXdIaGNOTWpNd01qRTNNRE0wTVRJNApXaGNOTWpRd01qRTRNRE0wTVRJNFdqQU1NUW93Q0FZRFZRUUREQUVxTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGCkFBT0NBUThBTUlJQkNnS0NBUUVBNmdNSTJSNElEeE5mQ2o1YmZHU1hVUjF4YkVjRjE5VXlhVC9VUEZZcFltM0gKN2c4T3Z6YWRlelFyRkt3dG9PWWFDN0hjam8zVnVHSmhqSDQ1Z3lVbWFzSEg1Q1gzaWFlRlhxQXdVQjRqVTZQSgpBbElCZWlMRVdZVjN1VjMwcGlKK09DWFhrUEQzSFFVb0ZYbnljcHM3OE9PbjZoS0wwNUY0YkJsT2UrMFdIUHdECll2dFQ4TEdpVmcrSkxhR2lxaGgxOXY5endwQUd2akI2Z09kN1BjdkNQNFExUHdkMWdMSnNXVFNweGhDUEVPb2kKV2ZSOG56RERVUHU5aXc2QTJObW1XQ1FxSVNYcDlZUmJMTEdjZnV4VURjcFVYMHpqY0xvcE1sajBnM0RkYVpWRwpzNm9JcW9BSjZ6MFhvdWwrM0ZZdUtJYy8rT1V3VkR1VkI4K0ZRZzlYdlFJREFRQUJvM1V3Y3pBT0JnTlZIUThCCkFmOEVCQU1DQlBBd0hRWURWUjBPQkJZRUZKaUJ3cytVaFRlT2p1L1ZXT29LQWNTSmZBeXVNQjhHQTFVZEl3UVkKTUJhQUZCT3kvOGkxeVMxRWxpN0tNK0gyeXZEM1BJMG1NQ0VHQTFVZEVRUWFNQmlDRmlvdVpXNTJiM2t0WjJGMApaWGRoZVMxemVYTjBaVzB3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUZraHdIakZtQWxqdEpheU54WitodURGCm5UdWd0REZvSTBFT2J0cUhLYnloWU9sdlNFdkhxbFNQSHNRUUhmQnQwbHpOOEtGUTd2YWxTSHRBZStlNzBETHkKaGY3TDQ3eklST3NLcmtmb0tjMjRqaUhNQkVwbCtJdjllU1RWVG9WemxzazVZUGxET2lrMzZpRUY3WDVVZ0RheApsVllZZnpSYzRUb0poODMwT285Wm9pai9LM295dVNXcTVGRzVFWExmeW9tQzZPQ3dxRm5GNzRSM21FTjVheDRlCnppVm5QVDNxVmFZdytzNngwSVhHU282U2M3Q2lUbmMrckFNa3FJNVNsK2p5RHhKTkZBQlIvRllCcTQzK1B1UGkKN0YxOEw0N2l3aVFFYU82NUJzU2hlYmg1Qk1VbytDdzIyM3JsMGRpTldwY3FrdVhtT1BWNDlrWkZkdHpFNytVPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==" + }, + "private_key": { + "inline_bytes": "W3JlZGFjdGVkXQ==" + } + } + } + }, + { + "name": "xds_trusted_ca", + "last_updated": "2023-02-23T09:05:23.447Z", + "secret": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "name": "xds_trusted_ca", + "validation_context": { + "trusted_ca": { + "inline_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHRENDQWdDZ0F3SUJBZ0lFSWFxd1VUQU5CZ2txaGtpRzl3MEJBUXNGQURBc01SWXdGQVlEVlFRREV3MWwKYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEVlFRRkV3azFOalE0TXpRek9EVXdIaGNOTWpNd01qRTNNRE0wTVRJNApXaGNOTWpRd01qRTRNRE0wTVRJNFdqQXNNUll3RkFZRFZRUURFdzFsYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEClZRUUZFd2sxTmpRNE16UXpPRFV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRDIKeFMrNkRWY2FvbHFkVVBzTHZwNUtQMEQyV0hrTkVEY0tPeml3bzZNYm9wczFLYWJnNXVYSVl5T21JRWNTTXNKNwpHbVAxMlJjK0J3V1dFWXRrTHVPU3BwQm1lSjN3aDRrUlVRVTRTemRFU1dDcU40RTNpcTJib3FFVm53SkFGQ1ZpCldldGVjZkZsODZFalliQUxxSnRCbGJCbFFQM1ZMZ1hva0VVamJ4QmFobE1wZitUWkVJNFBuam1zUWN5a21LeXIKaDJwdmM3cnZYb29HTlhTM0Q0eFc1VDY3dmxLYi94UlM3c2gwTkJEU0dtTE1jY2pxWFZXazVOR2lBWVB3dXBWSwpTWG02dnZXUFZCdEd1bkZhS0JSRGx4TlJrb0wzRUN6UkNtenoxR2ZYMGJkSm1leElOM2VIUFBRdkd0M0txeUlnCkgrYnc0OXpqdlVUb2dNcXFpTlcvQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQQmdOVkhSTUIKQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJRVHN2L0l0Y2t0UkpZdXlqUGg5c3J3OXp5TkpqQU5CZ2txaGtpRwo5dzBCQVFzRkFBT0NBUUVBd2dvZEsxalhVWFZDVXBTSjE0cEo3S3ZobWZPT1hkaVNISmNSSzlIUzI1c2xwOWN2CkJDSndmWUZmanJ4Rmc5TnV4aVpiM01oVXk5MDBqenBPdk1QWStEeUxFWFVxTGd5ZlBMUzYveVliem8yZHdwdzMKOCtrTXlsQUFlZmtaSW9oT0VhYSsvNFFBVVVGZVp1a1B6bmF6RzZIWnZKQkNxWVdRNXBaSSt3WTI1dzhEU0VOMgpkOCswVkpzWU5IdUk4aXhneGZhUkRycW5LRHBMUGJ3Z3VaRDl6ZkV3dVFaNG1oeEd0Vk1wR0NLSndscWFhdXJ0CkF5aGhzOXBHNERndkpSY1BLeFY4bndRdzZtSm55dkIxcExxTW1aQTVqZWhxbFNvUGVpWUlBMk1neU83cTVPYmMKL040bzBNTVdvZ1piRWR6aTBnTXJRT2lpNE41Q0ZlakVrYStIMmc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==" + }, + "match_typed_subject_alt_names": [{ + "san_type": "DNS", + "matcher": { + "exact": "higress" + } + }] + } + } + } + ] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump", + "staticEndpointConfigs": [{ + "endpointConfig": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "xds_cluster", + "endpoints": [{ + "locality": {}, + "lbEndpoints": [{ + "endpoint": { + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 18000 + } + }, + "healthCheckConfig": {}, + "hostname": "higress" + }, + "healthStatus": "HEALTHY", + "metadata": {}, + "loadBalancingWeight": 1 + }] + }], + "policy": { + "overprovisioningFactor": 140 + } + } + }] + } + ] +} diff --git a/pkg/cmd/hgctl/testdata/config/output/out.all.yaml b/pkg/cmd/hgctl/testdata/config/output/out.all.yaml new file mode 100644 index 0000000000..f79d4c7160 --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.all.yaml @@ -0,0 +1,1305 @@ +--- +configs: +- "@type": type.googleapis.com/envoy.admin.v3.BootstrapConfigDump + bootstrap: + node: + user_agent_name: envoy + user_agent_build_version: + version: + major_number: 1 + minor_number: 26 + metadata: + revision.status: Clean + revision.sha: 14111e3c62d3d38b0c921cb7011fd0a94e880aed + ssl.version: BoringSSL + build.label: dev + build.type: RELEASE + extensions: + - name: envoy.filters.connection_pools.tcp.generic + category: envoy.upstreams + type_urls: + - envoy.extensions.upstreams.tcp.generic.v3.GenericConnectionPoolProto + - name: envoy.rate_limit_descriptors.expr + category: envoy.rate_limit_descriptors + type_urls: + - envoy.extensions.rate_limit_descriptors.expr.v3.Descriptor + - name: envoy.matching.inputs.destination_ip + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput + - name: envoy.matching.inputs.destination_port + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + - name: envoy.matching.inputs.direct_source_ip + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput + - name: envoy.matching.inputs.dns_san + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput + - name: envoy.matching.inputs.request_headers + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpRequestHeaderMatchInput + - name: envoy.matching.inputs.request_trailers + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpRequestTrailerMatchInput + - name: envoy.matching.inputs.response_headers + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpResponseHeaderMatchInput + - name: envoy.matching.inputs.response_trailers + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpResponseTrailerMatchInput + - name: envoy.matching.inputs.server_name + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.ServerNameInput + - name: envoy.matching.inputs.source_ip + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourceIPInput + - name: envoy.matching.inputs.source_port + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourcePortInput + - name: envoy.matching.inputs.source_type + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput + - name: envoy.matching.inputs.status_code_class_input + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpResponseStatusCodeClassMatchInput + - name: envoy.matching.inputs.status_code_input + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpResponseStatusCodeMatchInput + - name: envoy.matching.inputs.subject + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput + - name: envoy.matching.inputs.uri_san + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput + - name: query_params + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpRequestQueryParamMatchInput + - name: envoy.tls.cert_validator.default + category: envoy.tls.cert_validator + - name: envoy.tls.cert_validator.spiffe + category: envoy.tls.cert_validator + - name: envoy.path.match.uri_template.uri_template_matcher + category: envoy.path.match + type_urls: + - envoy.extensions.path.match.uri_template.v3.UriTemplateMatchConfig + - name: envoy.http.original_ip_detection.custom_header + category: envoy.http.original_ip_detection + type_urls: + - envoy.extensions.http.original_ip_detection.custom_header.v3.CustomHeaderConfig + - name: envoy.http.original_ip_detection.xff + category: envoy.http.original_ip_detection + type_urls: + - envoy.extensions.http.original_ip_detection.xff.v3.XffConfig + - name: envoy.buffer + category: envoy.filters.http.upstream + - name: envoy.filters.http.admission_control + category: envoy.filters.http.upstream + type_urls: + - envoy.extensions.filters.http.admission_control.v3.AdmissionControl + - name: envoy.filters.http.buffer + category: envoy.filters.http.upstream + type_urls: + - envoy.extensions.filters.http.buffer.v3.Buffer + - envoy.extensions.filters.http.buffer.v3.BufferPerRoute + - name: envoy.filters.http.upstream_codec + category: envoy.filters.http.upstream + type_urls: + - envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + - name: envoy.route.early_data_policy.default + category: envoy.route.early_data_policy + type_urls: + - envoy.extensions.early_data.v3.DefaultEarlyDataPolicy + - name: envoy.compression.brotli.compressor + category: envoy.compression.compressor + type_urls: + - envoy.extensions.compression.brotli.compressor.v3.Brotli + - name: envoy.compression.gzip.compressor + category: envoy.compression.compressor + type_urls: + - envoy.extensions.compression.gzip.compressor.v3.Gzip + - name: envoy.compression.zstd.compressor + category: envoy.compression.compressor + type_urls: + - envoy.extensions.compression.zstd.compressor.v3.Zstd + - name: envoy.compression.brotli.decompressor + category: envoy.compression.decompressor + type_urls: + - envoy.extensions.compression.brotli.decompressor.v3.Brotli + - name: envoy.compression.gzip.decompressor + category: envoy.compression.decompressor + type_urls: + - envoy.extensions.compression.gzip.decompressor.v3.Gzip + - name: envoy.compression.zstd.decompressor + category: envoy.compression.decompressor + type_urls: + - envoy.extensions.compression.zstd.decompressor.v3.Zstd + - name: envoy.wasm.runtime.null + category: envoy.wasm.runtime + - name: envoy.wasm.runtime.v8 + category: envoy.wasm.runtime + - name: envoy.dog_statsd + category: envoy.stats_sinks + - name: envoy.graphite_statsd + category: envoy.stats_sinks + - name: envoy.metrics_service + category: envoy.stats_sinks + - name: envoy.stat_sinks.dog_statsd + category: envoy.stats_sinks + type_urls: + - envoy.config.metrics.v3.DogStatsdSink + - name: envoy.stat_sinks.graphite_statsd + category: envoy.stats_sinks + type_urls: + - envoy.extensions.stat_sinks.graphite_statsd.v3.GraphiteStatsdSink + - name: envoy.stat_sinks.hystrix + category: envoy.stats_sinks + type_urls: + - envoy.config.metrics.v3.HystrixSink + - name: envoy.stat_sinks.metrics_service + category: envoy.stats_sinks + type_urls: + - envoy.config.metrics.v3.MetricsServiceConfig + - name: envoy.stat_sinks.statsd + category: envoy.stats_sinks + type_urls: + - envoy.config.metrics.v3.StatsdSink + - name: envoy.stat_sinks.wasm + category: envoy.stats_sinks + type_urls: + - envoy.extensions.stat_sinks.wasm.v3.Wasm + - name: envoy.statsd + category: envoy.stats_sinks + - name: envoy.path.rewrite.uri_template.uri_template_rewriter + category: envoy.path.rewrite + type_urls: + - envoy.extensions.path.rewrite.uri_template.v3.UriTemplateRewriteConfig + - name: envoy.extensions.http.custom_response.local_response_policy + category: envoy.http.custom_response + type_urls: + - envoy.extensions.http.custom_response.local_response_policy.v3.LocalResponsePolicy + - name: envoy.extensions.http.custom_response.redirect_policy + category: envoy.http.custom_response + type_urls: + - envoy.extensions.http.custom_response.redirect_policy.v3.RedirectPolicy + - name: envoy.matching.actions.format_string + category: envoy.matching.action + type_urls: + - envoy.config.core.v3.SubstitutionFormatString + - name: filter-chain-name + category: envoy.matching.action + type_urls: + - google.protobuf.StringValue + - name: envoy.quic.deterministic_connection_id_generator + category: envoy.quic.connection_id_generator + type_urls: + - envoy.extensions.quic.connection_id_generator.v3.DeterministicConnectionIdGeneratorConfig + - name: envoy.network.dns_resolver.cares + category: envoy.network.dns_resolver + type_urls: + - envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig + - name: envoy.network.dns_resolver.getaddrinfo + category: envoy.network.dns_resolver + type_urls: + - envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig + - name: envoy.bootstrap.internal_listener + category: envoy.bootstrap + type_urls: + - envoy.extensions.bootstrap.internal_listener.v3.InternalListener + - name: envoy.bootstrap.wasm + category: envoy.bootstrap + type_urls: + - envoy.extensions.wasm.v3.WasmService + - name: envoy.extensions.network.socket_interface.default_socket_interface + category: envoy.bootstrap + type_urls: + - envoy.extensions.network.socket_interface.v3.DefaultSocketInterface + - name: envoy.filters.listener.http_inspector + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.http_inspector.v3.HttpInspector + - name: envoy.filters.listener.original_dst + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.original_dst.v3.OriginalDst + - name: envoy.filters.listener.original_src + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.original_src.v3.OriginalSrc + - name: envoy.filters.listener.proxy_protocol + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol + - name: envoy.filters.listener.tls_inspector + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + - name: envoy.listener.http_inspector + category: envoy.filters.listener + - name: envoy.listener.original_dst + category: envoy.filters.listener + - name: envoy.listener.original_src + category: envoy.filters.listener + - name: envoy.listener.proxy_protocol + category: envoy.filters.listener + - name: envoy.listener.tls_inspector + category: envoy.filters.listener + - name: envoy.matching.common_inputs.environment_variable + category: envoy.matching.common_inputs + type_urls: + - envoy.extensions.matching.common_inputs.environment_variable.v3.Config + - name: envoy.matching.matchers.consistent_hashing + category: envoy.matching.input_matchers + type_urls: + - envoy.extensions.matching.input_matchers.consistent_hashing.v3.ConsistentHashing + - name: envoy.matching.matchers.ip + category: envoy.matching.input_matchers + type_urls: + - envoy.extensions.matching.input_matchers.ip.v3.Ip + - name: envoy.grpc_credentials.aws_iam + category: envoy.grpc_credentials + - name: envoy.grpc_credentials.default + category: envoy.grpc_credentials + - name: envoy.grpc_credentials.file_based_metadata + category: envoy.grpc_credentials + - name: envoy.request_id.uuid + category: envoy.request_id + type_urls: + - envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig + - name: envoy.load_balancing_policies.least_request + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + - name: envoy.load_balancing_policies.maglev + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.maglev.v3.Maglev + - name: envoy.load_balancing_policies.random + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.random.v3.Random + - name: envoy.load_balancing_policies.ring_hash + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash + - name: envoy.load_balancing_policies.round_robin + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin + - name: envoy.ip + category: envoy.resolvers + - name: envoy.bandwidth_limit + category: envoy.filters.http + - name: envoy.buffer + category: envoy.filters.http + - name: envoy.cors + category: envoy.filters.http + - name: envoy.csrf + category: envoy.filters.http + - name: envoy.ext_authz + category: envoy.filters.http + - name: envoy.ext_proc + category: envoy.filters.http + - name: envoy.fault + category: envoy.filters.http + - name: envoy.filters.http.adaptive_concurrency + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.adaptive_concurrency.v3.AdaptiveConcurrency + - name: envoy.filters.http.admission_control + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.admission_control.v3.AdmissionControl + - name: envoy.filters.http.alternate_protocols_cache + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig + - name: envoy.filters.http.aws_lambda + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.aws_lambda.v3.Config + - envoy.extensions.filters.http.aws_lambda.v3.PerRouteConfig + - name: envoy.filters.http.aws_request_signing + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning + - name: envoy.filters.http.bandwidth_limit + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.bandwidth_limit.v3.BandwidthLimit + - name: envoy.filters.http.buffer + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.buffer.v3.Buffer + - envoy.extensions.filters.http.buffer.v3.BufferPerRoute + - name: envoy.filters.http.cache + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.cache.v3.CacheConfig + - name: envoy.filters.http.cdn_loop + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.cdn_loop.v3.CdnLoopConfig + - name: envoy.filters.http.composite + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.composite.v3.Composite + - name: envoy.filters.http.compressor + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.compressor.v3.Compressor + - envoy.extensions.filters.http.compressor.v3.CompressorPerRoute + - name: envoy.filters.http.connect_grpc_bridge + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.connect_grpc_bridge.v3.FilterConfig + - name: envoy.filters.http.cors + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.cors.v3.Cors + - envoy.extensions.filters.http.cors.v3.CorsPolicy + - name: envoy.filters.http.csrf + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.csrf.v3.CsrfPolicy + - name: envoy.filters.http.custom_response + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.custom_response.v3.CustomResponse + - name: envoy.filters.http.decompressor + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.decompressor.v3.Decompressor + - name: envoy.filters.http.dynamic_forward_proxy + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig + - envoy.extensions.filters.http.dynamic_forward_proxy.v3.PerRouteConfig + - name: envoy.filters.http.ext_authz + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + - envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute + - name: envoy.filters.http.ext_proc + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute + - envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + - name: envoy.filters.http.fault + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.fault.v3.HTTPFault + - name: envoy.filters.http.file_system_buffer + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.file_system_buffer.v3.FileSystemBufferFilterConfig + - name: envoy.filters.http.gcp_authn + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig + - name: envoy.filters.http.grpc_http1_bridge + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_http1_bridge.v3.Config + - name: envoy.filters.http.grpc_http1_reverse_bridge + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfig + - envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfigPerRoute + - name: envoy.filters.http.grpc_json_transcoder + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder + - name: envoy.filters.http.grpc_stats + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_stats.v3.FilterConfig + - name: envoy.filters.http.grpc_web + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_web.v3.GrpcWeb + - name: envoy.filters.http.header_to_metadata + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.header_to_metadata.v3.Config + - name: envoy.filters.http.health_check + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.health_check.v3.HealthCheck + - name: envoy.filters.http.ip_tagging + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.ip_tagging.v3.IPTagging + - name: envoy.filters.http.jwt_authn + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication + - envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig + - name: envoy.filters.http.local_ratelimit + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit + - name: envoy.filters.http.lua + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.lua.v3.Lua + - envoy.extensions.filters.http.lua.v3.LuaPerRoute + - name: envoy.filters.http.match_delegate + category: envoy.filters.http + type_urls: + - envoy.extensions.common.matching.v3.ExtensionWithMatcher + - name: envoy.filters.http.oauth2 + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.oauth2.v3.OAuth2 + - name: envoy.filters.http.on_demand + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.on_demand.v3.OnDemand + - envoy.extensions.filters.http.on_demand.v3.PerRouteConfig + - name: envoy.filters.http.original_src + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.original_src.v3.OriginalSrc + - name: envoy.filters.http.rate_limit_quota + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaFilterConfig + - envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaOverride + - name: envoy.filters.http.ratelimit + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.ratelimit.v3.RateLimit + - envoy.extensions.filters.http.ratelimit.v3.RateLimitPerRoute + - name: envoy.filters.http.rbac + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.rbac.v3.RBAC + - envoy.extensions.filters.http.rbac.v3.RBACPerRoute + - name: envoy.filters.http.router + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.router.v3.Router + - name: envoy.filters.http.set_metadata + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.set_metadata.v3.Config + - name: envoy.filters.http.stateful_session + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.stateful_session.v3.StatefulSession + - envoy.extensions.filters.http.stateful_session.v3.StatefulSessionPerRoute + - name: envoy.filters.http.tap + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.tap.v3.Tap + - name: envoy.filters.http.wasm + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.wasm.v3.Wasm + - name: envoy.grpc_http1_bridge + category: envoy.filters.http + - name: envoy.grpc_json_transcoder + category: envoy.filters.http + - name: envoy.grpc_web + category: envoy.filters.http + - name: envoy.health_check + category: envoy.filters.http + - name: envoy.ip_tagging + category: envoy.filters.http + - name: envoy.local_rate_limit + category: envoy.filters.http + - name: envoy.lua + category: envoy.filters.http + - name: envoy.rate_limit + category: envoy.filters.http + - name: envoy.router + category: envoy.filters.http + - name: envoy.access_loggers.file + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.file.v3.FileAccessLog + - name: envoy.access_loggers.http_grpc + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig + - name: envoy.access_loggers.open_telemetry + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.open_telemetry.v3.OpenTelemetryAccessLogConfig + - name: envoy.access_loggers.stderr + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.stream.v3.StderrAccessLog + - name: envoy.access_loggers.stdout + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + - name: envoy.access_loggers.tcp_grpc + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.grpc.v3.TcpGrpcAccessLogConfig + - name: envoy.access_loggers.wasm + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.wasm.v3.WasmAccessLog + - name: envoy.file_access_log + category: envoy.access_loggers + - name: envoy.http_grpc_access_log + category: envoy.access_loggers + - name: envoy.open_telemetry_access_log + category: envoy.access_loggers + - name: envoy.stderr_access_log + category: envoy.access_loggers + - name: envoy.stdout_access_log + category: envoy.access_loggers + - name: envoy.tcp_grpc_access_log + category: envoy.access_loggers + - name: envoy.wasm_access_log + category: envoy.access_loggers + - name: envoy.config.validators.minimum_clusters + category: envoy.config.validators + - name: envoy.config.validators.minimum_clusters_validator + category: envoy.config.validators + type_urls: + - envoy.extensions.config.validators.minimum_clusters.v3.MinimumClustersValidator + - name: envoy.http.header_validators.envoy_default + category: envoy.http.header_validators + type_urls: + - envoy.extensions.http.header_validators.envoy_default.v3.HeaderValidatorConfig + - name: dubbo.hessian2 + category: envoy.dubbo_proxy.serializers + - name: quic.http_server_connection.default + category: quic.http_server_connection + - name: envoy.transport_sockets.alts + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.alts.v3.Alts + - name: envoy.transport_sockets.quic + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.quic.v3.QuicDownstreamTransport + - name: envoy.transport_sockets.raw_buffer + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer + - name: envoy.transport_sockets.starttls + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.starttls.v3.StartTlsConfig + - name: envoy.transport_sockets.tap + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.tap.v3.Tap + - name: envoy.transport_sockets.tcp_stats + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.tcp_stats.v3.Config + - name: envoy.transport_sockets.tls + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + - name: raw_buffer + category: envoy.transport_sockets.downstream + - name: starttls + category: envoy.transport_sockets.downstream + - name: tls + category: envoy.transport_sockets.downstream + - name: envoy.rbac.matchers.upstream_ip_port + category: envoy.rbac.matchers + type_urls: + - envoy.extensions.rbac.matchers.upstream_ip_port.v3.UpstreamIpPortMatcher + - name: envoy.key_value.file_based + category: envoy.common.key_value + type_urls: + - envoy.extensions.key_value.file_based.v3.FileBasedKeyValueStoreConfig + - name: envoy.matching.inputs.application_protocol + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + - name: envoy.matching.inputs.destination_ip + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput + - name: envoy.matching.inputs.destination_port + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + - name: envoy.matching.inputs.direct_source_ip + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput + - name: envoy.matching.inputs.dns_san + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput + - name: envoy.matching.inputs.server_name + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.ServerNameInput + - name: envoy.matching.inputs.source_ip + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourceIPInput + - name: envoy.matching.inputs.source_port + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourcePortInput + - name: envoy.matching.inputs.source_type + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput + - name: envoy.matching.inputs.subject + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput + - name: envoy.matching.inputs.transport_protocol + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput + - name: envoy.matching.inputs.uri_san + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput + - name: dubbo + category: envoy.dubbo_proxy.protocols + - name: envoy.watchdog.abort_action + category: envoy.guarddog_actions + type_urls: + - envoy.watchdog.v3.AbortActionConfig + - name: envoy.watchdog.profile_action + category: envoy.guarddog_actions + type_urls: + - envoy.extensions.watchdog.profile_action.v3.ProfileActionConfig + - name: envoy.quic.crypto_stream.server.quiche + category: envoy.quic.server.crypto_stream + type_urls: + - envoy.extensions.quic.crypto_stream.v3.CryptoServerStreamConfig + - name: envoy.regex_engines.google_re2 + category: envoy.regex_engines + type_urls: + - envoy.extensions.regex_engines.v3.GoogleRE2 + - name: envoy.http.stateful_session.cookie + category: envoy.http.stateful_session + type_urls: + - envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState + - name: envoy.http.stateful_session.header + category: envoy.http.stateful_session + type_urls: + - envoy.extensions.http.stateful_session.header.v3.HeaderBasedSessionState + - name: envoy.matching.custom_matchers.trie_matcher + category: envoy.matching.network.custom_matchers + type_urls: + - xds.type.matcher.v3.IPMatcher + - name: envoy.udp_packet_writer.default + category: envoy.udp_packet_writer + type_urls: + - envoy.extensions.udp_packet_writer.v3.UdpDefaultWriterFactory + - name: envoy.udp_packet_writer.gso + category: envoy.udp_packet_writer + type_urls: + - envoy.extensions.udp_packet_writer.v3.UdpGsoBatchWriterFactory + - name: envoy.quic.proof_source.filter_chain + category: envoy.quic.proof_source + type_urls: + - envoy.extensions.quic.proof_source.v3.ProofSourceConfig + - name: envoy.resource_monitors.fixed_heap + category: envoy.resource_monitors + type_urls: + - envoy.extensions.resource_monitors.fixed_heap.v3.FixedHeapConfig + - name: envoy.resource_monitors.injected_resource + category: envoy.resource_monitors + type_urls: + - envoy.extensions.resource_monitors.injected_resource.v3.InjectedResourceConfig + - name: envoy.http.stateful_header_formatters.preserve_case + category: envoy.http.stateful_header_formatters + type_urls: + - envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig + - name: preserve_case + category: envoy.http.stateful_header_formatters + - name: envoy.filters.thrift.header_to_metadata + category: envoy.thrift_proxy.filters + type_urls: + - envoy.extensions.filters.network.thrift_proxy.filters.header_to_metadata.v3.HeaderToMetadata + - name: envoy.filters.thrift.payload_to_metadata + category: envoy.thrift_proxy.filters + type_urls: + - envoy.extensions.filters.network.thrift_proxy.filters.payload_to_metadata.v3.PayloadToMetadata + - name: envoy.filters.thrift.rate_limit + category: envoy.thrift_proxy.filters + type_urls: + - envoy.extensions.filters.network.thrift_proxy.filters.ratelimit.v3.RateLimit + - name: envoy.filters.thrift.router + category: envoy.thrift_proxy.filters + type_urls: + - envoy.extensions.filters.network.thrift_proxy.router.v3.Router + - name: envoy.tracers.datadog + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.DatadogConfig + - name: envoy.tracers.dynamic_ot + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.DynamicOtConfig + - name: envoy.tracers.opencensus + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.OpenCensusConfig + - name: envoy.tracers.opentelemetry + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.OpenTelemetryConfig + - name: envoy.tracers.skywalking + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.SkyWalkingConfig + - name: envoy.tracers.xray + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.XRayConfig + - name: envoy.tracers.zipkin + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.ZipkinConfig + - name: envoy.zipkin + category: envoy.tracers + - name: envoy.retry_priorities.previous_priorities + category: envoy.retry_priorities + type_urls: + - envoy.extensions.retry.priority.previous_priorities.v3.PreviousPrioritiesConfig + - name: envoy.http.early_header_mutation.header_mutation + category: envoy.http.early_header_mutation + type_urls: + - envoy.extensions.http.early_header_mutation.header_mutation.v3.HeaderMutation + - name: envoy.connection_handler.default + category: envoy.connection_handler + - name: envoy.transport_sockets.alts + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.alts.v3.Alts + - name: envoy.transport_sockets.http_11_proxy + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.http_11_proxy.v3.Http11ProxyUpstreamTransport + - name: envoy.transport_sockets.internal_upstream + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.internal_upstream.v3.InternalUpstreamTransport + - name: envoy.transport_sockets.quic + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.quic.v3.QuicUpstreamTransport + - name: envoy.transport_sockets.raw_buffer + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer + - name: envoy.transport_sockets.starttls + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.starttls.v3.UpstreamStartTlsConfig + - name: envoy.transport_sockets.tap + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.tap.v3.Tap + - name: envoy.transport_sockets.tcp_stats + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.tcp_stats.v3.Config + - name: envoy.transport_sockets.tls + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + - name: envoy.transport_sockets.upstream_proxy_protocol + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport + - name: raw_buffer + category: envoy.transport_sockets.upstream + - name: starttls + category: envoy.transport_sockets.upstream + - name: tls + category: envoy.transport_sockets.upstream + - name: auto + category: envoy.thrift_proxy.transports + - name: framed + category: envoy.thrift_proxy.transports + - name: header + category: envoy.thrift_proxy.transports + - name: unframed + category: envoy.thrift_proxy.transports + - name: envoy.cluster.eds + category: envoy.clusters + - name: envoy.cluster.logical_dns + category: envoy.clusters + - name: envoy.cluster.original_dst + category: envoy.clusters + - name: envoy.cluster.static + category: envoy.clusters + - name: envoy.cluster.strict_dns + category: envoy.clusters + - name: envoy.clusters.aggregate + category: envoy.clusters + - name: envoy.clusters.dynamic_forward_proxy + category: envoy.clusters + - name: envoy.clusters.redis + category: envoy.clusters + - name: envoy.access_loggers.extension_filters.cel + category: envoy.access_loggers.extension_filters + type_urls: + - envoy.extensions.access_loggers.filters.cel.v3.ExpressionFilter + - name: auto + category: envoy.thrift_proxy.protocols + - name: binary + category: envoy.thrift_proxy.protocols + - name: binary/non-strict + category: envoy.thrift_proxy.protocols + - name: compact + category: envoy.thrift_proxy.protocols + - name: twitter + category: envoy.thrift_proxy.protocols + - name: envoy.extensions.upstreams.http.v3.HttpProtocolOptions + category: envoy.upstream_options + type_urls: + - envoy.extensions.upstreams.http.v3.HttpProtocolOptions + - name: envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions + category: envoy.upstream_options + type_urls: + - envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions + - name: envoy.upstreams.http.http_protocol_options + category: envoy.upstream_options + - name: envoy.upstreams.tcp.tcp_protocol_options + category: envoy.upstream_options + - name: envoy.listener_manager_impl.default + category: envoy.listener_manager_impl + type_urls: + - envoy.config.listener.v3.ListenerManager + - name: default + category: network.connection.client + - name: envoy_internal + category: network.connection.client + - name: envoy.filters.udp.dns_filter + category: envoy.filters.udp_listener + type_urls: + - envoy.extensions.filters.udp.dns_filter.v3.DnsFilterConfig + - name: envoy.filters.udp_listener.udp_proxy + category: envoy.filters.udp_listener + type_urls: + - envoy.extensions.filters.udp.udp_proxy.v3.UdpProxyConfig + - name: envoy.extensions.http.cache.file_system_http_cache + category: envoy.http.cache + type_urls: + - envoy.extensions.http.cache.file_system_http_cache.v3.FileSystemHttpCacheConfig + - name: envoy.extensions.http.cache.simple + category: envoy.http.cache + type_urls: + - envoy.extensions.http.cache.simple_http_cache.v3.SimpleHttpCacheConfig + - name: envoy.retry_host_predicates.omit_canary_hosts + category: envoy.retry_host_predicates + type_urls: + - envoy.extensions.retry.host.omit_canary_hosts.v3.OmitCanaryHostsPredicate + - name: envoy.retry_host_predicates.omit_host_metadata + category: envoy.retry_host_predicates + type_urls: + - envoy.extensions.retry.host.omit_host_metadata.v3.OmitHostMetadataConfig + - name: envoy.retry_host_predicates.previous_hosts + category: envoy.retry_host_predicates + type_urls: + - envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate + - name: envoy.formatter.metadata + category: envoy.formatter + type_urls: + - envoy.extensions.formatter.metadata.v3.Metadata + - name: envoy.formatter.req_without_query + category: envoy.formatter + type_urls: + - envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery + - name: envoy.internal_redirect_predicates.allow_listed_routes + category: envoy.internal_redirect_predicates + type_urls: + - envoy.extensions.internal_redirect.allow_listed_routes.v3.AllowListedRoutesConfig + - name: envoy.internal_redirect_predicates.previous_routes + category: envoy.internal_redirect_predicates + type_urls: + - envoy.extensions.internal_redirect.previous_routes.v3.PreviousRoutesConfig + - name: envoy.internal_redirect_predicates.safe_cross_scheme + category: envoy.internal_redirect_predicates + type_urls: + - envoy.extensions.internal_redirect.safe_cross_scheme.v3.SafeCrossSchemeConfig + - name: envoy.matching.custom_matchers.trie_matcher + category: envoy.matching.http.custom_matchers + type_urls: + - xds.type.matcher.v3.IPMatcher + - name: envoy.filters.dubbo.router + category: envoy.dubbo_proxy.filters + type_urls: + - envoy.extensions.filters.network.dubbo_proxy.router.v3.Router + - name: envoy.echo + category: envoy.filters.network + - name: envoy.ext_authz + category: envoy.filters.network + - name: envoy.filters.network.connection_limit + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit + - name: envoy.filters.network.direct_response + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.direct_response.v3.Config + - name: envoy.filters.network.dubbo_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.dubbo_proxy.v3.DubboProxy + - name: envoy.filters.network.echo + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.echo.v3.Echo + - name: envoy.filters.network.ext_authz + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.ext_authz.v3.ExtAuthz + - name: envoy.filters.network.http_connection_manager + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + - name: envoy.filters.network.local_ratelimit + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.local_ratelimit.v3.LocalRateLimit + - name: envoy.filters.network.mongo_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy + - name: envoy.filters.network.ratelimit + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.ratelimit.v3.RateLimit + - name: envoy.filters.network.rbac + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.rbac.v3.RBAC + - name: envoy.filters.network.redis_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.redis_proxy.v3.RedisProxy + - name: envoy.filters.network.sni_cluster + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.sni_cluster.v3.SniCluster + - name: envoy.filters.network.sni_dynamic_forward_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.sni_dynamic_forward_proxy.v3.FilterConfig + - name: envoy.filters.network.tcp_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + - name: envoy.filters.network.thrift_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.thrift_proxy.v3.ThriftProxy + - name: envoy.filters.network.wasm + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.wasm.v3.Wasm + - name: envoy.filters.network.zookeeper_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.zookeeper_proxy.v3.ZooKeeperProxy + - name: envoy.http_connection_manager + category: envoy.filters.network + - name: envoy.mongo_proxy + category: envoy.filters.network + - name: envoy.ratelimit + category: envoy.filters.network + - name: envoy.redis_proxy + category: envoy.filters.network + - name: envoy.tcp_proxy + category: envoy.filters.network + - name: envoy.health_checkers.redis + category: envoy.health_checkers + type_urls: + - envoy.extensions.health_checkers.redis.v3.Redis + - name: envoy.health_checkers.thrift + category: envoy.health_checkers + type_urls: + - envoy.extensions.health_checkers.thrift.v3.Thrift + static_resources: + clusters: + - name: xds_cluster + type: STRICT_DNS + connect_timeout: 1s + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + tls_certificate_sds_secret_configs: + - name: xds_certificate + sds_config: + resource_api_version: V3 + path_config_source: + path: "/sds/xds-certificate.json" + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + resource_api_version: V3 + path_config_source: + path: "/sds/xds-trusted-ca.json" + load_assignment: + cluster_name: xds_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: higress + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + dynamic_resources: + lds_config: + api_config_source: + api_type: DELTA_GRPC + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + transport_api_version: V3 + resource_api_version: V3 + cds_config: + api_config_source: + api_type: DELTA_GRPC + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + transport_api_version: V3 + resource_api_version: V3 + admin: + address: + socket_address: + address: 127.0.0.1 + port_value: 15000 + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: "/dev/null" + layered_runtime: + layers: + - name: runtime-0 + rtds_layer: + name: runtime-0 + rtds_config: + api_config_source: + api_type: DELTA_GRPC + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + transport_api_version: V3 + resource_api_version: V3 + last_updated: '2023-02-23T09:05:23.422Z' +- "@type": type.googleapis.com/envoy.admin.v3.ClustersConfigDump + version_info: '2' + static_clusters: + - cluster: + "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster + name: xds_cluster + type: STRICT_DNS + connect_timeout: 1s + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + tls_certificate_sds_secret_configs: + - name: xds_certificate + sds_config: + resource_api_version: V3 + path_config_source: + path: "/sds/xds-certificate.json" + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + resource_api_version: V3 + path_config_source: + path: "/sds/xds-trusted-ca.json" + load_assignment: + cluster_name: xds_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: higress + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + last_updated: '2023-02-23T09:05:23.436Z' + dynamic_active_clusters: + - version_info: 2a0a1698a9d3e05b802047b0cd36b52a070afa49042e1ba267168c5265c7cabf + cluster: + "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster + name: default-backend-rule-0-match-0-www.example.com + type: STATIC + connect_timeout: 5s + dns_lookup_family: V4_ONLY + outlier_detection: {} + common_lb_config: + locality_weighted_lb_config: {} + load_assignment: + cluster_name: default-backend-rule-0-match-0-www.example.com + endpoints: + - locality: {} + lb_endpoints: + - endpoint: + address: + socket_address: + address: 0.0.0.0 + port_value: 3000 + load_balancing_weight: 1 + load_balancing_weight: 1 + last_updated: '2023-02-23T09:05:38.443Z' +- "@type": type.googleapis.com/envoy.admin.v3.ListenersConfigDump + version_info: '2' + dynamic_listeners: + - name: default-higress-http + active_state: + version_info: 42c71fb50c315ee3a32b327da69f8cc0baf420bc84b747e82d9c38e1b0c33eb2 + listener: + "@type": type.googleapis.com/envoy.config.listener.v3.Listener + name: default-higress-http + address: + socket_address: + address: 0.0.0.0 + port_value: 10080 + access_log: + - name: envoy.access_loggers.file + filter: + response_flag_filter: + flags: + - NR + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: "/dev/stdout" + default_filter_chain: + filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: http + rds: + config_source: + api_config_source: + api_type: DELTA_GRPC + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + transport_api_version: V3 + resource_api_version: V3 + route_config_name: default-higress-http + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: "/dev/stdout" + use_remote_address: true + upgrade_configs: + - upgrade_type: websocket + last_updated: '2023-02-23T09:05:38.446Z' +- "@type": type.googleapis.com/envoy.admin.v3.ScopedRoutesConfigDump +- "@type": type.googleapis.com/envoy.admin.v3.RoutesConfigDump + dynamic_route_configs: + - version_info: cb1e51997a9c3aa6f4d920f39fd5bdbd966e9382b7b6bdf42efca8c22c6c3442 + route_config: + "@type": type.googleapis.com/envoy.config.route.v3.RouteConfiguration + name: default-higress-http + virtual_hosts: + - name: default-higress-http + domains: + - "*" + routes: + - match: + prefix: "/" + headers: + - name: ":authority" + string_match: + exact: www.example.com + route: + cluster: default-backend-rule-0-match-0-www.example.com + last_updated: '2023-02-23T09:05:38.448Z' +- "@type": type.googleapis.com/envoy.admin.v3.SecretsConfigDump + dynamic_active_secrets: + - name: xds_certificate + last_updated: '2023-02-23T09:05:23.442Z' + secret: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret + name: xds_certificate + tls_certificate: + certificate_chain: + inline_bytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLekNDQWhPZ0F3SUJBZ0lFTnJRVi9qQU5CZ2txaGtpRzl3MEJBUXNGQURBc01SWXdGQVlEVlFRREV3MWwKYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEVlFRRkV3azFOalE0TXpRek9EVXdIaGNOTWpNd01qRTNNRE0wTVRJNApXaGNOTWpRd01qRTRNRE0wTVRJNFdqQU1NUW93Q0FZRFZRUUREQUVxTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGCkFBT0NBUThBTUlJQkNnS0NBUUVBNmdNSTJSNElEeE5mQ2o1YmZHU1hVUjF4YkVjRjE5VXlhVC9VUEZZcFltM0gKN2c4T3Z6YWRlelFyRkt3dG9PWWFDN0hjam8zVnVHSmhqSDQ1Z3lVbWFzSEg1Q1gzaWFlRlhxQXdVQjRqVTZQSgpBbElCZWlMRVdZVjN1VjMwcGlKK09DWFhrUEQzSFFVb0ZYbnljcHM3OE9PbjZoS0wwNUY0YkJsT2UrMFdIUHdECll2dFQ4TEdpVmcrSkxhR2lxaGgxOXY5endwQUd2akI2Z09kN1BjdkNQNFExUHdkMWdMSnNXVFNweGhDUEVPb2kKV2ZSOG56RERVUHU5aXc2QTJObW1XQ1FxSVNYcDlZUmJMTEdjZnV4VURjcFVYMHpqY0xvcE1sajBnM0RkYVpWRwpzNm9JcW9BSjZ6MFhvdWwrM0ZZdUtJYy8rT1V3VkR1VkI4K0ZRZzlYdlFJREFRQUJvM1V3Y3pBT0JnTlZIUThCCkFmOEVCQU1DQlBBd0hRWURWUjBPQkJZRUZKaUJ3cytVaFRlT2p1L1ZXT29LQWNTSmZBeXVNQjhHQTFVZEl3UVkKTUJhQUZCT3kvOGkxeVMxRWxpN0tNK0gyeXZEM1BJMG1NQ0VHQTFVZEVRUWFNQmlDRmlvdVpXNTJiM2t0WjJGMApaWGRoZVMxemVYTjBaVzB3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUZraHdIakZtQWxqdEpheU54WitodURGCm5UdWd0REZvSTBFT2J0cUhLYnloWU9sdlNFdkhxbFNQSHNRUUhmQnQwbHpOOEtGUTd2YWxTSHRBZStlNzBETHkKaGY3TDQ3eklST3NLcmtmb0tjMjRqaUhNQkVwbCtJdjllU1RWVG9WemxzazVZUGxET2lrMzZpRUY3WDVVZ0RheApsVllZZnpSYzRUb0poODMwT285Wm9pai9LM295dVNXcTVGRzVFWExmeW9tQzZPQ3dxRm5GNzRSM21FTjVheDRlCnppVm5QVDNxVmFZdytzNngwSVhHU282U2M3Q2lUbmMrckFNa3FJNVNsK2p5RHhKTkZBQlIvRllCcTQzK1B1UGkKN0YxOEw0N2l3aVFFYU82NUJzU2hlYmg1Qk1VbytDdzIyM3JsMGRpTldwY3FrdVhtT1BWNDlrWkZkdHpFNytVPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + private_key: + inline_bytes: W3JlZGFjdGVkXQ== + - name: xds_trusted_ca + last_updated: '2023-02-23T09:05:23.447Z' + secret: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret + name: xds_trusted_ca + validation_context: + trusted_ca: + inline_bytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHRENDQWdDZ0F3SUJBZ0lFSWFxd1VUQU5CZ2txaGtpRzl3MEJBUXNGQURBc01SWXdGQVlEVlFRREV3MWwKYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEVlFRRkV3azFOalE0TXpRek9EVXdIaGNOTWpNd01qRTNNRE0wTVRJNApXaGNOTWpRd01qRTRNRE0wTVRJNFdqQXNNUll3RkFZRFZRUURFdzFsYm5admVTMW5ZWFJsZDJGNU1SSXdFQVlEClZRUUZFd2sxTmpRNE16UXpPRFV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRDIKeFMrNkRWY2FvbHFkVVBzTHZwNUtQMEQyV0hrTkVEY0tPeml3bzZNYm9wczFLYWJnNXVYSVl5T21JRWNTTXNKNwpHbVAxMlJjK0J3V1dFWXRrTHVPU3BwQm1lSjN3aDRrUlVRVTRTemRFU1dDcU40RTNpcTJib3FFVm53SkFGQ1ZpCldldGVjZkZsODZFalliQUxxSnRCbGJCbFFQM1ZMZ1hva0VVamJ4QmFobE1wZitUWkVJNFBuam1zUWN5a21LeXIKaDJwdmM3cnZYb29HTlhTM0Q0eFc1VDY3dmxLYi94UlM3c2gwTkJEU0dtTE1jY2pxWFZXazVOR2lBWVB3dXBWSwpTWG02dnZXUFZCdEd1bkZhS0JSRGx4TlJrb0wzRUN6UkNtenoxR2ZYMGJkSm1leElOM2VIUFBRdkd0M0txeUlnCkgrYnc0OXpqdlVUb2dNcXFpTlcvQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQQmdOVkhSTUIKQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJRVHN2L0l0Y2t0UkpZdXlqUGg5c3J3OXp5TkpqQU5CZ2txaGtpRwo5dzBCQVFzRkFBT0NBUUVBd2dvZEsxalhVWFZDVXBTSjE0cEo3S3ZobWZPT1hkaVNISmNSSzlIUzI1c2xwOWN2CkJDSndmWUZmanJ4Rmc5TnV4aVpiM01oVXk5MDBqenBPdk1QWStEeUxFWFVxTGd5ZlBMUzYveVliem8yZHdwdzMKOCtrTXlsQUFlZmtaSW9oT0VhYSsvNFFBVVVGZVp1a1B6bmF6RzZIWnZKQkNxWVdRNXBaSSt3WTI1dzhEU0VOMgpkOCswVkpzWU5IdUk4aXhneGZhUkRycW5LRHBMUGJ3Z3VaRDl6ZkV3dVFaNG1oeEd0Vk1wR0NLSndscWFhdXJ0CkF5aGhzOXBHNERndkpSY1BLeFY4bndRdzZtSm55dkIxcExxTW1aQTVqZWhxbFNvUGVpWUlBMk1neU83cTVPYmMKL040bzBNTVdvZ1piRWR6aTBnTXJRT2lpNE41Q0ZlakVrYStIMmc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: higress +- "@type": type.googleapis.com/envoy.admin.v3.EndpointsConfigDump + staticEndpointConfigs: + - endpointConfig: + "@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment + clusterName: xds_cluster + endpoints: + - locality: {} + lbEndpoints: + - endpoint: + address: + socketAddress: + address: 0.0.0.0 + portValue: 18000 + healthCheckConfig: {} + hostname: higress + healthStatus: HEALTHY + metadata: {} + loadBalancingWeight: 1 + policy: + overprovisioningFactor: 140 diff --git a/pkg/cmd/hgctl/testdata/config/output/out.bootstrap.json b/pkg/cmd/hgctl/testdata/config/output/out.bootstrap.json new file mode 100644 index 0000000000..930a77e923 --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.bootstrap.json @@ -0,0 +1,1966 @@ +{ + "@type": "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump", + "bootstrap": { + "node": { + "user_agent_name": "envoy", + "user_agent_build_version": { + "version": { + "major_number": 1, + "minor_number": 26 + }, + "metadata": { + "revision.status": "Clean", + "revision.sha": "14111e3c62d3d38b0c921cb7011fd0a94e880aed", + "ssl.version": "BoringSSL", + "build.label": "dev", + "build.type": "RELEASE" + } + }, + "extensions": [{ + "name": "envoy.filters.connection_pools.tcp.generic", + "category": "envoy.upstreams", + "type_urls": [ + "envoy.extensions.upstreams.tcp.generic.v3.GenericConnectionPoolProto" + ] + }, + { + "name": "envoy.rate_limit_descriptors.expr", + "category": "envoy.rate_limit_descriptors", + "type_urls": [ + "envoy.extensions.rate_limit_descriptors.expr.v3.Descriptor" + ] + }, + { + "name": "envoy.matching.inputs.destination_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_port", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput" + ] + }, + { + "name": "envoy.matching.inputs.direct_source_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.dns_san", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput" + ] + }, + { + "name": "envoy.matching.inputs.request_headers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestHeaderMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.request_trailers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestTrailerMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.response_headers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseHeaderMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.response_trailers", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseTrailerMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.server_name", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ServerNameInput" + ] + }, + { + "name": "envoy.matching.inputs.source_ip", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.source_port", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourcePortInput" + ] + }, + { + "name": "envoy.matching.inputs.source_type", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput" + ] + }, + { + "name": "envoy.matching.inputs.status_code_class_input", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseStatusCodeClassMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.status_code_input", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpResponseStatusCodeMatchInput" + ] + }, + { + "name": "envoy.matching.inputs.subject", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput" + ] + }, + { + "name": "envoy.matching.inputs.uri_san", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput" + ] + }, + { + "name": "query_params", + "category": "envoy.matching.http.input", + "type_urls": [ + "envoy.type.matcher.v3.HttpRequestQueryParamMatchInput" + ] + }, + { + "name": "envoy.tls.cert_validator.default", + "category": "envoy.tls.cert_validator" + }, + { + "name": "envoy.tls.cert_validator.spiffe", + "category": "envoy.tls.cert_validator" + }, + { + "name": "envoy.path.match.uri_template.uri_template_matcher", + "category": "envoy.path.match", + "type_urls": [ + "envoy.extensions.path.match.uri_template.v3.UriTemplateMatchConfig" + ] + }, + { + "name": "envoy.http.original_ip_detection.custom_header", + "category": "envoy.http.original_ip_detection", + "type_urls": [ + "envoy.extensions.http.original_ip_detection.custom_header.v3.CustomHeaderConfig" + ] + }, + { + "name": "envoy.http.original_ip_detection.xff", + "category": "envoy.http.original_ip_detection", + "type_urls": [ + "envoy.extensions.http.original_ip_detection.xff.v3.XffConfig" + ] + }, + { + "name": "envoy.buffer", + "category": "envoy.filters.http.upstream" + }, + { + "name": "envoy.filters.http.admission_control", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.admission_control.v3.AdmissionControl" + ] + }, + { + "name": "envoy.filters.http.buffer", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.buffer.v3.Buffer", + "envoy.extensions.filters.http.buffer.v3.BufferPerRoute" + ] + }, + { + "name": "envoy.filters.http.upstream_codec", + "category": "envoy.filters.http.upstream", + "type_urls": [ + "envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec" + ] + }, + { + "name": "envoy.route.early_data_policy.default", + "category": "envoy.route.early_data_policy", + "type_urls": [ + "envoy.extensions.early_data.v3.DefaultEarlyDataPolicy" + ] + }, + { + "name": "envoy.compression.brotli.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.brotli.compressor.v3.Brotli" + ] + }, + { + "name": "envoy.compression.gzip.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.gzip.compressor.v3.Gzip" + ] + }, + { + "name": "envoy.compression.zstd.compressor", + "category": "envoy.compression.compressor", + "type_urls": [ + "envoy.extensions.compression.zstd.compressor.v3.Zstd" + ] + }, + { + "name": "envoy.compression.brotli.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.brotli.decompressor.v3.Brotli" + ] + }, + { + "name": "envoy.compression.gzip.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.gzip.decompressor.v3.Gzip" + ] + }, + { + "name": "envoy.compression.zstd.decompressor", + "category": "envoy.compression.decompressor", + "type_urls": [ + "envoy.extensions.compression.zstd.decompressor.v3.Zstd" + ] + }, + { + "name": "envoy.wasm.runtime.null", + "category": "envoy.wasm.runtime" + }, + { + "name": "envoy.wasm.runtime.v8", + "category": "envoy.wasm.runtime" + }, + { + "name": "envoy.dog_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.graphite_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.metrics_service", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.dog_statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.DogStatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.graphite_statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.extensions.stat_sinks.graphite_statsd.v3.GraphiteStatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.hystrix", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.HystrixSink" + ] + }, + { + "name": "envoy.stat_sinks.metrics_service", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.MetricsServiceConfig" + ] + }, + { + "name": "envoy.stat_sinks.statsd", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.config.metrics.v3.StatsdSink" + ] + }, + { + "name": "envoy.stat_sinks.wasm", + "category": "envoy.stats_sinks", + "type_urls": [ + "envoy.extensions.stat_sinks.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.path.rewrite.uri_template.uri_template_rewriter", + "category": "envoy.path.rewrite", + "type_urls": [ + "envoy.extensions.path.rewrite.uri_template.v3.UriTemplateRewriteConfig" + ] + }, + { + "name": "envoy.extensions.http.custom_response.local_response_policy", + "category": "envoy.http.custom_response", + "type_urls": [ + "envoy.extensions.http.custom_response.local_response_policy.v3.LocalResponsePolicy" + ] + }, + { + "name": "envoy.extensions.http.custom_response.redirect_policy", + "category": "envoy.http.custom_response", + "type_urls": [ + "envoy.extensions.http.custom_response.redirect_policy.v3.RedirectPolicy" + ] + }, + { + "name": "envoy.matching.actions.format_string", + "category": "envoy.matching.action", + "type_urls": [ + "envoy.config.core.v3.SubstitutionFormatString" + ] + }, + { + "name": "filter-chain-name", + "category": "envoy.matching.action", + "type_urls": [ + "google.protobuf.StringValue" + ] + }, + { + "name": "envoy.quic.deterministic_connection_id_generator", + "category": "envoy.quic.connection_id_generator", + "type_urls": [ + "envoy.extensions.quic.connection_id_generator.v3.DeterministicConnectionIdGeneratorConfig" + ] + }, + { + "name": "envoy.network.dns_resolver.cares", + "category": "envoy.network.dns_resolver", + "type_urls": [ + "envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig" + ] + }, + { + "name": "envoy.network.dns_resolver.getaddrinfo", + "category": "envoy.network.dns_resolver", + "type_urls": [ + "envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig" + ] + }, + { + "name": "envoy.bootstrap.internal_listener", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.bootstrap.internal_listener.v3.InternalListener" + ] + }, + { + "name": "envoy.bootstrap.wasm", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.wasm.v3.WasmService" + ] + }, + { + "name": "envoy.extensions.network.socket_interface.default_socket_interface", + "category": "envoy.bootstrap", + "type_urls": [ + "envoy.extensions.network.socket_interface.v3.DefaultSocketInterface" + ] + }, + { + "name": "envoy.filters.listener.http_inspector", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.http_inspector.v3.HttpInspector" + ] + }, + { + "name": "envoy.filters.listener.original_dst", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.original_dst.v3.OriginalDst" + ] + }, + { + "name": "envoy.filters.listener.original_src", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.original_src.v3.OriginalSrc" + ] + }, + { + "name": "envoy.filters.listener.proxy_protocol", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol" + ] + }, + { + "name": "envoy.filters.listener.tls_inspector", + "category": "envoy.filters.listener", + "type_urls": [ + "envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + ] + }, + { + "name": "envoy.listener.http_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.original_dst", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.original_src", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.proxy_protocol", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.tls_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.matching.common_inputs.environment_variable", + "category": "envoy.matching.common_inputs", + "type_urls": [ + "envoy.extensions.matching.common_inputs.environment_variable.v3.Config" + ] + }, + { + "name": "envoy.matching.matchers.consistent_hashing", + "category": "envoy.matching.input_matchers", + "type_urls": [ + "envoy.extensions.matching.input_matchers.consistent_hashing.v3.ConsistentHashing" + ] + }, + { + "name": "envoy.matching.matchers.ip", + "category": "envoy.matching.input_matchers", + "type_urls": [ + "envoy.extensions.matching.input_matchers.ip.v3.Ip" + ] + }, + { + "name": "envoy.grpc_credentials.aws_iam", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.grpc_credentials.default", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.grpc_credentials.file_based_metadata", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.request_id.uuid", + "category": "envoy.request_id", + "type_urls": [ + "envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig" + ] + }, + { + "name": "envoy.load_balancing_policies.least_request", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest" + ] + }, + { + "name": "envoy.load_balancing_policies.maglev", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.maglev.v3.Maglev" + ] + }, + { + "name": "envoy.load_balancing_policies.random", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.random.v3.Random" + ] + }, + { + "name": "envoy.load_balancing_policies.ring_hash", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash" + ] + }, + { + "name": "envoy.load_balancing_policies.round_robin", + "category": "envoy.load_balancing_policies", + "type_urls": [ + "envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin" + ] + }, + { + "name": "envoy.ip", + "category": "envoy.resolvers" + }, + { + "name": "envoy.bandwidth_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.buffer", + "category": "envoy.filters.http" + }, + { + "name": "envoy.cors", + "category": "envoy.filters.http" + }, + { + "name": "envoy.csrf", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ext_authz", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ext_proc", + "category": "envoy.filters.http" + }, + { + "name": "envoy.fault", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.adaptive_concurrency", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.adaptive_concurrency.v3.AdaptiveConcurrency" + ] + }, + { + "name": "envoy.filters.http.admission_control", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.admission_control.v3.AdmissionControl" + ] + }, + { + "name": "envoy.filters.http.alternate_protocols_cache", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.aws_lambda", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.aws_lambda.v3.Config", + "envoy.extensions.filters.http.aws_lambda.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.aws_request_signing", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning" + ] + }, + { + "name": "envoy.filters.http.bandwidth_limit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.bandwidth_limit.v3.BandwidthLimit" + ] + }, + { + "name": "envoy.filters.http.buffer", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.buffer.v3.Buffer", + "envoy.extensions.filters.http.buffer.v3.BufferPerRoute" + ] + }, + { + "name": "envoy.filters.http.cache", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cache.v3.CacheConfig" + ] + }, + { + "name": "envoy.filters.http.cdn_loop", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cdn_loop.v3.CdnLoopConfig" + ] + }, + { + "name": "envoy.filters.http.composite", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.composite.v3.Composite" + ] + }, + { + "name": "envoy.filters.http.compressor", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.compressor.v3.Compressor", + "envoy.extensions.filters.http.compressor.v3.CompressorPerRoute" + ] + }, + { + "name": "envoy.filters.http.connect_grpc_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.connect_grpc_bridge.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.cors", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.cors.v3.Cors", + "envoy.extensions.filters.http.cors.v3.CorsPolicy" + ] + }, + { + "name": "envoy.filters.http.csrf", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.csrf.v3.CsrfPolicy" + ] + }, + { + "name": "envoy.filters.http.custom_response", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.custom_response.v3.CustomResponse" + ] + }, + { + "name": "envoy.filters.http.decompressor", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.decompressor.v3.Decompressor" + ] + }, + { + "name": "envoy.filters.http.dynamic_forward_proxy", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig", + "envoy.extensions.filters.http.dynamic_forward_proxy.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.ext_authz", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ext_authz.v3.ExtAuthz", + "envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute" + ] + }, + { + "name": "envoy.filters.http.ext_proc", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute", + "envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor" + ] + }, + { + "name": "envoy.filters.http.fault", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.fault.v3.HTTPFault" + ] + }, + { + "name": "envoy.filters.http.file_system_buffer", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.file_system_buffer.v3.FileSystemBufferFilterConfig" + ] + }, + { + "name": "envoy.filters.http.gcp_authn", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig" + ] + }, + { + "name": "envoy.filters.http.grpc_http1_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" + ] + }, + { + "name": "envoy.filters.http.grpc_http1_reverse_bridge", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfig", + "envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfigPerRoute" + ] + }, + { + "name": "envoy.filters.http.grpc_json_transcoder", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder" + ] + }, + { + "name": "envoy.filters.http.grpc_stats", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_stats.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.http.grpc_web", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.grpc_web.v3.GrpcWeb" + ] + }, + { + "name": "envoy.filters.http.header_to_metadata", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.header_to_metadata.v3.Config" + ] + }, + { + "name": "envoy.filters.http.health_check", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.health_check.v3.HealthCheck" + ] + }, + { + "name": "envoy.filters.http.ip_tagging", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ip_tagging.v3.IPTagging" + ] + }, + { + "name": "envoy.filters.http.jwt_authn", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication", + "envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.local_ratelimit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit" + ] + }, + { + "name": "envoy.filters.http.lua", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.lua.v3.Lua", + "envoy.extensions.filters.http.lua.v3.LuaPerRoute" + ] + }, + { + "name": "envoy.filters.http.match_delegate", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.common.matching.v3.ExtensionWithMatcher" + ] + }, + { + "name": "envoy.filters.http.oauth2", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.oauth2.v3.OAuth2" + ] + }, + { + "name": "envoy.filters.http.on_demand", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.on_demand.v3.OnDemand", + "envoy.extensions.filters.http.on_demand.v3.PerRouteConfig" + ] + }, + { + "name": "envoy.filters.http.original_src", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.original_src.v3.OriginalSrc" + ] + }, + { + "name": "envoy.filters.http.rate_limit_quota", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaFilterConfig", + "envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaOverride" + ] + }, + { + "name": "envoy.filters.http.ratelimit", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.ratelimit.v3.RateLimit", + "envoy.extensions.filters.http.ratelimit.v3.RateLimitPerRoute" + ] + }, + { + "name": "envoy.filters.http.rbac", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.rbac.v3.RBAC", + "envoy.extensions.filters.http.rbac.v3.RBACPerRoute" + ] + }, + { + "name": "envoy.filters.http.router", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.router.v3.Router" + ] + }, + { + "name": "envoy.filters.http.set_metadata", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.set_metadata.v3.Config" + ] + }, + { + "name": "envoy.filters.http.stateful_session", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.stateful_session.v3.StatefulSession", + "envoy.extensions.filters.http.stateful_session.v3.StatefulSessionPerRoute" + ] + }, + { + "name": "envoy.filters.http.tap", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.tap.v3.Tap" + ] + }, + { + "name": "envoy.filters.http.wasm", + "category": "envoy.filters.http", + "type_urls": [ + "envoy.extensions.filters.http.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.grpc_http1_bridge", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_json_transcoder", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_web", + "category": "envoy.filters.http" + }, + { + "name": "envoy.health_check", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ip_tagging", + "category": "envoy.filters.http" + }, + { + "name": "envoy.local_rate_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.lua", + "category": "envoy.filters.http" + }, + { + "name": "envoy.rate_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.router", + "category": "envoy.filters.http" + }, + { + "name": "envoy.access_loggers.file", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.file.v3.FileAccessLog" + ] + }, + { + "name": "envoy.access_loggers.http_grpc", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.open_telemetry", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.open_telemetry.v3.OpenTelemetryAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.stderr", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.stream.v3.StderrAccessLog" + ] + }, + { + "name": "envoy.access_loggers.stdout", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.stream.v3.StdoutAccessLog" + ] + }, + { + "name": "envoy.access_loggers.tcp_grpc", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.grpc.v3.TcpGrpcAccessLogConfig" + ] + }, + { + "name": "envoy.access_loggers.wasm", + "category": "envoy.access_loggers", + "type_urls": [ + "envoy.extensions.access_loggers.wasm.v3.WasmAccessLog" + ] + }, + { + "name": "envoy.file_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.http_grpc_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.open_telemetry_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.stderr_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.stdout_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.tcp_grpc_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.wasm_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.config.validators.minimum_clusters", + "category": "envoy.config.validators" + }, + { + "name": "envoy.config.validators.minimum_clusters_validator", + "category": "envoy.config.validators", + "type_urls": [ + "envoy.extensions.config.validators.minimum_clusters.v3.MinimumClustersValidator" + ] + }, + { + "name": "envoy.http.header_validators.envoy_default", + "category": "envoy.http.header_validators", + "type_urls": [ + "envoy.extensions.http.header_validators.envoy_default.v3.HeaderValidatorConfig" + ] + }, + { + "name": "dubbo.hessian2", + "category": "envoy.dubbo_proxy.serializers" + }, + { + "name": "quic.http_server_connection.default", + "category": "quic.http_server_connection" + }, + { + "name": "envoy.transport_sockets.alts", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.alts.v3.Alts" + ] + }, + { + "name": "envoy.transport_sockets.quic", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.quic.v3.QuicDownstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.raw_buffer", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer" + ] + }, + { + "name": "envoy.transport_sockets.starttls", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.starttls.v3.StartTlsConfig" + ] + }, + { + "name": "envoy.transport_sockets.tap", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tap.v3.Tap" + ] + }, + { + "name": "envoy.transport_sockets.tcp_stats", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tcp_stats.v3.Config" + ] + }, + { + "name": "envoy.transport_sockets.tls", + "category": "envoy.transport_sockets.downstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext" + ] + }, + { + "name": "raw_buffer", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "starttls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "tls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.rbac.matchers.upstream_ip_port", + "category": "envoy.rbac.matchers", + "type_urls": [ + "envoy.extensions.rbac.matchers.upstream_ip_port.v3.UpstreamIpPortMatcher" + ] + }, + { + "name": "envoy.key_value.file_based", + "category": "envoy.common.key_value", + "type_urls": [ + "envoy.extensions.key_value.file_based.v3.FileBasedKeyValueStoreConfig" + ] + }, + { + "name": "envoy.matching.inputs.application_protocol", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput" + ] + }, + { + "name": "envoy.matching.inputs.destination_port", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput" + ] + }, + { + "name": "envoy.matching.inputs.direct_source_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.dns_san", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput" + ] + }, + { + "name": "envoy.matching.inputs.server_name", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.ServerNameInput" + ] + }, + { + "name": "envoy.matching.inputs.source_ip", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceIPInput" + ] + }, + { + "name": "envoy.matching.inputs.source_port", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourcePortInput" + ] + }, + { + "name": "envoy.matching.inputs.source_type", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput" + ] + }, + { + "name": "envoy.matching.inputs.subject", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput" + ] + }, + { + "name": "envoy.matching.inputs.transport_protocol", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput" + ] + }, + { + "name": "envoy.matching.inputs.uri_san", + "category": "envoy.matching.network.input", + "type_urls": [ + "envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput" + ] + }, + { + "name": "dubbo", + "category": "envoy.dubbo_proxy.protocols" + }, + { + "name": "envoy.watchdog.abort_action", + "category": "envoy.guarddog_actions", + "type_urls": [ + "envoy.watchdog.v3.AbortActionConfig" + ] + }, + { + "name": "envoy.watchdog.profile_action", + "category": "envoy.guarddog_actions", + "type_urls": [ + "envoy.extensions.watchdog.profile_action.v3.ProfileActionConfig" + ] + }, + { + "name": "envoy.quic.crypto_stream.server.quiche", + "category": "envoy.quic.server.crypto_stream", + "type_urls": [ + "envoy.extensions.quic.crypto_stream.v3.CryptoServerStreamConfig" + ] + }, + { + "name": "envoy.regex_engines.google_re2", + "category": "envoy.regex_engines", + "type_urls": [ + "envoy.extensions.regex_engines.v3.GoogleRE2" + ] + }, + { + "name": "envoy.http.stateful_session.cookie", + "category": "envoy.http.stateful_session", + "type_urls": [ + "envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState" + ] + }, + { + "name": "envoy.http.stateful_session.header", + "category": "envoy.http.stateful_session", + "type_urls": [ + "envoy.extensions.http.stateful_session.header.v3.HeaderBasedSessionState" + ] + }, + { + "name": "envoy.matching.custom_matchers.trie_matcher", + "category": "envoy.matching.network.custom_matchers", + "type_urls": [ + "xds.type.matcher.v3.IPMatcher" + ] + }, + { + "name": "envoy.udp_packet_writer.default", + "category": "envoy.udp_packet_writer", + "type_urls": [ + "envoy.extensions.udp_packet_writer.v3.UdpDefaultWriterFactory" + ] + }, + { + "name": "envoy.udp_packet_writer.gso", + "category": "envoy.udp_packet_writer", + "type_urls": [ + "envoy.extensions.udp_packet_writer.v3.UdpGsoBatchWriterFactory" + ] + }, + { + "name": "envoy.quic.proof_source.filter_chain", + "category": "envoy.quic.proof_source", + "type_urls": [ + "envoy.extensions.quic.proof_source.v3.ProofSourceConfig" + ] + }, + { + "name": "envoy.resource_monitors.fixed_heap", + "category": "envoy.resource_monitors", + "type_urls": [ + "envoy.extensions.resource_monitors.fixed_heap.v3.FixedHeapConfig" + ] + }, + { + "name": "envoy.resource_monitors.injected_resource", + "category": "envoy.resource_monitors", + "type_urls": [ + "envoy.extensions.resource_monitors.injected_resource.v3.InjectedResourceConfig" + ] + }, + { + "name": "envoy.http.stateful_header_formatters.preserve_case", + "category": "envoy.http.stateful_header_formatters", + "type_urls": [ + "envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig" + ] + }, + { + "name": "preserve_case", + "category": "envoy.http.stateful_header_formatters" + }, + { + "name": "envoy.filters.thrift.header_to_metadata", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.header_to_metadata.v3.HeaderToMetadata" + ] + }, + { + "name": "envoy.filters.thrift.payload_to_metadata", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.payload_to_metadata.v3.PayloadToMetadata" + ] + }, + { + "name": "envoy.filters.thrift.rate_limit", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.filters.ratelimit.v3.RateLimit" + ] + }, + { + "name": "envoy.filters.thrift.router", + "category": "envoy.thrift_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.router.v3.Router" + ] + }, + { + "name": "envoy.tracers.datadog", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.DatadogConfig" + ] + }, + { + "name": "envoy.tracers.dynamic_ot", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.DynamicOtConfig" + ] + }, + { + "name": "envoy.tracers.opencensus", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.OpenCensusConfig" + ] + }, + { + "name": "envoy.tracers.opentelemetry", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.OpenTelemetryConfig" + ] + }, + { + "name": "envoy.tracers.skywalking", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.SkyWalkingConfig" + ] + }, + { + "name": "envoy.tracers.xray", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.XRayConfig" + ] + }, + { + "name": "envoy.tracers.zipkin", + "category": "envoy.tracers", + "type_urls": [ + "envoy.config.trace.v3.ZipkinConfig" + ] + }, + { + "name": "envoy.zipkin", + "category": "envoy.tracers" + }, + { + "name": "envoy.retry_priorities.previous_priorities", + "category": "envoy.retry_priorities", + "type_urls": [ + "envoy.extensions.retry.priority.previous_priorities.v3.PreviousPrioritiesConfig" + ] + }, + { + "name": "envoy.http.early_header_mutation.header_mutation", + "category": "envoy.http.early_header_mutation", + "type_urls": [ + "envoy.extensions.http.early_header_mutation.header_mutation.v3.HeaderMutation" + ] + }, + { + "name": "envoy.connection_handler.default", + "category": "envoy.connection_handler" + }, + { + "name": "envoy.transport_sockets.alts", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.alts.v3.Alts" + ] + }, + { + "name": "envoy.transport_sockets.http_11_proxy", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.http_11_proxy.v3.Http11ProxyUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.internal_upstream", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.internal_upstream.v3.InternalUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.quic", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.quic.v3.QuicUpstreamTransport" + ] + }, + { + "name": "envoy.transport_sockets.raw_buffer", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer" + ] + }, + { + "name": "envoy.transport_sockets.starttls", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.starttls.v3.UpstreamStartTlsConfig" + ] + }, + { + "name": "envoy.transport_sockets.tap", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tap.v3.Tap" + ] + }, + { + "name": "envoy.transport_sockets.tcp_stats", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tcp_stats.v3.Config" + ] + }, + { + "name": "envoy.transport_sockets.tls", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext" + ] + }, + { + "name": "envoy.transport_sockets.upstream_proxy_protocol", + "category": "envoy.transport_sockets.upstream", + "type_urls": [ + "envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport" + ] + }, + { + "name": "raw_buffer", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "starttls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "tls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "auto", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "framed", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "header", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "unframed", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "envoy.cluster.eds", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.logical_dns", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.original_dst", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.static", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.strict_dns", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.aggregate", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.dynamic_forward_proxy", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.redis", + "category": "envoy.clusters" + }, + { + "name": "envoy.access_loggers.extension_filters.cel", + "category": "envoy.access_loggers.extension_filters", + "type_urls": [ + "envoy.extensions.access_loggers.filters.cel.v3.ExpressionFilter" + ] + }, + { + "name": "auto", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "binary", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "binary/non-strict", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "compact", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "twitter", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "category": "envoy.upstream_options", + "type_urls": [ + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + ] + }, + { + "name": "envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions", + "category": "envoy.upstream_options", + "type_urls": [ + "envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions" + ] + }, + { + "name": "envoy.upstreams.http.http_protocol_options", + "category": "envoy.upstream_options" + }, + { + "name": "envoy.upstreams.tcp.tcp_protocol_options", + "category": "envoy.upstream_options" + }, + { + "name": "envoy.listener_manager_impl.default", + "category": "envoy.listener_manager_impl", + "type_urls": [ + "envoy.config.listener.v3.ListenerManager" + ] + }, + { + "name": "default", + "category": "network.connection.client" + }, + { + "name": "envoy_internal", + "category": "network.connection.client" + }, + { + "name": "envoy.filters.udp.dns_filter", + "category": "envoy.filters.udp_listener", + "type_urls": [ + "envoy.extensions.filters.udp.dns_filter.v3.DnsFilterConfig" + ] + }, + { + "name": "envoy.filters.udp_listener.udp_proxy", + "category": "envoy.filters.udp_listener", + "type_urls": [ + "envoy.extensions.filters.udp.udp_proxy.v3.UdpProxyConfig" + ] + }, + { + "name": "envoy.extensions.http.cache.file_system_http_cache", + "category": "envoy.http.cache", + "type_urls": [ + "envoy.extensions.http.cache.file_system_http_cache.v3.FileSystemHttpCacheConfig" + ] + }, + { + "name": "envoy.extensions.http.cache.simple", + "category": "envoy.http.cache", + "type_urls": [ + "envoy.extensions.http.cache.simple_http_cache.v3.SimpleHttpCacheConfig" + ] + }, + { + "name": "envoy.retry_host_predicates.omit_canary_hosts", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.omit_canary_hosts.v3.OmitCanaryHostsPredicate" + ] + }, + { + "name": "envoy.retry_host_predicates.omit_host_metadata", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.omit_host_metadata.v3.OmitHostMetadataConfig" + ] + }, + { + "name": "envoy.retry_host_predicates.previous_hosts", + "category": "envoy.retry_host_predicates", + "type_urls": [ + "envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate" + ] + }, + { + "name": "envoy.formatter.metadata", + "category": "envoy.formatter", + "type_urls": [ + "envoy.extensions.formatter.metadata.v3.Metadata" + ] + }, + { + "name": "envoy.formatter.req_without_query", + "category": "envoy.formatter", + "type_urls": [ + "envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery" + ] + }, + { + "name": "envoy.internal_redirect_predicates.allow_listed_routes", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.allow_listed_routes.v3.AllowListedRoutesConfig" + ] + }, + { + "name": "envoy.internal_redirect_predicates.previous_routes", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.previous_routes.v3.PreviousRoutesConfig" + ] + }, + { + "name": "envoy.internal_redirect_predicates.safe_cross_scheme", + "category": "envoy.internal_redirect_predicates", + "type_urls": [ + "envoy.extensions.internal_redirect.safe_cross_scheme.v3.SafeCrossSchemeConfig" + ] + }, + { + "name": "envoy.matching.custom_matchers.trie_matcher", + "category": "envoy.matching.http.custom_matchers", + "type_urls": [ + "xds.type.matcher.v3.IPMatcher" + ] + }, + { + "name": "envoy.filters.dubbo.router", + "category": "envoy.dubbo_proxy.filters", + "type_urls": [ + "envoy.extensions.filters.network.dubbo_proxy.router.v3.Router" + ] + }, + { + "name": "envoy.echo", + "category": "envoy.filters.network" + }, + { + "name": "envoy.ext_authz", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.connection_limit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit" + ] + }, + { + "name": "envoy.filters.network.direct_response", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.direct_response.v3.Config" + ] + }, + { + "name": "envoy.filters.network.dubbo_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.dubbo_proxy.v3.DubboProxy" + ] + }, + { + "name": "envoy.filters.network.echo", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.echo.v3.Echo" + ] + }, + { + "name": "envoy.filters.network.ext_authz", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + ] + }, + { + "name": "envoy.filters.network.http_connection_manager", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager" + ] + }, + { + "name": "envoy.filters.network.local_ratelimit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.local_ratelimit.v3.LocalRateLimit" + ] + }, + { + "name": "envoy.filters.network.mongo_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy" + ] + }, + { + "name": "envoy.filters.network.ratelimit", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.ratelimit.v3.RateLimit" + ] + }, + { + "name": "envoy.filters.network.rbac", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.rbac.v3.RBAC" + ] + }, + { + "name": "envoy.filters.network.redis_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.redis_proxy.v3.RedisProxy" + ] + }, + { + "name": "envoy.filters.network.sni_cluster", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + ] + }, + { + "name": "envoy.filters.network.sni_dynamic_forward_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.sni_dynamic_forward_proxy.v3.FilterConfig" + ] + }, + { + "name": "envoy.filters.network.tcp_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy" + ] + }, + { + "name": "envoy.filters.network.thrift_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.thrift_proxy.v3.ThriftProxy" + ] + }, + { + "name": "envoy.filters.network.wasm", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.wasm.v3.Wasm" + ] + }, + { + "name": "envoy.filters.network.zookeeper_proxy", + "category": "envoy.filters.network", + "type_urls": [ + "envoy.extensions.filters.network.zookeeper_proxy.v3.ZooKeeperProxy" + ] + }, + { + "name": "envoy.http_connection_manager", + "category": "envoy.filters.network" + }, + { + "name": "envoy.mongo_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.ratelimit", + "category": "envoy.filters.network" + }, + { + "name": "envoy.redis_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.tcp_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.health_checkers.redis", + "category": "envoy.health_checkers", + "type_urls": [ + "envoy.extensions.health_checkers.redis.v3.Redis" + ] + }, + { + "name": "envoy.health_checkers.thrift", + "category": "envoy.health_checkers", + "type_urls": [ + "envoy.extensions.health_checkers.thrift.v3.Thrift" + ] + } + ] + }, + "static_resources": { + "clusters": [{ + "name": "xds_cluster", + "type": "STRICT_DNS", + "connect_timeout": "1s", + "transport_socket": { + "name": "envoy.transport_sockets.tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": { + "tls_maximum_protocol_version": "TLSv1_3" + }, + "tls_certificate_sds_secret_configs": [{ + "name": "xds_certificate", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-certificate.json" + } + } + }], + "validation_context_sds_secret_config": { + "name": "xds_trusted_ca", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-trusted-ca.json" + } + } + } + } + } + }, + "load_assignment": { + "cluster_name": "xds_cluster", + "endpoints": [{ + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "higress", + "port_value": 18000 + } + } + } + }] + }] + }, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + } + }] + }, + "dynamic_resources": { + "lds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + }, + "cds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + } + }, + "admin": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 15000 + } + }, + "access_log": [{ + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + }] + }, + "layered_runtime": { + "layers": [{ + "name": "runtime-0", + "rtds_layer": { + "name": "runtime-0", + "rtds_config": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + } + } + }] + } + }, + "last_updated": "2023-02-23T09:05:23.422Z" +} diff --git a/pkg/cmd/hgctl/testdata/config/output/out.bootstrap.yaml b/pkg/cmd/hgctl/testdata/config/output/out.bootstrap.yaml new file mode 100644 index 0000000000..a5e05b4848 --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.bootstrap.yaml @@ -0,0 +1,1121 @@ +--- +"@type": type.googleapis.com/envoy.admin.v3.BootstrapConfigDump +bootstrap: + node: + user_agent_name: envoy + user_agent_build_version: + version: + major_number: 1 + minor_number: 26 + metadata: + revision.status: Clean + revision.sha: 14111e3c62d3d38b0c921cb7011fd0a94e880aed + ssl.version: BoringSSL + build.label: dev + build.type: RELEASE + extensions: + - name: envoy.filters.connection_pools.tcp.generic + category: envoy.upstreams + type_urls: + - envoy.extensions.upstreams.tcp.generic.v3.GenericConnectionPoolProto + - name: envoy.rate_limit_descriptors.expr + category: envoy.rate_limit_descriptors + type_urls: + - envoy.extensions.rate_limit_descriptors.expr.v3.Descriptor + - name: envoy.matching.inputs.destination_ip + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput + - name: envoy.matching.inputs.destination_port + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + - name: envoy.matching.inputs.direct_source_ip + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput + - name: envoy.matching.inputs.dns_san + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput + - name: envoy.matching.inputs.request_headers + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpRequestHeaderMatchInput + - name: envoy.matching.inputs.request_trailers + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpRequestTrailerMatchInput + - name: envoy.matching.inputs.response_headers + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpResponseHeaderMatchInput + - name: envoy.matching.inputs.response_trailers + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpResponseTrailerMatchInput + - name: envoy.matching.inputs.server_name + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.ServerNameInput + - name: envoy.matching.inputs.source_ip + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourceIPInput + - name: envoy.matching.inputs.source_port + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourcePortInput + - name: envoy.matching.inputs.source_type + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput + - name: envoy.matching.inputs.status_code_class_input + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpResponseStatusCodeClassMatchInput + - name: envoy.matching.inputs.status_code_input + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpResponseStatusCodeMatchInput + - name: envoy.matching.inputs.subject + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput + - name: envoy.matching.inputs.uri_san + category: envoy.matching.http.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput + - name: query_params + category: envoy.matching.http.input + type_urls: + - envoy.type.matcher.v3.HttpRequestQueryParamMatchInput + - name: envoy.tls.cert_validator.default + category: envoy.tls.cert_validator + - name: envoy.tls.cert_validator.spiffe + category: envoy.tls.cert_validator + - name: envoy.path.match.uri_template.uri_template_matcher + category: envoy.path.match + type_urls: + - envoy.extensions.path.match.uri_template.v3.UriTemplateMatchConfig + - name: envoy.http.original_ip_detection.custom_header + category: envoy.http.original_ip_detection + type_urls: + - envoy.extensions.http.original_ip_detection.custom_header.v3.CustomHeaderConfig + - name: envoy.http.original_ip_detection.xff + category: envoy.http.original_ip_detection + type_urls: + - envoy.extensions.http.original_ip_detection.xff.v3.XffConfig + - name: envoy.buffer + category: envoy.filters.http.upstream + - name: envoy.filters.http.admission_control + category: envoy.filters.http.upstream + type_urls: + - envoy.extensions.filters.http.admission_control.v3.AdmissionControl + - name: envoy.filters.http.buffer + category: envoy.filters.http.upstream + type_urls: + - envoy.extensions.filters.http.buffer.v3.Buffer + - envoy.extensions.filters.http.buffer.v3.BufferPerRoute + - name: envoy.filters.http.upstream_codec + category: envoy.filters.http.upstream + type_urls: + - envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + - name: envoy.route.early_data_policy.default + category: envoy.route.early_data_policy + type_urls: + - envoy.extensions.early_data.v3.DefaultEarlyDataPolicy + - name: envoy.compression.brotli.compressor + category: envoy.compression.compressor + type_urls: + - envoy.extensions.compression.brotli.compressor.v3.Brotli + - name: envoy.compression.gzip.compressor + category: envoy.compression.compressor + type_urls: + - envoy.extensions.compression.gzip.compressor.v3.Gzip + - name: envoy.compression.zstd.compressor + category: envoy.compression.compressor + type_urls: + - envoy.extensions.compression.zstd.compressor.v3.Zstd + - name: envoy.compression.brotli.decompressor + category: envoy.compression.decompressor + type_urls: + - envoy.extensions.compression.brotli.decompressor.v3.Brotli + - name: envoy.compression.gzip.decompressor + category: envoy.compression.decompressor + type_urls: + - envoy.extensions.compression.gzip.decompressor.v3.Gzip + - name: envoy.compression.zstd.decompressor + category: envoy.compression.decompressor + type_urls: + - envoy.extensions.compression.zstd.decompressor.v3.Zstd + - name: envoy.wasm.runtime.null + category: envoy.wasm.runtime + - name: envoy.wasm.runtime.v8 + category: envoy.wasm.runtime + - name: envoy.dog_statsd + category: envoy.stats_sinks + - name: envoy.graphite_statsd + category: envoy.stats_sinks + - name: envoy.metrics_service + category: envoy.stats_sinks + - name: envoy.stat_sinks.dog_statsd + category: envoy.stats_sinks + type_urls: + - envoy.config.metrics.v3.DogStatsdSink + - name: envoy.stat_sinks.graphite_statsd + category: envoy.stats_sinks + type_urls: + - envoy.extensions.stat_sinks.graphite_statsd.v3.GraphiteStatsdSink + - name: envoy.stat_sinks.hystrix + category: envoy.stats_sinks + type_urls: + - envoy.config.metrics.v3.HystrixSink + - name: envoy.stat_sinks.metrics_service + category: envoy.stats_sinks + type_urls: + - envoy.config.metrics.v3.MetricsServiceConfig + - name: envoy.stat_sinks.statsd + category: envoy.stats_sinks + type_urls: + - envoy.config.metrics.v3.StatsdSink + - name: envoy.stat_sinks.wasm + category: envoy.stats_sinks + type_urls: + - envoy.extensions.stat_sinks.wasm.v3.Wasm + - name: envoy.statsd + category: envoy.stats_sinks + - name: envoy.path.rewrite.uri_template.uri_template_rewriter + category: envoy.path.rewrite + type_urls: + - envoy.extensions.path.rewrite.uri_template.v3.UriTemplateRewriteConfig + - name: envoy.extensions.http.custom_response.local_response_policy + category: envoy.http.custom_response + type_urls: + - envoy.extensions.http.custom_response.local_response_policy.v3.LocalResponsePolicy + - name: envoy.extensions.http.custom_response.redirect_policy + category: envoy.http.custom_response + type_urls: + - envoy.extensions.http.custom_response.redirect_policy.v3.RedirectPolicy + - name: envoy.matching.actions.format_string + category: envoy.matching.action + type_urls: + - envoy.config.core.v3.SubstitutionFormatString + - name: filter-chain-name + category: envoy.matching.action + type_urls: + - google.protobuf.StringValue + - name: envoy.quic.deterministic_connection_id_generator + category: envoy.quic.connection_id_generator + type_urls: + - envoy.extensions.quic.connection_id_generator.v3.DeterministicConnectionIdGeneratorConfig + - name: envoy.network.dns_resolver.cares + category: envoy.network.dns_resolver + type_urls: + - envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig + - name: envoy.network.dns_resolver.getaddrinfo + category: envoy.network.dns_resolver + type_urls: + - envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig + - name: envoy.bootstrap.internal_listener + category: envoy.bootstrap + type_urls: + - envoy.extensions.bootstrap.internal_listener.v3.InternalListener + - name: envoy.bootstrap.wasm + category: envoy.bootstrap + type_urls: + - envoy.extensions.wasm.v3.WasmService + - name: envoy.extensions.network.socket_interface.default_socket_interface + category: envoy.bootstrap + type_urls: + - envoy.extensions.network.socket_interface.v3.DefaultSocketInterface + - name: envoy.filters.listener.http_inspector + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.http_inspector.v3.HttpInspector + - name: envoy.filters.listener.original_dst + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.original_dst.v3.OriginalDst + - name: envoy.filters.listener.original_src + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.original_src.v3.OriginalSrc + - name: envoy.filters.listener.proxy_protocol + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol + - name: envoy.filters.listener.tls_inspector + category: envoy.filters.listener + type_urls: + - envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + - name: envoy.listener.http_inspector + category: envoy.filters.listener + - name: envoy.listener.original_dst + category: envoy.filters.listener + - name: envoy.listener.original_src + category: envoy.filters.listener + - name: envoy.listener.proxy_protocol + category: envoy.filters.listener + - name: envoy.listener.tls_inspector + category: envoy.filters.listener + - name: envoy.matching.common_inputs.environment_variable + category: envoy.matching.common_inputs + type_urls: + - envoy.extensions.matching.common_inputs.environment_variable.v3.Config + - name: envoy.matching.matchers.consistent_hashing + category: envoy.matching.input_matchers + type_urls: + - envoy.extensions.matching.input_matchers.consistent_hashing.v3.ConsistentHashing + - name: envoy.matching.matchers.ip + category: envoy.matching.input_matchers + type_urls: + - envoy.extensions.matching.input_matchers.ip.v3.Ip + - name: envoy.grpc_credentials.aws_iam + category: envoy.grpc_credentials + - name: envoy.grpc_credentials.default + category: envoy.grpc_credentials + - name: envoy.grpc_credentials.file_based_metadata + category: envoy.grpc_credentials + - name: envoy.request_id.uuid + category: envoy.request_id + type_urls: + - envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig + - name: envoy.load_balancing_policies.least_request + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + - name: envoy.load_balancing_policies.maglev + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.maglev.v3.Maglev + - name: envoy.load_balancing_policies.random + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.random.v3.Random + - name: envoy.load_balancing_policies.ring_hash + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash + - name: envoy.load_balancing_policies.round_robin + category: envoy.load_balancing_policies + type_urls: + - envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin + - name: envoy.ip + category: envoy.resolvers + - name: envoy.bandwidth_limit + category: envoy.filters.http + - name: envoy.buffer + category: envoy.filters.http + - name: envoy.cors + category: envoy.filters.http + - name: envoy.csrf + category: envoy.filters.http + - name: envoy.ext_authz + category: envoy.filters.http + - name: envoy.ext_proc + category: envoy.filters.http + - name: envoy.fault + category: envoy.filters.http + - name: envoy.filters.http.adaptive_concurrency + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.adaptive_concurrency.v3.AdaptiveConcurrency + - name: envoy.filters.http.admission_control + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.admission_control.v3.AdmissionControl + - name: envoy.filters.http.alternate_protocols_cache + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig + - name: envoy.filters.http.aws_lambda + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.aws_lambda.v3.Config + - envoy.extensions.filters.http.aws_lambda.v3.PerRouteConfig + - name: envoy.filters.http.aws_request_signing + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning + - name: envoy.filters.http.bandwidth_limit + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.bandwidth_limit.v3.BandwidthLimit + - name: envoy.filters.http.buffer + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.buffer.v3.Buffer + - envoy.extensions.filters.http.buffer.v3.BufferPerRoute + - name: envoy.filters.http.cache + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.cache.v3.CacheConfig + - name: envoy.filters.http.cdn_loop + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.cdn_loop.v3.CdnLoopConfig + - name: envoy.filters.http.composite + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.composite.v3.Composite + - name: envoy.filters.http.compressor + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.compressor.v3.Compressor + - envoy.extensions.filters.http.compressor.v3.CompressorPerRoute + - name: envoy.filters.http.connect_grpc_bridge + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.connect_grpc_bridge.v3.FilterConfig + - name: envoy.filters.http.cors + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.cors.v3.Cors + - envoy.extensions.filters.http.cors.v3.CorsPolicy + - name: envoy.filters.http.csrf + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.csrf.v3.CsrfPolicy + - name: envoy.filters.http.custom_response + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.custom_response.v3.CustomResponse + - name: envoy.filters.http.decompressor + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.decompressor.v3.Decompressor + - name: envoy.filters.http.dynamic_forward_proxy + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig + - envoy.extensions.filters.http.dynamic_forward_proxy.v3.PerRouteConfig + - name: envoy.filters.http.ext_authz + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + - envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute + - name: envoy.filters.http.ext_proc + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.ext_proc.v3.ExtProcPerRoute + - envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + - name: envoy.filters.http.fault + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.fault.v3.HTTPFault + - name: envoy.filters.http.file_system_buffer + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.file_system_buffer.v3.FileSystemBufferFilterConfig + - name: envoy.filters.http.gcp_authn + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig + - name: envoy.filters.http.grpc_http1_bridge + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_http1_bridge.v3.Config + - name: envoy.filters.http.grpc_http1_reverse_bridge + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfig + - envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfigPerRoute + - name: envoy.filters.http.grpc_json_transcoder + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder + - name: envoy.filters.http.grpc_stats + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_stats.v3.FilterConfig + - name: envoy.filters.http.grpc_web + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.grpc_web.v3.GrpcWeb + - name: envoy.filters.http.header_to_metadata + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.header_to_metadata.v3.Config + - name: envoy.filters.http.health_check + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.health_check.v3.HealthCheck + - name: envoy.filters.http.ip_tagging + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.ip_tagging.v3.IPTagging + - name: envoy.filters.http.jwt_authn + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication + - envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig + - name: envoy.filters.http.local_ratelimit + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit + - name: envoy.filters.http.lua + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.lua.v3.Lua + - envoy.extensions.filters.http.lua.v3.LuaPerRoute + - name: envoy.filters.http.match_delegate + category: envoy.filters.http + type_urls: + - envoy.extensions.common.matching.v3.ExtensionWithMatcher + - name: envoy.filters.http.oauth2 + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.oauth2.v3.OAuth2 + - name: envoy.filters.http.on_demand + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.on_demand.v3.OnDemand + - envoy.extensions.filters.http.on_demand.v3.PerRouteConfig + - name: envoy.filters.http.original_src + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.original_src.v3.OriginalSrc + - name: envoy.filters.http.rate_limit_quota + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaFilterConfig + - envoy.extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaOverride + - name: envoy.filters.http.ratelimit + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.ratelimit.v3.RateLimit + - envoy.extensions.filters.http.ratelimit.v3.RateLimitPerRoute + - name: envoy.filters.http.rbac + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.rbac.v3.RBAC + - envoy.extensions.filters.http.rbac.v3.RBACPerRoute + - name: envoy.filters.http.router + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.router.v3.Router + - name: envoy.filters.http.set_metadata + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.set_metadata.v3.Config + - name: envoy.filters.http.stateful_session + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.stateful_session.v3.StatefulSession + - envoy.extensions.filters.http.stateful_session.v3.StatefulSessionPerRoute + - name: envoy.filters.http.tap + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.tap.v3.Tap + - name: envoy.filters.http.wasm + category: envoy.filters.http + type_urls: + - envoy.extensions.filters.http.wasm.v3.Wasm + - name: envoy.grpc_http1_bridge + category: envoy.filters.http + - name: envoy.grpc_json_transcoder + category: envoy.filters.http + - name: envoy.grpc_web + category: envoy.filters.http + - name: envoy.health_check + category: envoy.filters.http + - name: envoy.ip_tagging + category: envoy.filters.http + - name: envoy.local_rate_limit + category: envoy.filters.http + - name: envoy.lua + category: envoy.filters.http + - name: envoy.rate_limit + category: envoy.filters.http + - name: envoy.router + category: envoy.filters.http + - name: envoy.access_loggers.file + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.file.v3.FileAccessLog + - name: envoy.access_loggers.http_grpc + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig + - name: envoy.access_loggers.open_telemetry + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.open_telemetry.v3.OpenTelemetryAccessLogConfig + - name: envoy.access_loggers.stderr + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.stream.v3.StderrAccessLog + - name: envoy.access_loggers.stdout + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + - name: envoy.access_loggers.tcp_grpc + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.grpc.v3.TcpGrpcAccessLogConfig + - name: envoy.access_loggers.wasm + category: envoy.access_loggers + type_urls: + - envoy.extensions.access_loggers.wasm.v3.WasmAccessLog + - name: envoy.file_access_log + category: envoy.access_loggers + - name: envoy.http_grpc_access_log + category: envoy.access_loggers + - name: envoy.open_telemetry_access_log + category: envoy.access_loggers + - name: envoy.stderr_access_log + category: envoy.access_loggers + - name: envoy.stdout_access_log + category: envoy.access_loggers + - name: envoy.tcp_grpc_access_log + category: envoy.access_loggers + - name: envoy.wasm_access_log + category: envoy.access_loggers + - name: envoy.config.validators.minimum_clusters + category: envoy.config.validators + - name: envoy.config.validators.minimum_clusters_validator + category: envoy.config.validators + type_urls: + - envoy.extensions.config.validators.minimum_clusters.v3.MinimumClustersValidator + - name: envoy.http.header_validators.envoy_default + category: envoy.http.header_validators + type_urls: + - envoy.extensions.http.header_validators.envoy_default.v3.HeaderValidatorConfig + - name: dubbo.hessian2 + category: envoy.dubbo_proxy.serializers + - name: quic.http_server_connection.default + category: quic.http_server_connection + - name: envoy.transport_sockets.alts + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.alts.v3.Alts + - name: envoy.transport_sockets.quic + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.quic.v3.QuicDownstreamTransport + - name: envoy.transport_sockets.raw_buffer + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer + - name: envoy.transport_sockets.starttls + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.starttls.v3.StartTlsConfig + - name: envoy.transport_sockets.tap + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.tap.v3.Tap + - name: envoy.transport_sockets.tcp_stats + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.tcp_stats.v3.Config + - name: envoy.transport_sockets.tls + category: envoy.transport_sockets.downstream + type_urls: + - envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + - name: raw_buffer + category: envoy.transport_sockets.downstream + - name: starttls + category: envoy.transport_sockets.downstream + - name: tls + category: envoy.transport_sockets.downstream + - name: envoy.rbac.matchers.upstream_ip_port + category: envoy.rbac.matchers + type_urls: + - envoy.extensions.rbac.matchers.upstream_ip_port.v3.UpstreamIpPortMatcher + - name: envoy.key_value.file_based + category: envoy.common.key_value + type_urls: + - envoy.extensions.key_value.file_based.v3.FileBasedKeyValueStoreConfig + - name: envoy.matching.inputs.application_protocol + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + - name: envoy.matching.inputs.destination_ip + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput + - name: envoy.matching.inputs.destination_port + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + - name: envoy.matching.inputs.direct_source_ip + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput + - name: envoy.matching.inputs.dns_san + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.DnsSanInput + - name: envoy.matching.inputs.server_name + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.ServerNameInput + - name: envoy.matching.inputs.source_ip + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourceIPInput + - name: envoy.matching.inputs.source_port + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourcePortInput + - name: envoy.matching.inputs.source_type + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput + - name: envoy.matching.inputs.subject + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.SubjectInput + - name: envoy.matching.inputs.transport_protocol + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput + - name: envoy.matching.inputs.uri_san + category: envoy.matching.network.input + type_urls: + - envoy.extensions.matching.common_inputs.ssl.v3.UriSanInput + - name: dubbo + category: envoy.dubbo_proxy.protocols + - name: envoy.watchdog.abort_action + category: envoy.guarddog_actions + type_urls: + - envoy.watchdog.v3.AbortActionConfig + - name: envoy.watchdog.profile_action + category: envoy.guarddog_actions + type_urls: + - envoy.extensions.watchdog.profile_action.v3.ProfileActionConfig + - name: envoy.quic.crypto_stream.server.quiche + category: envoy.quic.server.crypto_stream + type_urls: + - envoy.extensions.quic.crypto_stream.v3.CryptoServerStreamConfig + - name: envoy.regex_engines.google_re2 + category: envoy.regex_engines + type_urls: + - envoy.extensions.regex_engines.v3.GoogleRE2 + - name: envoy.http.stateful_session.cookie + category: envoy.http.stateful_session + type_urls: + - envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState + - name: envoy.http.stateful_session.header + category: envoy.http.stateful_session + type_urls: + - envoy.extensions.http.stateful_session.header.v3.HeaderBasedSessionState + - name: envoy.matching.custom_matchers.trie_matcher + category: envoy.matching.network.custom_matchers + type_urls: + - xds.type.matcher.v3.IPMatcher + - name: envoy.udp_packet_writer.default + category: envoy.udp_packet_writer + type_urls: + - envoy.extensions.udp_packet_writer.v3.UdpDefaultWriterFactory + - name: envoy.udp_packet_writer.gso + category: envoy.udp_packet_writer + type_urls: + - envoy.extensions.udp_packet_writer.v3.UdpGsoBatchWriterFactory + - name: envoy.quic.proof_source.filter_chain + category: envoy.quic.proof_source + type_urls: + - envoy.extensions.quic.proof_source.v3.ProofSourceConfig + - name: envoy.resource_monitors.fixed_heap + category: envoy.resource_monitors + type_urls: + - envoy.extensions.resource_monitors.fixed_heap.v3.FixedHeapConfig + - name: envoy.resource_monitors.injected_resource + category: envoy.resource_monitors + type_urls: + - envoy.extensions.resource_monitors.injected_resource.v3.InjectedResourceConfig + - name: envoy.http.stateful_header_formatters.preserve_case + category: envoy.http.stateful_header_formatters + type_urls: + - envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig + - name: preserve_case + category: envoy.http.stateful_header_formatters + - name: envoy.filters.thrift.header_to_metadata + category: envoy.thrift_proxy.filters + type_urls: + - envoy.extensions.filters.network.thrift_proxy.filters.header_to_metadata.v3.HeaderToMetadata + - name: envoy.filters.thrift.payload_to_metadata + category: envoy.thrift_proxy.filters + type_urls: + - envoy.extensions.filters.network.thrift_proxy.filters.payload_to_metadata.v3.PayloadToMetadata + - name: envoy.filters.thrift.rate_limit + category: envoy.thrift_proxy.filters + type_urls: + - envoy.extensions.filters.network.thrift_proxy.filters.ratelimit.v3.RateLimit + - name: envoy.filters.thrift.router + category: envoy.thrift_proxy.filters + type_urls: + - envoy.extensions.filters.network.thrift_proxy.router.v3.Router + - name: envoy.tracers.datadog + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.DatadogConfig + - name: envoy.tracers.dynamic_ot + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.DynamicOtConfig + - name: envoy.tracers.opencensus + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.OpenCensusConfig + - name: envoy.tracers.opentelemetry + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.OpenTelemetryConfig + - name: envoy.tracers.skywalking + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.SkyWalkingConfig + - name: envoy.tracers.xray + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.XRayConfig + - name: envoy.tracers.zipkin + category: envoy.tracers + type_urls: + - envoy.config.trace.v3.ZipkinConfig + - name: envoy.zipkin + category: envoy.tracers + - name: envoy.retry_priorities.previous_priorities + category: envoy.retry_priorities + type_urls: + - envoy.extensions.retry.priority.previous_priorities.v3.PreviousPrioritiesConfig + - name: envoy.http.early_header_mutation.header_mutation + category: envoy.http.early_header_mutation + type_urls: + - envoy.extensions.http.early_header_mutation.header_mutation.v3.HeaderMutation + - name: envoy.connection_handler.default + category: envoy.connection_handler + - name: envoy.transport_sockets.alts + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.alts.v3.Alts + - name: envoy.transport_sockets.http_11_proxy + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.http_11_proxy.v3.Http11ProxyUpstreamTransport + - name: envoy.transport_sockets.internal_upstream + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.internal_upstream.v3.InternalUpstreamTransport + - name: envoy.transport_sockets.quic + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.quic.v3.QuicUpstreamTransport + - name: envoy.transport_sockets.raw_buffer + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer + - name: envoy.transport_sockets.starttls + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.starttls.v3.UpstreamStartTlsConfig + - name: envoy.transport_sockets.tap + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.tap.v3.Tap + - name: envoy.transport_sockets.tcp_stats + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.tcp_stats.v3.Config + - name: envoy.transport_sockets.tls + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + - name: envoy.transport_sockets.upstream_proxy_protocol + category: envoy.transport_sockets.upstream + type_urls: + - envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport + - name: raw_buffer + category: envoy.transport_sockets.upstream + - name: starttls + category: envoy.transport_sockets.upstream + - name: tls + category: envoy.transport_sockets.upstream + - name: auto + category: envoy.thrift_proxy.transports + - name: framed + category: envoy.thrift_proxy.transports + - name: header + category: envoy.thrift_proxy.transports + - name: unframed + category: envoy.thrift_proxy.transports + - name: envoy.cluster.eds + category: envoy.clusters + - name: envoy.cluster.logical_dns + category: envoy.clusters + - name: envoy.cluster.original_dst + category: envoy.clusters + - name: envoy.cluster.static + category: envoy.clusters + - name: envoy.cluster.strict_dns + category: envoy.clusters + - name: envoy.clusters.aggregate + category: envoy.clusters + - name: envoy.clusters.dynamic_forward_proxy + category: envoy.clusters + - name: envoy.clusters.redis + category: envoy.clusters + - name: envoy.access_loggers.extension_filters.cel + category: envoy.access_loggers.extension_filters + type_urls: + - envoy.extensions.access_loggers.filters.cel.v3.ExpressionFilter + - name: auto + category: envoy.thrift_proxy.protocols + - name: binary + category: envoy.thrift_proxy.protocols + - name: binary/non-strict + category: envoy.thrift_proxy.protocols + - name: compact + category: envoy.thrift_proxy.protocols + - name: twitter + category: envoy.thrift_proxy.protocols + - name: envoy.extensions.upstreams.http.v3.HttpProtocolOptions + category: envoy.upstream_options + type_urls: + - envoy.extensions.upstreams.http.v3.HttpProtocolOptions + - name: envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions + category: envoy.upstream_options + type_urls: + - envoy.extensions.upstreams.tcp.v3.TcpProtocolOptions + - name: envoy.upstreams.http.http_protocol_options + category: envoy.upstream_options + - name: envoy.upstreams.tcp.tcp_protocol_options + category: envoy.upstream_options + - name: envoy.listener_manager_impl.default + category: envoy.listener_manager_impl + type_urls: + - envoy.config.listener.v3.ListenerManager + - name: default + category: network.connection.client + - name: envoy_internal + category: network.connection.client + - name: envoy.filters.udp.dns_filter + category: envoy.filters.udp_listener + type_urls: + - envoy.extensions.filters.udp.dns_filter.v3.DnsFilterConfig + - name: envoy.filters.udp_listener.udp_proxy + category: envoy.filters.udp_listener + type_urls: + - envoy.extensions.filters.udp.udp_proxy.v3.UdpProxyConfig + - name: envoy.extensions.http.cache.file_system_http_cache + category: envoy.http.cache + type_urls: + - envoy.extensions.http.cache.file_system_http_cache.v3.FileSystemHttpCacheConfig + - name: envoy.extensions.http.cache.simple + category: envoy.http.cache + type_urls: + - envoy.extensions.http.cache.simple_http_cache.v3.SimpleHttpCacheConfig + - name: envoy.retry_host_predicates.omit_canary_hosts + category: envoy.retry_host_predicates + type_urls: + - envoy.extensions.retry.host.omit_canary_hosts.v3.OmitCanaryHostsPredicate + - name: envoy.retry_host_predicates.omit_host_metadata + category: envoy.retry_host_predicates + type_urls: + - envoy.extensions.retry.host.omit_host_metadata.v3.OmitHostMetadataConfig + - name: envoy.retry_host_predicates.previous_hosts + category: envoy.retry_host_predicates + type_urls: + - envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate + - name: envoy.formatter.metadata + category: envoy.formatter + type_urls: + - envoy.extensions.formatter.metadata.v3.Metadata + - name: envoy.formatter.req_without_query + category: envoy.formatter + type_urls: + - envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery + - name: envoy.internal_redirect_predicates.allow_listed_routes + category: envoy.internal_redirect_predicates + type_urls: + - envoy.extensions.internal_redirect.allow_listed_routes.v3.AllowListedRoutesConfig + - name: envoy.internal_redirect_predicates.previous_routes + category: envoy.internal_redirect_predicates + type_urls: + - envoy.extensions.internal_redirect.previous_routes.v3.PreviousRoutesConfig + - name: envoy.internal_redirect_predicates.safe_cross_scheme + category: envoy.internal_redirect_predicates + type_urls: + - envoy.extensions.internal_redirect.safe_cross_scheme.v3.SafeCrossSchemeConfig + - name: envoy.matching.custom_matchers.trie_matcher + category: envoy.matching.http.custom_matchers + type_urls: + - xds.type.matcher.v3.IPMatcher + - name: envoy.filters.dubbo.router + category: envoy.dubbo_proxy.filters + type_urls: + - envoy.extensions.filters.network.dubbo_proxy.router.v3.Router + - name: envoy.echo + category: envoy.filters.network + - name: envoy.ext_authz + category: envoy.filters.network + - name: envoy.filters.network.connection_limit + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit + - name: envoy.filters.network.direct_response + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.direct_response.v3.Config + - name: envoy.filters.network.dubbo_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.dubbo_proxy.v3.DubboProxy + - name: envoy.filters.network.echo + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.echo.v3.Echo + - name: envoy.filters.network.ext_authz + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.ext_authz.v3.ExtAuthz + - name: envoy.filters.network.http_connection_manager + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + - name: envoy.filters.network.local_ratelimit + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.local_ratelimit.v3.LocalRateLimit + - name: envoy.filters.network.mongo_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy + - name: envoy.filters.network.ratelimit + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.ratelimit.v3.RateLimit + - name: envoy.filters.network.rbac + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.rbac.v3.RBAC + - name: envoy.filters.network.redis_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.redis_proxy.v3.RedisProxy + - name: envoy.filters.network.sni_cluster + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.sni_cluster.v3.SniCluster + - name: envoy.filters.network.sni_dynamic_forward_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.sni_dynamic_forward_proxy.v3.FilterConfig + - name: envoy.filters.network.tcp_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + - name: envoy.filters.network.thrift_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.thrift_proxy.v3.ThriftProxy + - name: envoy.filters.network.wasm + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.wasm.v3.Wasm + - name: envoy.filters.network.zookeeper_proxy + category: envoy.filters.network + type_urls: + - envoy.extensions.filters.network.zookeeper_proxy.v3.ZooKeeperProxy + - name: envoy.http_connection_manager + category: envoy.filters.network + - name: envoy.mongo_proxy + category: envoy.filters.network + - name: envoy.ratelimit + category: envoy.filters.network + - name: envoy.redis_proxy + category: envoy.filters.network + - name: envoy.tcp_proxy + category: envoy.filters.network + - name: envoy.health_checkers.redis + category: envoy.health_checkers + type_urls: + - envoy.extensions.health_checkers.redis.v3.Redis + - name: envoy.health_checkers.thrift + category: envoy.health_checkers + type_urls: + - envoy.extensions.health_checkers.thrift.v3.Thrift + static_resources: + clusters: + - name: xds_cluster + type: STRICT_DNS + connect_timeout: 1s + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + tls_certificate_sds_secret_configs: + - name: xds_certificate + sds_config: + resource_api_version: V3 + path_config_source: + path: "/sds/xds-certificate.json" + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + resource_api_version: V3 + path_config_source: + path: "/sds/xds-trusted-ca.json" + load_assignment: + cluster_name: xds_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: higress + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + dynamic_resources: + lds_config: + api_config_source: + api_type: DELTA_GRPC + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + transport_api_version: V3 + resource_api_version: V3 + cds_config: + api_config_source: + api_type: DELTA_GRPC + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + transport_api_version: V3 + resource_api_version: V3 + admin: + address: + socket_address: + address: 127.0.0.1 + port_value: 15000 + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: "/dev/null" + layered_runtime: + layers: + - name: runtime-0 + rtds_layer: + name: runtime-0 + rtds_config: + api_config_source: + api_type: DELTA_GRPC + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + transport_api_version: V3 + resource_api_version: V3 +last_updated: '2023-02-23T09:05:23.422Z' diff --git a/pkg/cmd/hgctl/testdata/config/output/out.cluster.json b/pkg/cmd/hgctl/testdata/config/output/out.cluster.json new file mode 100644 index 0000000000..3f158fd19c --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.cluster.json @@ -0,0 +1,98 @@ +{ + "@type": "type.googleapis.com/envoy.admin.v3.ClustersConfigDump", + "version_info": "2", + "static_clusters": [{ + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "xds_cluster", + "type": "STRICT_DNS", + "connect_timeout": "1s", + "transport_socket": { + "name": "envoy.transport_sockets.tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": { + "tls_maximum_protocol_version": "TLSv1_3" + }, + "tls_certificate_sds_secret_configs": [{ + "name": "xds_certificate", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-certificate.json" + } + } + }], + "validation_context_sds_secret_config": { + "name": "xds_trusted_ca", + "sds_config": { + "resource_api_version": "V3", + "path_config_source": { + "path": "/sds/xds-trusted-ca.json" + } + } + } + } + } + }, + "load_assignment": { + "cluster_name": "xds_cluster", + "endpoints": [{ + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "higress", + "port_value": 18000 + } + } + } + }] + }] + }, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + } + }, + "last_updated": "2023-02-23T09:05:23.436Z" + }], + "dynamic_active_clusters": [{ + "version_info": "2a0a1698a9d3e05b802047b0cd36b52a070afa49042e1ba267168c5265c7cabf", + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "default-backend-rule-0-match-0-www.example.com", + "type": "STATIC", + "connect_timeout": "5s", + "dns_lookup_family": "V4_ONLY", + "outlier_detection": {}, + "common_lb_config": { + "locality_weighted_lb_config": {} + }, + "load_assignment": { + "cluster_name": "default-backend-rule-0-match-0-www.example.com", + "endpoints": [{ + "locality": {}, + "lb_endpoints": [{ + "endpoint": { + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 3000 + } + } + }, + "load_balancing_weight": 1 + }], + "load_balancing_weight": 1 + }] + } + }, + "last_updated": "2023-02-23T09:05:38.443Z" + }] +} diff --git a/pkg/cmd/hgctl/testdata/config/output/out.cluster.yaml b/pkg/cmd/hgctl/testdata/config/output/out.cluster.yaml new file mode 100644 index 0000000000..799a8d5517 --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.cluster.yaml @@ -0,0 +1,67 @@ +--- +"@type": type.googleapis.com/envoy.admin.v3.ClustersConfigDump +version_info: '2' +static_clusters: +- cluster: + "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster + name: xds_cluster + type: STRICT_DNS + connect_timeout: 1s + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + tls_certificate_sds_secret_configs: + - name: xds_certificate + sds_config: + resource_api_version: V3 + path_config_source: + path: "/sds/xds-certificate.json" + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + resource_api_version: V3 + path_config_source: + path: "/sds/xds-trusted-ca.json" + load_assignment: + cluster_name: xds_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: higress + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + last_updated: '2023-02-23T09:05:23.436Z' +dynamic_active_clusters: +- version_info: 2a0a1698a9d3e05b802047b0cd36b52a070afa49042e1ba267168c5265c7cabf + cluster: + "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster + name: default-backend-rule-0-match-0-www.example.com + type: STATIC + connect_timeout: 5s + dns_lookup_family: V4_ONLY + outlier_detection: {} + common_lb_config: + locality_weighted_lb_config: {} + load_assignment: + cluster_name: default-backend-rule-0-match-0-www.example.com + endpoints: + - locality: {} + lb_endpoints: + - endpoint: + address: + socket_address: + address: 0.0.0.0 + port_value: 3000 + load_balancing_weight: 1 + load_balancing_weight: 1 + last_updated: '2023-02-23T09:05:38.443Z' diff --git a/pkg/cmd/hgctl/testdata/config/output/out.endpoints.json b/pkg/cmd/hgctl/testdata/config/output/out.endpoints.json new file mode 100644 index 0000000000..a8d86015aa --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.endpoints.json @@ -0,0 +1,30 @@ +{ + "@type": "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump", + "staticEndpointConfigs": [{ + "endpointConfig": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "xds_cluster", + "endpoints": [{ + "locality": {}, + "lbEndpoints": [{ + "endpoint": { + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 18000 + } + }, + "healthCheckConfig": {}, + "hostname": "higress" + }, + "healthStatus": "HEALTHY", + "metadata": {}, + "loadBalancingWeight": 1 + }] + }], + "policy": { + "overprovisioningFactor": 140 + } + } + }] +} diff --git a/pkg/cmd/hgctl/testdata/config/output/out.endpoints.yaml b/pkg/cmd/hgctl/testdata/config/output/out.endpoints.yaml new file mode 100644 index 0000000000..f224724d9f --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.endpoints.yaml @@ -0,0 +1,21 @@ +--- +"@type": type.googleapis.com/envoy.admin.v3.EndpointsConfigDump +staticEndpointConfigs: +- endpointConfig: + "@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment + clusterName: xds_cluster + endpoints: + - locality: {} + lbEndpoints: + - endpoint: + address: + socketAddress: + address: 0.0.0.0 + portValue: 18000 + healthCheckConfig: {} + hostname: higress + healthStatus: HEALTHY + metadata: {} + loadBalancingWeight: 1 + policy: + overprovisioningFactor: 140 diff --git a/pkg/cmd/hgctl/testdata/config/output/out.listener.json b/pkg/cmd/hgctl/testdata/config/output/out.listener.json new file mode 100644 index 0000000000..31f100e60a --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.listener.json @@ -0,0 +1,77 @@ +{ + "@type": "type.googleapis.com/envoy.admin.v3.ListenersConfigDump", + "version_info": "2", + "dynamic_listeners": [{ + "name": "default-higress-http", + "active_state": { + "version_info": "42c71fb50c315ee3a32b327da69f8cc0baf420bc84b747e82d9c38e1b0c33eb2", + "listener": { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "default-higress-http", + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 10080 + } + }, + "access_log": [{ + "name": "envoy.access_loggers.file", + "filter": { + "response_flag_filter": { + "flags": [ + "NR" + ] + } + }, + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/stdout" + } + }], + "default_filter_chain": { + "filters": [{ + "name": "envoy.filters.network.http_connection_manager", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "http", + "rds": { + "config_source": { + "api_config_source": { + "api_type": "DELTA_GRPC", + "grpc_services": [{ + "envoy_grpc": { + "cluster_name": "xds_cluster" + } + }], + "set_node_on_first_message_only": true, + "transport_api_version": "V3" + }, + "resource_api_version": "V3" + }, + "route_config_name": "default-higress-http" + }, + "http_filters": [{ + "name": "envoy.filters.http.router", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + }], + "access_log": [{ + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/stdout" + } + }], + "use_remote_address": true, + "upgrade_configs": [{ + "upgrade_type": "websocket" + }] + } + }] + } + }, + "last_updated": "2023-02-23T09:05:38.446Z" + } + }] +} diff --git a/pkg/cmd/hgctl/testdata/config/output/out.listener.yaml b/pkg/cmd/hgctl/testdata/config/output/out.listener.yaml new file mode 100644 index 0000000000..d8e4c66a62 --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.listener.yaml @@ -0,0 +1,53 @@ +--- +"@type": type.googleapis.com/envoy.admin.v3.ListenersConfigDump +version_info: '2' +dynamic_listeners: +- name: default-higress-http + active_state: + version_info: 42c71fb50c315ee3a32b327da69f8cc0baf420bc84b747e82d9c38e1b0c33eb2 + listener: + "@type": type.googleapis.com/envoy.config.listener.v3.Listener + name: default-higress-http + address: + socket_address: + address: 0.0.0.0 + port_value: 10080 + access_log: + - name: envoy.access_loggers.file + filter: + response_flag_filter: + flags: + - NR + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: "/dev/stdout" + default_filter_chain: + filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: http + rds: + config_source: + api_config_source: + api_type: DELTA_GRPC + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + transport_api_version: V3 + resource_api_version: V3 + route_config_name: default-higress-http + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: "/dev/stdout" + use_remote_address: true + upgrade_configs: + - upgrade_type: websocket + last_updated: '2023-02-23T09:05:38.446Z' diff --git a/pkg/cmd/hgctl/testdata/config/output/out.route.json b/pkg/cmd/hgctl/testdata/config/output/out.route.json new file mode 100644 index 0000000000..5f06bffb92 --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.route.json @@ -0,0 +1,31 @@ +{ + "@type": "type.googleapis.com/envoy.admin.v3.RoutesConfigDump", + "dynamic_route_configs": [{ + "version_info": "cb1e51997a9c3aa6f4d920f39fd5bdbd966e9382b7b6bdf42efca8c22c6c3442", + "route_config": { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "default-higress-http", + "virtual_hosts": [{ + "name": "default-higress-http", + "domains": [ + "*" + ], + "routes": [{ + "match": { + "prefix": "/", + "headers": [{ + "name": ":authority", + "string_match": { + "exact": "www.example.com" + } + }] + }, + "route": { + "cluster": "default-backend-rule-0-match-0-www.example.com" + } + }] + }] + }, + "last_updated": "2023-02-23T09:05:38.448Z" + }] +} diff --git a/pkg/cmd/hgctl/testdata/config/output/out.route.yaml b/pkg/cmd/hgctl/testdata/config/output/out.route.yaml new file mode 100644 index 0000000000..df99a268ec --- /dev/null +++ b/pkg/cmd/hgctl/testdata/config/output/out.route.yaml @@ -0,0 +1,21 @@ +--- +"@type": type.googleapis.com/envoy.admin.v3.RoutesConfigDump +dynamic_route_configs: +- version_info: cb1e51997a9c3aa6f4d920f39fd5bdbd966e9382b7b6bdf42efca8c22c6c3442 + route_config: + "@type": type.googleapis.com/envoy.config.route.v3.RouteConfiguration + name: default-higress-http + virtual_hosts: + - name: default-higress-http + domains: + - "*" + routes: + - match: + prefix: "/" + headers: + - name: ":authority" + string_match: + exact: www.example.com + route: + cluster: default-backend-rule-0-match-0-www.example.com + last_updated: '2023-02-23T09:05:38.448Z' diff --git a/pkg/cmd/hgctl/utils.go b/pkg/cmd/hgctl/utils.go new file mode 100644 index 0000000000..c9c271c82f --- /dev/null +++ b/pkg/cmd/hgctl/utils.go @@ -0,0 +1,81 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "encoding/json" + "fmt" +) + +type envoyConfigType string + +var ( + BootstrapEnvoyConfigType envoyConfigType = "bootstrap" + ClusterEnvoyConfigType envoyConfigType = "cluster" + EndpointEnvoyConfigType envoyConfigType = "endpoint" + ListenerEnvoyConfigType envoyConfigType = "listener" + RouteEnvoyConfigType envoyConfigType = "route" + AllEnvoyConfigType envoyConfigType = "all" +) + +func GetXDSResource(resourceType envoyConfigType, configDump []byte) (any, error) { + cd := map[string]any{} + if err := json.Unmarshal(configDump, &cd); err != nil { + return nil, err + } + if resourceType == AllEnvoyConfigType { + return cd, nil + } + configs := cd["configs"] + globalConfigs := configs.([]any) + + switch resourceType { + case BootstrapEnvoyConfigType: + for _, config := range globalConfigs { + if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump" { + return config, nil + } + } + case EndpointEnvoyConfigType: + for _, config := range globalConfigs { + if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump" { + return config, nil + } + } + + case ClusterEnvoyConfigType: + for _, config := range globalConfigs { + if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.ClustersConfigDump" { + return config, nil + } + } + case ListenerEnvoyConfigType: + for _, config := range globalConfigs { + if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump" { + return config, nil + } + } + case RouteEnvoyConfigType: + for _, config := range globalConfigs { + if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.RoutesConfigDump" { + return config, nil + } + } + default: + return nil, fmt.Errorf("unknown resourceType %s", resourceType) + } + + return nil, fmt.Errorf("unknown resourceType %s", resourceType) +} diff --git a/pkg/cmd/hgctl/version.go b/pkg/cmd/hgctl/version.go new file mode 100644 index 0000000000..75b78467db --- /dev/null +++ b/pkg/cmd/hgctl/version.go @@ -0,0 +1,193 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hgctl + +import ( + "encoding/json" + "fmt" + "io" + "sort" + "strings" + + "github.com/alibaba/higress/pkg/cmd/hgctl/kubernetes" + "github.com/alibaba/higress/pkg/cmd/options" + "github.com/alibaba/higress/pkg/cmd/version" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +const ( + yamlOutput = "yaml" + jsonOutput = "json" + higressCoreContainerName = "higress-core" + higressGatewayContainerName = "higress-gateway" +) + +func newVersionCommand() *cobra.Command { + var ( + output string + client bool + ) + + versionCommand := &cobra.Command{ + Use: "version", + Aliases: []string{"versions", "v"}, + Short: "Show version", + Example: ` # Show versions of both client and server. + hgctl version + + # Show versions of both client and server in JSON format. + hgctl version --output=json + + # Show version of client without server. + hgctl version --client + `, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(versions(cmd.OutOrStdout(), output, client)) + }, + } + + flags := versionCommand.Flags() + options.AddKubeConfigFlags(flags) + + versionCommand.PersistentFlags().StringVarP(&output, "output", "o", yamlOutput, "One of 'yaml' or 'json'") + + versionCommand.PersistentFlags().BoolVarP(&client, "client", "r", false, "If true, only log client version.") + + return versionCommand +} + +type VersionInfo struct { + ClientVersion string `json:"client" yaml:"client"` + ServerVersions []*ServerVersion `json:"server,omitempty" yaml:"server"` +} + +type ServerVersion struct { + types.NamespacedName `yaml:"namespacedName"` + version.Info `yaml:"versionInfo"` +} + +func Get() VersionInfo { + return VersionInfo{ + ClientVersion: version.Get().HigressVersion, + ServerVersions: make([]*ServerVersion, 0), + } +} + +func retrieveVersion(w io.Writer, v *VersionInfo, containerName string, cmd string, labelSelector string, c kubernetes.CLIClient, f versionFunc) error { + pods, err := c.PodsForSelector(metav1.NamespaceAll, labelSelector) + if err != nil { + return errors.Wrap(err, "list Higress pods failed") + } + + for _, pod := range pods.Items { + if pod.Status.Phase != v1.PodRunning { + + fmt.Fprintf(w, "WARN: pod %s/%s is not running, skipping it.", pod.Namespace, pod.Name) + continue + } + + nn := types.NamespacedName{ + Namespace: pod.Namespace, + Name: pod.Name, + } + stdout, _, err := c.PodExec(nn, containerName, cmd) + if err != nil { + return fmt.Errorf("pod exec on %s/%s failed: %w", nn.Namespace, nn.Name, err) + } + + info, err := f(stdout) + if err != nil { + return err + } + + v.ServerVersions = append(v.ServerVersions, &ServerVersion{ + NamespacedName: nn, + Info: *info, + }) + } + + return nil +} + +type versionFunc func(string) (*version.Info, error) + +func versions(w io.Writer, output string, client bool) error { + v := Get() + + if client { + fmt.Fprintf(w, "clientVersion: %s", v.ClientVersion) + return nil + } + + c, err := kubernetes.NewCLIClient(options.DefaultConfigFlags.ToRawKubeConfigLoader()) + if err != nil { + return fmt.Errorf("failed to build kubernetes client: %w", err) + } + + if err := retrieveVersion(w, &v, higressCoreContainerName, "higress version -ojson", "app=higress-controller", c, func(s string) (*version.Info, error) { + info := &version.Info{} + if err := json.Unmarshal([]byte(s), info); err != nil { + return nil, fmt.Errorf("unmarshall pod exec result failed: %w", err) + } + info.Type = "higress-controller" + return info, nil + }); err != nil { + return err + } + + if err := retrieveVersion(w, &v, higressGatewayContainerName, "envoy --version", "app=higress-gateway", c, func(s string) (*version.Info, error) { + if len(strings.Split(s, ":")) != 2 { + return nil, nil + } + proxyVersion := strings.TrimSpace(strings.Split(s, ":")[1]) + return &version.Info{ + GatewayVersion: proxyVersion, + Type: "higress-gateway", + }, nil + }); err != nil { + return err + } + + sort.Slice(v.ServerVersions, func(i, j int) bool { + if v.ServerVersions[i].Namespace == v.ServerVersions[j].Namespace { + return v.ServerVersions[i].Name < v.ServerVersions[j].Name + } + + return v.ServerVersions[i].Namespace < v.ServerVersions[j].Namespace + }) + + var out []byte + switch output { + case yamlOutput: + out, err = yaml.Marshal(v) + case jsonOutput: + out, err = json.MarshalIndent(v, "", " ") + default: + out, err = json.MarshalIndent(v, "", " ") + } + + if err != nil { + return err + } + fmt.Fprintln(w, string(out)) + + return nil +} diff --git a/pkg/cmd/options/global.go b/pkg/cmd/options/global.go new file mode 100644 index 0000000000..056c30523f --- /dev/null +++ b/pkg/cmd/options/global.go @@ -0,0 +1,29 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package options + +import ( + "github.com/spf13/pflag" + "k8s.io/cli-runtime/pkg/genericclioptions" +) + +var DefaultConfigFlags = genericclioptions.NewConfigFlags(true) + +func AddKubeConfigFlags(flags *pflag.FlagSet) { + flags.StringVar(DefaultConfigFlags.KubeConfig, "kubeconfig", *DefaultConfigFlags.KubeConfig, + "Path to the kubeconfig file to use for CLI requests.") + flags.StringVar(DefaultConfigFlags.Context, "context", *DefaultConfigFlags.Context, + "The name of the kubeconfig context to use.") +} diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go new file mode 100644 index 0000000000..f4faa5256b --- /dev/null +++ b/pkg/cmd/root.go @@ -0,0 +1,32 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import "github.com/spf13/cobra" + +// GetRootCommand returns the root cobra command to be executed +// by main. +func GetRootCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "higress", + Short: "Higress", + Long: "Next-generation Cloud Native Gateway", + } + + cmd.AddCommand(getServerCommand()) + cmd.AddCommand(getVersionCommand()) + + return cmd +} diff --git a/pkg/cmd/server.go b/pkg/cmd/server.go new file mode 100644 index 0000000000..948db6da8f --- /dev/null +++ b/pkg/cmd/server.go @@ -0,0 +1,120 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "time" + + "github.com/alibaba/higress/pkg/bootstrap" + innerconstants "github.com/alibaba/higress/pkg/config/constants" + "github.com/spf13/cobra" + "istio.io/istio/pilot/pkg/features" + "istio.io/istio/pkg/cmd" + "istio.io/istio/pkg/config/constants" + "istio.io/istio/pkg/keepalive" + "istio.io/pkg/log" +) + +var ( + serverArgs *bootstrap.ServerArgs + loggingOptions = log.DefaultOptions() + + serverProvider = func(args *bootstrap.ServerArgs) (bootstrap.ServerInterface, error) { + return bootstrap.NewServer(serverArgs) + } + + waitForMonitorSignal = func(stop chan struct{}) { + cmd.WaitSignal(stop) + } +) + +// getServerCommand returns the server cobra command to be executed. +func getServerCommand() *cobra.Command { + serveCmd := &cobra.Command{ + Use: "serve", + Aliases: []string{"serve"}, + Short: "Starts the higress ingress controller", + Example: "higress serve", + PreRunE: func(c *cobra.Command, args []string) error { + return log.Configure(loggingOptions) + }, + RunE: func(c *cobra.Command, args []string) error { + cmd.PrintFlags(c.Flags()) + + stop := make(chan struct{}) + + server, err := serverProvider(serverArgs) + if err != nil { + return fmt.Errorf("fail to create higress server: %v", err) + } + + if err := server.Start(stop); err != nil { + return fmt.Errorf("fail to start higress server: %v", err) + } + + waitForMonitorSignal(stop) + + server.WaitUntilCompletion() + return nil + }, + } + + serverArgs = &bootstrap.ServerArgs{ + Debug: true, + NativeIstio: true, + HttpAddress: ":8888", + GrpcAddress: ":15051", + GrpcKeepAliveOptions: keepalive.DefaultOption(), + XdsOptions: bootstrap.XdsOptions{ + DebounceAfter: features.DebounceAfter, + DebounceMax: features.DebounceMax, + EnableEDSDebounce: features.EnableEDSDebounce, + }, + } + + serveCmd.PersistentFlags().StringVar(&serverArgs.GatewaySelectorKey, "gatewaySelectorKey", "higress", "gateway resource selector label key") + serveCmd.PersistentFlags().StringVar(&serverArgs.GatewaySelectorValue, "gatewaySelectorValue", "higress-gateway", "gateway resource selector label value") + serveCmd.PersistentFlags().BoolVar(&serverArgs.EnableStatus, "enableStatus", true, "enable the ingress status syncer which use to update the ip in ingress's status") + serveCmd.PersistentFlags().StringVar(&serverArgs.IngressClass, "ingressClass", innerconstants.DefaultIngressClass, "if not empty, only watch the ingresses have the specified class, otherwise watch all ingresses") + serveCmd.PersistentFlags().StringVar(&serverArgs.WatchNamespace, "watchNamespace", "", "if not empty, only wath the ingresses in the specified namespace, otherwise watch in all namespacees") + serveCmd.PersistentFlags().BoolVar(&serverArgs.Debug, "debug", serverArgs.Debug, "if true, enables more debug http api") + serveCmd.PersistentFlags().StringVar(&serverArgs.HttpAddress, "httpAddress", serverArgs.HttpAddress, "the http address") + serveCmd.PersistentFlags().StringVar(&serverArgs.GrpcAddress, "grpcAddress", serverArgs.GrpcAddress, "the grpc address") + serveCmd.PersistentFlags().BoolVar(&serverArgs.KeepStaleWhenEmpty, "keepStaleWhenEmpty", false, "keep the stale service entry when there are no endpoints in the service") + serveCmd.PersistentFlags().StringVar(&serverArgs.RegistryOptions.ClusterRegistriesNamespace, "clusterRegistriesNamespace", + serverArgs.RegistryOptions.ClusterRegistriesNamespace, "Namespace for ConfigMap which stores clusters configs") + serveCmd.PersistentFlags().StringVar(&serverArgs.RegistryOptions.KubeConfig, "kubeconfig", "", + "Use a Kubernetes configuration file instead of in-cluster configuration") + // RegistryOptions Controller options + serveCmd.PersistentFlags().DurationVar(&serverArgs.RegistryOptions.KubeOptions.ResyncPeriod, "resync", 60*time.Second, + "Controller resync interval") + serveCmd.PersistentFlags().StringVar(&serverArgs.RegistryOptions.KubeOptions.DomainSuffix, "domain", constants.DefaultKubernetesDomain, + "DNS domain suffix") + serveCmd.PersistentFlags().StringVar((*string)(&serverArgs.RegistryOptions.KubeOptions.ClusterID), "clusterID", "Kubernetes", + "The ID of the cluster that this instance resides") + serveCmd.PersistentFlags().StringToStringVar(&serverArgs.RegistryOptions.KubeOptions.ClusterAliases, "clusterAliases", map[string]string{}, + "Alias names for clusters") + serveCmd.PersistentFlags().Float32Var(&serverArgs.RegistryOptions.KubeOptions.KubernetesAPIQPS, "kubernetesApiQPS", 80.0, + "Maximum QPS when communicating with the kubernetes API") + + serveCmd.PersistentFlags().IntVar(&serverArgs.RegistryOptions.KubeOptions.KubernetesAPIBurst, "kubernetesApiBurst", 160, + "Maximum burst for throttle when communicating with the kubernetes API") + + loggingOptions.AttachCobraFlags(serveCmd) + serverArgs.GrpcKeepAliveOptions.AttachCobraFlags(serveCmd) + + return serveCmd +} diff --git a/cmd/higress/main_test.go b/pkg/cmd/server_test.go similarity index 96% rename from cmd/higress/main_test.go rename to pkg/cmd/server_test.go index 52f54423d8..785a911d7b 100644 --- a/cmd/higress/main_test.go +++ b/pkg/cmd/server_test.go @@ -12,18 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -package main +package cmd import ( - "github.com/alibaba/higress/pkg/bootstrap" - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" "os" "testing" "time" + + "github.com/alibaba/higress/pkg/bootstrap" + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" ) func TestServe(t *testing.T) { + serveCmd := getServerCommand() runEBackup := serveCmd.RunE argsBackup := os.Args serverProviderBackup := serverProvider @@ -53,7 +55,9 @@ func TestServe(t *testing.T) { time.Sleep(delay) close(stop) } - main() + + serveCmd.Execute() + end := time.Now() cost := end.Sub(start) diff --git a/pkg/cmd/version.go b/pkg/cmd/version.go new file mode 100644 index 0000000000..94e4121fee --- /dev/null +++ b/pkg/cmd/version.go @@ -0,0 +1,38 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/alibaba/higress/pkg/cmd/version" + "github.com/spf13/cobra" +) + +// getVersionCommand returns the version cobra command to be executed. +func getVersionCommand() *cobra.Command { + var output string + + cmd := &cobra.Command{ + Use: "version", + Aliases: []string{"versions", "v"}, + Short: "Show versions", + RunE: func(cmd *cobra.Command, args []string) error { + return version.Print(cmd.OutOrStdout(), output) + }, + } + + cmd.PersistentFlags().StringVarP(&output, "output", "o", "", "One of 'yaml' or 'json'") + + return cmd +} diff --git a/pkg/cmd/version/version.go b/pkg/cmd/version/version.go new file mode 100644 index 0000000000..1736efbc61 --- /dev/null +++ b/pkg/cmd/version/version.go @@ -0,0 +1,62 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package version + +import ( + "encoding/json" + "fmt" + "io" + + "sigs.k8s.io/yaml" +) + +type Info struct { + Type string `json:"type,omitempty" yaml:"type,omitempty"` + HigressVersion string `json:"higressVersion,omitempty" yaml:"higressVersion,omitempty"` + GitCommitID string `json:"gitCommitID,omitempty" yaml:"gitCommitID,omitempty"` + GatewayVersion string `json:"gatewayVersion,omitempty" yaml:"gatewayVersion,omitempty"` +} + +func Get() Info { + return Info{ + HigressVersion: higressVersion, + GitCommitID: gitCommitID, + } +} + +var ( + higressVersion string + gitCommitID string +) + +// Print shows the versions of the Envoy Gateway. +func Print(w io.Writer, format string) error { + v := Get() + switch format { + case "json": + if marshalled, err := json.MarshalIndent(v, "", " "); err == nil { + _, _ = fmt.Fprintln(w, string(marshalled)) + } + case "yaml": + if marshalled, err := yaml.Marshal(v); err == nil { + _, _ = fmt.Fprintln(w, string(marshalled)) + } + default: + _, _ = fmt.Fprintf(w, "HIGRESS_VERSION: %s\n", v.HigressVersion) + _, _ = fmt.Fprintf(w, "GIT_COMMIT_ID: %s\n", v.GitCommitID) + } + + return nil +} diff --git a/pkg/ingress/config/ingress_config.go b/pkg/ingress/config/ingress_config.go index b19241de15..529974224b 100644 --- a/pkg/ingress/config/ingress_config.go +++ b/pkg/ingress/config/ingress_config.go @@ -559,27 +559,36 @@ func (m *IngressConfig) convertDestinationRule(configs []common.WrapperConfig) [ IngressLog.Debugf("traffic policy number %d", len(convertOptions.Service2TrafficPolicy)) for _, wrapperTrafficPolicy := range convertOptions.Service2TrafficPolicy { - m.annotationHandler.ApplyTrafficPolicy(wrapperTrafficPolicy.TrafficPolicy, wrapperTrafficPolicy.WrapperConfig.AnnotationsConfig) + m.annotationHandler.ApplyTrafficPolicy(wrapperTrafficPolicy.TrafficPolicy, wrapperTrafficPolicy.PortTrafficPolicy, wrapperTrafficPolicy.WrapperConfig.AnnotationsConfig) } // Merge multi-port traffic policy per service into one destination rule. destinationRules := map[string]*common.WrapperDestinationRule{} for key, wrapperTrafficPolicy := range convertOptions.Service2TrafficPolicy { - serviceName := util.CreateServiceFQDN(key.Namespace, key.Name) + var serviceName string + if key.ServiceFQDN != "" { + serviceName = key.ServiceFQDN + } else { + serviceName = util.CreateServiceFQDN(key.Namespace, key.Name) + } dr, exist := destinationRules[serviceName] if !exist { + trafficPolicy := &networking.TrafficPolicy{} + if wrapperTrafficPolicy.PortTrafficPolicy != nil { + trafficPolicy.PortLevelSettings = []*networking.TrafficPolicy_PortTrafficPolicy{wrapperTrafficPolicy.PortTrafficPolicy} + } else if wrapperTrafficPolicy.TrafficPolicy != nil { + trafficPolicy = wrapperTrafficPolicy.TrafficPolicy + } dr = &common.WrapperDestinationRule{ DestinationRule: &networking.DestinationRule{ - Host: serviceName, - TrafficPolicy: &networking.TrafficPolicy{ - PortLevelSettings: []*networking.TrafficPolicy_PortTrafficPolicy{wrapperTrafficPolicy.TrafficPolicy}, - }, + Host: serviceName, + TrafficPolicy: trafficPolicy, }, WrapperConfig: wrapperTrafficPolicy.WrapperConfig, ServiceKey: key, } - } else { - dr.DestinationRule.TrafficPolicy.PortLevelSettings = append(dr.DestinationRule.TrafficPolicy.PortLevelSettings, wrapperTrafficPolicy.TrafficPolicy) + } else if wrapperTrafficPolicy.PortTrafficPolicy != nil { + dr.DestinationRule.TrafficPolicy.PortLevelSettings = append(dr.DestinationRule.TrafficPolicy.PortLevelSettings, wrapperTrafficPolicy.PortTrafficPolicy) } destinationRules[serviceName] = dr @@ -710,6 +719,7 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext if !obj.DefaultConfigDisable { result.PluginConfig = obj.DefaultConfig } + hasValidRule := false if len(obj.MatchRules) > 0 { if result.PluginConfig == nil { result.PluginConfig = &types.Struct{ @@ -769,14 +779,20 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext Kind: v, }) } - result.PluginConfig.Fields["_rules_"] = &types.Value{ - Kind: &types.Value_ListValue{ - ListValue: &types.ListValue{ - Values: ruleValues, + if len(ruleValues) > 0 { + hasValidRule = true + result.PluginConfig.Fields["_rules_"] = &types.Value{ + Kind: &types.Value_ListValue{ + ListValue: &types.ListValue{ + Values: ruleValues, + }, }, - }, + } } } + if !hasValidRule && obj.DefaultConfigDisable { + return nil, nil + } return result, nil } @@ -807,6 +823,14 @@ func (m *IngressConfig) AddOrUpdateWasmPlugin(clusterNamespacedName util.Cluster IngressLog.Errorf("invalid wasmPlugin:%s, err:%v", clusterNamespacedName.Name, err) return } + if istioWasmPlugin == nil { + IngressLog.Infof("wasmPlugin:%s will not be transferred to istio since config disabled", + clusterNamespacedName.Name) + m.mutex.Lock() + delete(m.wasmPlugins, clusterNamespacedName.Name) + m.mutex.Unlock() + return + } IngressLog.Debugf("wasmPlugin:%s convert to istioWasmPlugin:%v", clusterNamespacedName.Name, istioWasmPlugin) m.mutex.Lock() m.wasmPlugins[clusterNamespacedName.Name] = istioWasmPlugin diff --git a/pkg/ingress/kube/annotations/annotations.go b/pkg/ingress/kube/annotations/annotations.go index a64e49a528..ef2c6f294d 100644 --- a/pkg/ingress/kube/annotations/annotations.go +++ b/pkg/ingress/kube/annotations/annotations.go @@ -192,8 +192,8 @@ func (h *AnnotationHandlerManager) ApplyRoute(route *networking.HTTPRoute, confi } } -func (h *AnnotationHandlerManager) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) { +func (h *AnnotationHandlerManager) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy, portTrafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) { for _, handler := range h.trafficPolicyHandlers { - handler.ApplyTrafficPolicy(trafficPolicy, config) + handler.ApplyTrafficPolicy(trafficPolicy, portTrafficPolicy, config) } } diff --git a/pkg/ingress/kube/annotations/auth.go b/pkg/ingress/kube/annotations/auth.go index ccaea574a9..f9d0308fd4 100644 --- a/pkg/ingress/kube/annotations/auth.go +++ b/pkg/ingress/kube/annotations/auth.go @@ -135,6 +135,9 @@ func convertCredentials(secretType authSecretType, secret *corev1.Secret) ([]str } userList := strings.Split(string(users), "\n") for _, item := range userList { + if !strings.Contains(item, ":") { + continue + } result = append(result, item) } case authMapAuthSecretType: diff --git a/pkg/ingress/kube/annotations/canary.go b/pkg/ingress/kube/annotations/canary.go index 7b6f4b5ef2..ea39004abb 100644 --- a/pkg/ingress/kube/annotations/canary.go +++ b/pkg/ingress/kube/annotations/canary.go @@ -134,37 +134,41 @@ func ApplyByHeader(canary, route *networking.HTTPRoute, canaryIngress *Ingress) // Modified match base on by header if canaryConfig.Header != "" { - canary.Match[0].Headers = map[string]*networking.StringMatch{ - canaryConfig.Header: { - MatchType: &networking.StringMatch_Exact{ - Exact: "always", - }, - }, - } - if canaryConfig.HeaderValue != "" { - canary.Match[0].Headers = map[string]*networking.StringMatch{ + for _, match := range canary.Match { + match.Headers = map[string]*networking.StringMatch{ canaryConfig.Header: { - MatchType: &networking.StringMatch_Regex{ - Regex: "always|" + canaryConfig.HeaderValue, + MatchType: &networking.StringMatch_Exact{ + Exact: "always", }, }, } - } else if canaryConfig.HeaderPattern != "" { - canary.Match[0].Headers = map[string]*networking.StringMatch{ - canaryConfig.Header: { - MatchType: &networking.StringMatch_Regex{ - Regex: canaryConfig.HeaderPattern, + if canaryConfig.HeaderValue != "" { + match.Headers = map[string]*networking.StringMatch{ + canaryConfig.Header: { + MatchType: &networking.StringMatch_Regex{ + Regex: "always|" + canaryConfig.HeaderValue, + }, }, - }, + } + } else if canaryConfig.HeaderPattern != "" { + match.Headers = map[string]*networking.StringMatch{ + canaryConfig.Header: { + MatchType: &networking.StringMatch_Regex{ + Regex: canaryConfig.HeaderPattern, + }, + }, + } } } } else if canaryConfig.Cookie != "" { - canary.Match[0].Headers = map[string]*networking.StringMatch{ - "cookie": { - MatchType: &networking.StringMatch_Regex{ - Regex: "^(.\\*?;)?(" + canaryConfig.Cookie + "=always)(;.\\*)?$", + for _, match := range canary.Match { + match.Headers = map[string]*networking.StringMatch{ + "cookie": { + MatchType: &networking.StringMatch_Regex{ + Regex: "^(.\\*?;)?(" + canaryConfig.Cookie + "=always)(;.\\*)?$", + }, }, - }, + } } } diff --git a/pkg/ingress/kube/annotations/destination.go b/pkg/ingress/kube/annotations/destination.go index 1cddbf145f..9919ae4ec9 100644 --- a/pkg/ingress/kube/annotations/destination.go +++ b/pkg/ingress/kube/annotations/destination.go @@ -73,10 +73,14 @@ func (a destination) Parse(annotations Annotations, config *Ingress, _ *GlobalCo } address := pairs[addrIndex] host := address - var port string + var port uint64 colon := strings.LastIndex(address, ":") if colon != -1 { - host, port = address[:colon], address[colon+1:] + var err error + port, err = strconv.ParseUint(address[colon+1:], 10, 32) + if err == nil && port > 0 && port < 65536 { + host = address[:colon] + } } var subset string if len(pairs) >= addrIndex+2 { @@ -89,14 +93,9 @@ func (a destination) Parse(annotations Annotations, config *Ingress, _ *GlobalCo }, Weight: int32(weight), } - if port != "" { - portNumber, err := strconv.ParseUint(port, 10, 32) - if err != nil { - IngressLog.Errorf("destination addr %s has invalid port %s within ingress %s/%s", address, port, config.Namespace, config.Name) - return nil - } + if port > 0 { dest.Destination.Port = &networking.PortSelector{ - Number: uint32(portNumber), + Number: uint32(port), } } IngressLog.Debugf("destination generated for ingress %s/%s: %v", config.Namespace, config.Name, dest) diff --git a/pkg/ingress/kube/annotations/destination_test.go b/pkg/ingress/kube/annotations/destination_test.go index aead0606ec..871af0453d 100644 --- a/pkg/ingress/kube/annotations/destination_test.go +++ b/pkg/ingress/kube/annotations/destination_test.go @@ -84,6 +84,39 @@ func TestDestinationParse(t *testing.T) { WeightSum: 100, }, }, + { + input: Annotations{ + buildHigressAnnotationKey(destinationKey): "providers:com.alibaba.nacos.example.dubbo.service.DemoService:1.0.0:.DEFAULT-GROUP.public.nacos", + }, + expect: &DestinationConfig{ + McpDestination: []*networking.HTTPRouteDestination{ + { + Destination: &networking.Destination{ + Host: "providers:com.alibaba.nacos.example.dubbo.service.DemoService:1.0.0:.DEFAULT-GROUP.public.nacos", + }, + Weight: 100, + }, + }, + WeightSum: 100, + }, + }, + { + input: Annotations{ + buildHigressAnnotationKey(destinationKey): "providers:com.alibaba.nacos.example.dubbo.service.DemoService:1.0.0:.DEFAULT-GROUP.public.nacos:8080", + }, + expect: &DestinationConfig{ + McpDestination: []*networking.HTTPRouteDestination{ + { + Destination: &networking.Destination{ + Host: "providers:com.alibaba.nacos.example.dubbo.service.DemoService:1.0.0:.DEFAULT-GROUP.public.nacos", + Port: &networking.PortSelector{Number: 8080}, + }, + Weight: 100, + }, + }, + WeightSum: 100, + }, + }, } for _, testCase := range testCases { diff --git a/pkg/ingress/kube/annotations/interface.go b/pkg/ingress/kube/annotations/interface.go index e5dfbc6f26..26091379cb 100644 --- a/pkg/ingress/kube/annotations/interface.go +++ b/pkg/ingress/kube/annotations/interface.go @@ -38,5 +38,5 @@ type RouteHandler interface { type TrafficPolicyHandler interface { // ApplyTrafficPolicy parsed ingress annotation config reflected on traffic policy - ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) + ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy, portTrafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) } diff --git a/pkg/ingress/kube/annotations/loadbalance.go b/pkg/ingress/kube/annotations/loadbalance.go index 1936f1ede5..6376ba569a 100644 --- a/pkg/ingress/kube/annotations/loadbalance.go +++ b/pkg/ingress/kube/annotations/loadbalance.go @@ -136,14 +136,16 @@ func (l loadBalance) Parse(annotations Annotations, config *Ingress, _ *GlobalCo return nil } -func (l loadBalance) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) { +func (l loadBalance) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy, portTrafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) { loadBalanceConfig := config.LoadBalance if loadBalanceConfig == nil { return } + var loadBalancer *networking.LoadBalancerSettings + if loadBalanceConfig.cookie != nil { - trafficPolicy.LoadBalancer = &networking.LoadBalancerSettings{ + loadBalancer = &networking.LoadBalancerSettings{ LbPolicy: &networking.LoadBalancerSettings_ConsistentHash{ ConsistentHash: &networking.LoadBalancerSettings_ConsistentHashLB{ HashKey: &networking.LoadBalancerSettings_ConsistentHashLB_HttpCookie{ @@ -171,18 +173,25 @@ func (l loadBalance) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy_ }, } } - trafficPolicy.LoadBalancer = &networking.LoadBalancerSettings{ + loadBalancer = &networking.LoadBalancerSettings{ LbPolicy: &networking.LoadBalancerSettings_ConsistentHash{ ConsistentHash: consistentHash, }, } } else { - trafficPolicy.LoadBalancer = &networking.LoadBalancerSettings{ + loadBalancer = &networking.LoadBalancerSettings{ LbPolicy: &networking.LoadBalancerSettings_Simple{ Simple: loadBalanceConfig.simple, }, } } + + if trafficPolicy != nil { + trafficPolicy.LoadBalancer = loadBalancer + } + if portTrafficPolicy != nil { + portTrafficPolicy.LoadBalancer = loadBalancer + } } func isCookieAffinity(annotations Annotations) bool { diff --git a/pkg/ingress/kube/annotations/loadbalance_test.go b/pkg/ingress/kube/annotations/loadbalance_test.go index 6126ad2007..25dfd46bd4 100644 --- a/pkg/ingress/kube/annotations/loadbalance_test.go +++ b/pkg/ingress/kube/annotations/loadbalance_test.go @@ -229,7 +229,7 @@ func TestLoadBalanceApplyTrafficPolicy(t *testing.T) { for _, inputCase := range inputCases { t.Run("", func(t *testing.T) { - loadBalance.ApplyTrafficPolicy(inputCase.input, inputCase.config) + loadBalance.ApplyTrafficPolicy(nil, inputCase.input, inputCase.config) if !reflect.DeepEqual(inputCase.input, inputCase.expect) { t.Fatal("Should be equal") } diff --git a/pkg/ingress/kube/annotations/rewrite.go b/pkg/ingress/kube/annotations/rewrite.go index 8ddeedc729..825e0162b1 100644 --- a/pkg/ingress/kube/annotations/rewrite.go +++ b/pkg/ingress/kube/annotations/rewrite.go @@ -22,6 +22,7 @@ import ( ) const ( + rewritePath = "rewrite-path" rewriteTarget = "rewrite-target" useRegex = "use-regex" upstreamVhost = "upstream-vhost" @@ -38,6 +39,7 @@ type RewriteConfig struct { RewriteTarget string UseRegex bool RewriteHost string + RewritePath string } type rewrite struct{} @@ -51,8 +53,9 @@ func (r rewrite) Parse(annotations Annotations, config *Ingress, _ *GlobalContex rewriteConfig.RewriteTarget, _ = annotations.ParseStringASAP(rewriteTarget) rewriteConfig.UseRegex, _ = annotations.ParseBoolASAP(useRegex) rewriteConfig.RewriteHost, _ = annotations.ParseStringASAP(upstreamVhost) + rewriteConfig.RewritePath, _ = annotations.ParseStringForHigress(rewritePath) - if rewriteConfig.RewriteTarget != "" { + if rewriteConfig.RewritePath == "" && rewriteConfig.RewriteTarget != "" { // When rewrite target is present and not empty, // we will enforce regex match on all rules in this ingress. rewriteConfig.UseRegex = true @@ -68,12 +71,22 @@ func (r rewrite) Parse(annotations Annotations, config *Ingress, _ *GlobalContex func (r rewrite) ApplyRoute(route *networking.HTTPRoute, config *Ingress) { rewriteConfig := config.Rewrite if rewriteConfig == nil || (rewriteConfig.RewriteTarget == "" && - rewriteConfig.RewriteHost == "") { + rewriteConfig.RewriteHost == "" && rewriteConfig.RewritePath == "") { return } route.Rewrite = &networking.HTTPRewrite{} - if rewriteConfig.RewriteTarget != "" { + if rewriteConfig.RewritePath != "" { + route.Rewrite.Uri = rewriteConfig.RewritePath + for _, match := range route.Match { + if strings.HasSuffix(match.Uri.GetPrefix(), "/") { + if !strings.HasSuffix(route.Rewrite.Uri, "/") { + route.Rewrite.Uri += "/" + } + break + } + } + } else if rewriteConfig.RewriteTarget != "" { route.Rewrite.UriRegex = &networking.RegexMatchAndSubstitute{ Pattern: route.Match[0].Uri.GetRegex(), Substitution: rewriteConfig.RewriteTarget, @@ -102,5 +115,5 @@ func NeedRegexMatch(annotations map[string]string) bool { func needRewriteConfig(annotations Annotations) bool { return annotations.HasASAP(rewriteTarget) || annotations.HasASAP(useRegex) || - annotations.HasASAP(upstreamVhost) + annotations.HasASAP(upstreamVhost) || annotations.HasHigress(rewritePath) } diff --git a/pkg/ingress/kube/annotations/rewrite_test.go b/pkg/ingress/kube/annotations/rewrite_test.go index 6be98a93ce..a3f7690a0b 100644 --- a/pkg/ingress/kube/annotations/rewrite_test.go +++ b/pkg/ingress/kube/annotations/rewrite_test.go @@ -124,6 +124,14 @@ func TestRewriteParse(t *testing.T) { RewriteHost: "test.com", }, }, + { + input: Annotations{ + buildHigressAnnotationKey(rewritePath): "/test", + }, + expect: &RewriteConfig{ + RewritePath: "/test", + }, + }, } for _, testCase := range testCases { @@ -241,6 +249,87 @@ func TestRewriteApplyRoute(t *testing.T) { }, }, }, + { + config: &Ingress{ + Rewrite: &RewriteConfig{ + RewriteTarget: "/test", + RewritePath: "/test", + RewriteHost: "test.com", + }, + }, + input: &networking.HTTPRoute{ + Match: []*networking.HTTPMatchRequest{ + { + Uri: &networking.StringMatch{ + MatchType: &networking.StringMatch_Regex{ + Regex: "/hello", + }, + }, + }, + }, + }, + expect: &networking.HTTPRoute{ + Match: []*networking.HTTPMatchRequest{ + { + Uri: &networking.StringMatch{ + MatchType: &networking.StringMatch_Regex{ + Regex: "/hello", + }, + }, + }, + }, + Rewrite: &networking.HTTPRewrite{ + Uri: "/test", + Authority: "test.com", + }, + }, + }, + { + config: &Ingress{ + Rewrite: &RewriteConfig{ + RewritePath: "/test", + }, + }, + input: &networking.HTTPRoute{ + Match: []*networking.HTTPMatchRequest{ + { + Uri: &networking.StringMatch{ + MatchType: &networking.StringMatch_Prefix{ + Prefix: "/hello/", + }, + }, + }, + { + Uri: &networking.StringMatch{ + MatchType: &networking.StringMatch_Exact{ + Exact: "/hello", + }, + }, + }, + }, + }, + expect: &networking.HTTPRoute{ + Match: []*networking.HTTPMatchRequest{ + { + Uri: &networking.StringMatch{ + MatchType: &networking.StringMatch_Prefix{ + Prefix: "/hello/", + }, + }, + }, + { + Uri: &networking.StringMatch{ + MatchType: &networking.StringMatch_Exact{ + Exact: "/hello", + }, + }, + }, + }, + Rewrite: &networking.HTTPRewrite{ + Uri: "/test/", + }, + }, + }, } for _, inputCase := range inputCases { diff --git a/pkg/ingress/kube/annotations/upstreamtls.go b/pkg/ingress/kube/annotations/upstreamtls.go index 6f8e7c24a6..d9d2e43007 100644 --- a/pkg/ingress/kube/annotations/upstreamtls.go +++ b/pkg/ingress/kube/annotations/upstreamtls.go @@ -75,17 +75,6 @@ func (u upstreamTLS) Parse(annotations Annotations, config *Ingress, _ *GlobalCo } } - secretName, _ := annotations.ParseStringASAP(proxySSLSecret) - namespacedName := util.SplitNamespacedName(secretName) - if namespacedName.Name == "" { - return nil - } - - if namespacedName.Namespace == "" { - namespacedName.Namespace = config.Namespace - } - upstreamTLSConfig.SecretName = namespacedName.String() - if sslVerify, err := annotations.ParseStringASAP(proxySSLVerify); err == nil { if OnOffRegex.MatchString(sslVerify) { upstreamTLSConfig.SSLVerify = onOffToBool(sslVerify) @@ -96,22 +85,34 @@ func (u upstreamTLS) Parse(annotations Annotations, config *Ingress, _ *GlobalCo if enableSNI, err := annotations.ParseStringASAP(proxySSLServerName); err == nil { if OnOffRegex.MatchString(enableSNI) { - upstreamTLSConfig.SSLVerify = onOffToBool(enableSNI) + upstreamTLSConfig.EnableSNI = onOffToBool(enableSNI) } } + secretName, _ := annotations.ParseStringASAP(proxySSLSecret) + namespacedName := util.SplitNamespacedName(secretName) + if namespacedName.Name == "" { + return nil + } + + if namespacedName.Namespace == "" { + namespacedName.Namespace = config.Namespace + } + upstreamTLSConfig.SecretName = namespacedName.String() + return nil } -func (u upstreamTLS) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) { +func (u upstreamTLS) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy, portTrafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) { if config.UpstreamTLS == nil { return } upstreamTLSConfig := config.UpstreamTLS + var connectionPool *networking.ConnectionPoolSettings if isH2(upstreamTLSConfig.BackendProtocol) { - trafficPolicy.ConnectionPool = &networking.ConnectionPoolSettings{ + connectionPool = &networking.ConnectionPoolSettings{ Http: &networking.ConnectionPoolSettings_HTTPSettings{ H2UpgradePolicy: networking.ConnectionPoolSettings_HTTPSettings_UPGRADE, }, @@ -125,8 +126,14 @@ func (u upstreamTLS) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy_ } else if isHTTPS(upstreamTLSConfig.BackendProtocol) { tls = processSimple(config) } - - trafficPolicy.Tls = tls + if trafficPolicy != nil { + trafficPolicy.ConnectionPool = connectionPool + trafficPolicy.Tls = tls + } + if portTrafficPolicy != nil { + portTrafficPolicy.ConnectionPool = connectionPool + portTrafficPolicy.Tls = tls + } } func processMTLS(config *Ingress) *networking.ClientTLSSettings { diff --git a/pkg/ingress/kube/annotations/upstreamtls_test.go b/pkg/ingress/kube/annotations/upstreamtls_test.go index 6cff326479..c48247952d 100644 --- a/pkg/ingress/kube/annotations/upstreamtls_test.go +++ b/pkg/ingress/kube/annotations/upstreamtls_test.go @@ -47,6 +47,7 @@ func TestUpstreamTLSParse(t *testing.T) { SSLVerify: true, SNI: "SSLName", SecretName: "namespace/SSLSecret", + EnableSNI: true, }, }, { @@ -60,9 +61,10 @@ func TestUpstreamTLSParse(t *testing.T) { }, expect: &UpstreamTLSConfig{ BackendProtocol: "HTTP2", - SSLVerify: false, - SNI: "", + SSLVerify: true, + SNI: "SSLName", SecretName: "", + EnableSNI: true, }, }, } @@ -143,7 +145,7 @@ func TestApplyTrafficPolicy(t *testing.T) { for _, testCase := range testCases { t.Run("", func(t *testing.T) { - parser.ApplyTrafficPolicy(testCase.input, testCase.config) + parser.ApplyTrafficPolicy(nil, testCase.input, testCase.config) if diff := cmp.Diff(testCase.expect, testCase.input); diff != "" { t.Fatalf("TestApplyTrafficPolicy() mismatch (-want +got): \n%s", diff) } diff --git a/pkg/ingress/kube/common/controller.go b/pkg/ingress/kube/common/controller.go index 6f22da24a4..9ada17f746 100644 --- a/pkg/ingress/kube/common/controller.go +++ b/pkg/ingress/kube/common/controller.go @@ -28,9 +28,10 @@ import ( ) type ServiceKey struct { - Namespace string - Name string - Port int32 + Namespace string + Name string + ServiceFQDN string + Port int32 } type WrapperConfig struct { @@ -98,8 +99,9 @@ type WrapperVirtualService struct { } type WrapperTrafficPolicy struct { - TrafficPolicy *networking.TrafficPolicy_PortTrafficPolicy - WrapperConfig *WrapperConfig + TrafficPolicy *networking.TrafficPolicy + PortTrafficPolicy *networking.TrafficPolicy_PortTrafficPolicy + WrapperConfig *WrapperConfig } type WrapperDestinationRule struct { diff --git a/pkg/ingress/kube/ingress/controller.go b/pkg/ingress/kube/ingress/controller.go index 19bbc78711..887b0730d9 100644 --- a/pkg/ingress/kube/ingress/controller.go +++ b/pkg/ingress/kube/ingress/controller.go @@ -19,7 +19,6 @@ import ( "fmt" "path" "reflect" - "regexp" "sort" "strings" "sync" @@ -532,40 +531,25 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra Host: rule.Host, ClusterId: c.options.ClusterId, } - httpMatch := &networking.HTTPMatchRequest{} - path := httpPath.Path + var pathType common.PathType + originPath := httpPath.Path if wrapper.AnnotationsConfig.NeedRegexMatch() { - wrapperHttpRoute.OriginPathType = common.Regex - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Regex{Regex: httpPath.Path + ".*"}, - } + pathType = common.Regex } else { switch *httpPath.PathType { case ingress.PathTypeExact: - wrapperHttpRoute.OriginPathType = common.Exact - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Exact{Exact: httpPath.Path}, - } + pathType = common.Exact case ingress.PathTypePrefix: - wrapperHttpRoute.OriginPathType = common.Prefix - // borrow from implement of official istio code. - if path == "/" { - wrapperVS.ConfiguredDefaultBackend = true - // Optimize common case of / to not needed regex - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Prefix{Prefix: path}, - } - } else { - path = strings.TrimSuffix(path, "/") - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Regex{Regex: regexp.QuoteMeta(path) + common.PrefixMatchRegex}, - } + pathType = common.Prefix + if httpPath.Path != "/" { + originPath = strings.TrimSuffix(httpPath.Path, "/") } } } - wrapperHttpRoute.OriginPath = path - wrapperHttpRoute.HTTPRoute.Match = []*networking.HTTPMatchRequest{httpMatch} + wrapperHttpRoute.OriginPath = originPath + wrapperHttpRoute.OriginPathType = pathType + wrapperHttpRoute.HTTPRoute.Match = c.generateHttpMatches(pathType, httpPath.Path, wrapperVS) wrapperHttpRoute.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, wrapperHttpRoute) ingressRouteBuilder := convertOptions.IngressRouteCache.New(wrapperHttpRoute) @@ -748,46 +732,31 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w } for _, httpPath := range rule.HTTP.Paths { - path := httpPath.Path - canary := &common.WrapperHTTPRoute{ HTTPRoute: &networking.HTTPRoute{}, WrapperConfig: wrapper, Host: rule.Host, ClusterId: c.options.ClusterId, } - httpMatch := &networking.HTTPMatchRequest{} + var pathType common.PathType + originPath := httpPath.Path if wrapper.AnnotationsConfig.NeedRegexMatch() { - canary.OriginPathType = common.Regex - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Regex{Regex: httpPath.Path + ".*"}, - } + pathType = common.Regex } else { switch *httpPath.PathType { case ingress.PathTypeExact: - canary.OriginPathType = common.Exact - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Exact{Exact: httpPath.Path}, - } + pathType = common.Exact case ingress.PathTypePrefix: - canary.OriginPathType = common.Prefix - // borrow from implement of official istio code. - if path == "/" { - // Optimize common case of / to not needed regex - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Prefix{Prefix: path}, - } - } else { - path = strings.TrimSuffix(path, "/") - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Regex{Regex: regexp.QuoteMeta(path) + common.PrefixMatchRegex}, - } + pathType = common.Prefix + if httpPath.Path != "/" { + originPath = strings.TrimSuffix(httpPath.Path, "/") } } } - canary.OriginPath = path - canary.HTTPRoute.Match = []*networking.HTTPMatchRequest{httpMatch} + canary.OriginPath = originPath + canary.OriginPathType = pathType + canary.HTTPRoute.Match = c.generateHttpMatches(pathType, httpPath.Path, nil) canary.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, canary) ingressRouteBuilder := convertOptions.IngressRouteCache.New(canary) @@ -879,20 +848,9 @@ func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions, } if ingressV1Beta.Backend != nil { - serviceKey, err := c.createServiceKey(ingressV1Beta.Backend, cfg.Namespace) + err := c.storeBackendTrafficPolicy(wrapper, ingressV1Beta.Backend, convertOptions.Service2TrafficPolicy) if err != nil { - IngressLog.Errorf("ignore default service %s within ingress %s/%s", serviceKey.Name, cfg.Namespace, cfg.Name) - } else { - if _, exist := convertOptions.Service2TrafficPolicy[serviceKey]; !exist { - convertOptions.Service2TrafficPolicy[serviceKey] = &common.WrapperTrafficPolicy{ - TrafficPolicy: &networking.TrafficPolicy_PortTrafficPolicy{ - Port: &networking.PortSelector{ - Number: uint32(serviceKey.Port), - }, - }, - WrapperConfig: wrapper, - } - } + IngressLog.Errorf("ignore default service within ingress %s/%s, since error:%v", cfg.Namespace, cfg.Name, err) } } @@ -902,22 +860,46 @@ func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions, } for _, httpPath := range rule.HTTP.Paths { - if httpPath.Backend.ServiceName == "" { - continue - } - - serviceKey, err := c.createServiceKey(&httpPath.Backend, cfg.Namespace) + err := c.storeBackendTrafficPolicy(wrapper, &httpPath.Backend, convertOptions.Service2TrafficPolicy) if err != nil { - IngressLog.Errorf("ignore service %s within ingress %s/%s", serviceKey.Name, cfg.Namespace, cfg.Name) - continue + IngressLog.Errorf("ignore service within ingress %s/%s, since error:%v", cfg.Namespace, cfg.Name, err) } + } + } - if _, exist := convertOptions.Service2TrafficPolicy[serviceKey]; exist { - continue + return nil +} + +func (c *controller) storeBackendTrafficPolicy(wrapper *common.WrapperConfig, backend *ingress.IngressBackend, store map[common.ServiceKey]*common.WrapperTrafficPolicy) error { + if backend == nil { + return errors.New("invalid empty backend") + } + if common.ValidateBackendResource(backend.Resource) && wrapper.AnnotationsConfig.Destination != nil { + for _, dest := range wrapper.AnnotationsConfig.Destination.McpDestination { + serviceKey := common.ServiceKey{ + Namespace: "mcp", + Name: dest.Destination.Host, + ServiceFQDN: dest.Destination.Host, + } + if _, exist := store[serviceKey]; !exist { + store[serviceKey] = &common.WrapperTrafficPolicy{ + TrafficPolicy: &networking.TrafficPolicy{}, + WrapperConfig: wrapper, + } } + } + } else { + if backend.ServiceName == "" { + return nil + } + serviceKey, err := c.createServiceKey(backend, wrapper.Config.Namespace) + if err != nil { + return fmt.Errorf("ignore service %s within ingress %s/%s", serviceKey.Name, wrapper.Config.Namespace, wrapper.Config.Name) + } - convertOptions.Service2TrafficPolicy[serviceKey] = &common.WrapperTrafficPolicy{ - TrafficPolicy: &networking.TrafficPolicy_PortTrafficPolicy{ + if _, exist := store[serviceKey]; !exist { + store[serviceKey] = &common.WrapperTrafficPolicy{ + PortTrafficPolicy: &networking.TrafficPolicy_PortTrafficPolicy{ Port: &networking.PortSelector{ Number: uint32(serviceKey.Port), }, @@ -926,7 +908,6 @@ func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions, } } } - return nil } @@ -1180,6 +1161,42 @@ func (c *controller) shouldProcessIngressUpdate(ing *ingress.Ingress) (bool, err return preProcessed, nil } +func (c *controller) generateHttpMatches(pathType common.PathType, path string, wrapperVS *common.WrapperVirtualService) []*networking.HTTPMatchRequest { + var httpMatches []*networking.HTTPMatchRequest + + httpMatch := &networking.HTTPMatchRequest{} + switch pathType { + case common.Regex: + httpMatch.Uri = &networking.StringMatch{ + MatchType: &networking.StringMatch_Regex{Regex: path + ".*"}, + } + case common.Exact: + httpMatch.Uri = &networking.StringMatch{ + MatchType: &networking.StringMatch_Exact{Exact: path}, + } + case common.Prefix: + if path == "/" { + if wrapperVS != nil { + wrapperVS.ConfiguredDefaultBackend = true + } + // Optimize common case of / to not needed regex + httpMatch.Uri = &networking.StringMatch{ + MatchType: &networking.StringMatch_Prefix{Prefix: path}, + } + } else { + newPath := strings.TrimSuffix(path, "/") + httpMatches = append(httpMatches, c.generateHttpMatches(common.Exact, newPath, wrapperVS)...) + httpMatch.Uri = &networking.StringMatch{ + MatchType: &networking.StringMatch_Prefix{Prefix: newPath + "/"}, + } + } + } + + httpMatches = append(httpMatches, httpMatch) + + return httpMatches +} + // setDefaultMSEIngressOptionalField sets a default value for optional fields when is not defined. func setDefaultMSEIngressOptionalField(ing *ingress.Ingress) { if ing == nil { diff --git a/pkg/ingress/kube/ingressv1/controller.go b/pkg/ingress/kube/ingressv1/controller.go index cd04caaa87..7b5a2c6fe9 100644 --- a/pkg/ingress/kube/ingressv1/controller.go +++ b/pkg/ingress/kube/ingressv1/controller.go @@ -19,7 +19,6 @@ import ( "fmt" "path" "reflect" - "regexp" "sort" "strings" "sync" @@ -507,6 +506,7 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra } wrapperHttpRoutes := make([]*common.WrapperHTTPRoute, 0, len(rule.HTTP.Paths)) + for _, httpPath := range rule.HTTP.Paths { wrapperHttpRoute := &common.WrapperHTTPRoute{ HTTPRoute: &networking.HTTPRoute{}, @@ -514,40 +514,25 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra Host: rule.Host, ClusterId: c.options.ClusterId, } - httpMatch := &networking.HTTPMatchRequest{} - path := httpPath.Path + var pathType common.PathType + originPath := httpPath.Path if wrapper.AnnotationsConfig.NeedRegexMatch() { - wrapperHttpRoute.OriginPathType = common.Regex - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Regex{Regex: httpPath.Path + ".*"}, - } + pathType = common.Regex } else { switch *httpPath.PathType { case ingress.PathTypeExact: - wrapperHttpRoute.OriginPathType = common.Exact - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Exact{Exact: httpPath.Path}, - } + pathType = common.Exact case ingress.PathTypePrefix: - wrapperHttpRoute.OriginPathType = common.Prefix - // borrow from implement of official istio code. - if path == "/" { - wrapperVS.ConfiguredDefaultBackend = true - // Optimize common case of / to not needed regex - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Prefix{Prefix: path}, - } - } else { - path = strings.TrimSuffix(path, "/") - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Regex{Regex: regexp.QuoteMeta(path) + common.PrefixMatchRegex}, - } + pathType = common.Prefix + if httpPath.Path != "/" { + originPath = strings.TrimSuffix(httpPath.Path, "/") } } } - wrapperHttpRoute.OriginPath = path - wrapperHttpRoute.HTTPRoute.Match = []*networking.HTTPMatchRequest{httpMatch} + wrapperHttpRoute.OriginPath = originPath + wrapperHttpRoute.OriginPathType = pathType + wrapperHttpRoute.HTTPRoute.Match = c.generateHttpMatches(pathType, httpPath.Path, wrapperVS) wrapperHttpRoute.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, wrapperHttpRoute) ingressRouteBuilder := convertOptions.IngressRouteCache.New(wrapperHttpRoute) @@ -620,6 +605,42 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra return nil } +func (c *controller) generateHttpMatches(pathType common.PathType, path string, wrapperVS *common.WrapperVirtualService) []*networking.HTTPMatchRequest { + var httpMatches []*networking.HTTPMatchRequest + + httpMatch := &networking.HTTPMatchRequest{} + switch pathType { + case common.Regex: + httpMatch.Uri = &networking.StringMatch{ + MatchType: &networking.StringMatch_Regex{Regex: path + ".*"}, + } + case common.Exact: + httpMatch.Uri = &networking.StringMatch{ + MatchType: &networking.StringMatch_Exact{Exact: path}, + } + case common.Prefix: + if path == "/" { + if wrapperVS != nil { + wrapperVS.ConfiguredDefaultBackend = true + } + // Optimize common case of / to not needed regex + httpMatch.Uri = &networking.StringMatch{ + MatchType: &networking.StringMatch_Prefix{Prefix: path}, + } + } else { + newPath := strings.TrimSuffix(path, "/") + httpMatches = append(httpMatches, c.generateHttpMatches(common.Exact, newPath, wrapperVS)...) + httpMatch.Uri = &networking.StringMatch{ + MatchType: &networking.StringMatch_Prefix{Prefix: newPath + "/"}, + } + } + } + + httpMatches = append(httpMatches, httpMatch) + + return httpMatches +} + func (c *controller) ApplyDefaultBackend(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error { if wrapper.AnnotationsConfig.IsCanary() { return nil @@ -717,46 +738,31 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w } for _, httpPath := range rule.HTTP.Paths { - path := httpPath.Path - canary := &common.WrapperHTTPRoute{ HTTPRoute: &networking.HTTPRoute{}, WrapperConfig: wrapper, Host: rule.Host, ClusterId: c.options.ClusterId, } - httpMatch := &networking.HTTPMatchRequest{} + var pathType common.PathType + originPath := httpPath.Path if wrapper.AnnotationsConfig.NeedRegexMatch() { - canary.OriginPathType = common.Regex - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Regex{Regex: httpPath.Path + ".*"}, - } + pathType = common.Regex } else { switch *httpPath.PathType { case ingress.PathTypeExact: - canary.OriginPathType = common.Exact - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Exact{Exact: httpPath.Path}, - } + pathType = common.Exact case ingress.PathTypePrefix: - canary.OriginPathType = common.Prefix - // borrow from implement of official istio code. - if path == "/" { - // Optimize common case of / to not needed regex - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Prefix{Prefix: path}, - } - } else { - path = strings.TrimSuffix(path, "/") - httpMatch.Uri = &networking.StringMatch{ - MatchType: &networking.StringMatch_Regex{Regex: regexp.QuoteMeta(path) + common.PrefixMatchRegex}, - } + pathType = common.Prefix + if httpPath.Path != "/" { + originPath = strings.TrimSuffix(httpPath.Path, "/") } } } - canary.OriginPath = path - canary.HTTPRoute.Match = []*networking.HTTPMatchRequest{httpMatch} + canary.OriginPath = originPath + canary.OriginPathType = pathType + canary.HTTPRoute.Match = c.generateHttpMatches(pathType, httpPath.Path, nil) canary.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, canary) ingressRouteBuilder := convertOptions.IngressRouteCache.New(canary) @@ -819,6 +825,7 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w } else { convertOptions.IngressRouteCache.Update(targetRoute) } + } } return nil @@ -841,20 +848,9 @@ func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions, } if ingressV1.DefaultBackend != nil { - serviceKey, err := c.createServiceKey(ingressV1.DefaultBackend.Service, cfg.Namespace) + err := c.storeBackendTrafficPolicy(wrapper, ingressV1.DefaultBackend, convertOptions.Service2TrafficPolicy) if err != nil { - IngressLog.Errorf("ignore default service %s within ingress %s/%s", serviceKey.Name, cfg.Namespace, cfg.Name) - } else { - if _, exist := convertOptions.Service2TrafficPolicy[serviceKey]; !exist { - convertOptions.Service2TrafficPolicy[serviceKey] = &common.WrapperTrafficPolicy{ - TrafficPolicy: &networking.TrafficPolicy_PortTrafficPolicy{ - Port: &networking.PortSelector{ - Number: uint32(serviceKey.Port), - }, - }, - WrapperConfig: wrapper, - } - } + IngressLog.Errorf("ignore default service within ingress %s/%s, since error:%v", cfg.Namespace, cfg.Name, err) } } @@ -864,22 +860,46 @@ func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions, } for _, httpPath := range rule.HTTP.Paths { - if httpPath.Backend.Service == nil { - continue - } - - serviceKey, err := c.createServiceKey(httpPath.Backend.Service, cfg.Namespace) + err := c.storeBackendTrafficPolicy(wrapper, &httpPath.Backend, convertOptions.Service2TrafficPolicy) if err != nil { - IngressLog.Errorf("ignore service %s within ingress %s/%s", serviceKey.Name, cfg.Namespace, cfg.Name) - continue + IngressLog.Errorf("ignore service within ingress %s/%s, since error:%v", cfg.Namespace, cfg.Name, err) } + } + } - if _, exist := convertOptions.Service2TrafficPolicy[serviceKey]; exist { - continue + return nil +} + +func (c *controller) storeBackendTrafficPolicy(wrapper *common.WrapperConfig, backend *ingress.IngressBackend, store map[common.ServiceKey]*common.WrapperTrafficPolicy) error { + if backend == nil { + return errors.New("invalid empty backend") + } + if common.ValidateBackendResource(backend.Resource) && wrapper.AnnotationsConfig.Destination != nil { + for _, dest := range wrapper.AnnotationsConfig.Destination.McpDestination { + serviceKey := common.ServiceKey{ + Namespace: "mcp", + Name: dest.Destination.Host, + ServiceFQDN: dest.Destination.Host, } + if _, exist := store[serviceKey]; !exist { + store[serviceKey] = &common.WrapperTrafficPolicy{ + TrafficPolicy: &networking.TrafficPolicy{}, + WrapperConfig: wrapper, + } + } + } + } else { + if backend.Service == nil { + return nil + } + serviceKey, err := c.createServiceKey(backend.Service, wrapper.Config.Namespace) + if err != nil { + return fmt.Errorf("ignore service %s within ingress %s/%s", serviceKey.Name, wrapper.Config.Namespace, wrapper.Config.Name) + } - convertOptions.Service2TrafficPolicy[serviceKey] = &common.WrapperTrafficPolicy{ - TrafficPolicy: &networking.TrafficPolicy_PortTrafficPolicy{ + if _, exist := store[serviceKey]; !exist { + store[serviceKey] = &common.WrapperTrafficPolicy{ + PortTrafficPolicy: &networking.TrafficPolicy_PortTrafficPolicy{ Port: &networking.PortSelector{ Number: uint32(serviceKey.Port), }, @@ -888,7 +908,6 @@ func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions, } } } - return nil } diff --git a/pkg/ingress/kube/ingressv1/controller_test.go b/pkg/ingress/kube/ingressv1/controller_test.go index 3fd3107ea9..5930c2e0e1 100644 --- a/pkg/ingress/kube/ingressv1/controller_test.go +++ b/pkg/ingress/kube/ingressv1/controller_test.go @@ -17,6 +17,8 @@ package ingressv1 import ( "testing" + "github.com/google/go-cmp/cmp" + networking "istio.io/api/networking/v1alpha3" v1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -76,3 +78,38 @@ func TestShouldProcessIngressUpdate(t *testing.T) { t.Fatal("should be true") } } + +func TestGenerateHttpMatches(t *testing.T) { + c := controller{} + + tt := []struct { + pathType common.PathType + path string + expect []*networking.HTTPMatchRequest + }{ + { + pathType: common.Prefix, + path: "/foo", + expect: []*networking.HTTPMatchRequest{ + { + Uri: &networking.StringMatch{ + MatchType: &networking.StringMatch_Exact{Exact: "/foo"}, + }, + }, { + Uri: &networking.StringMatch{ + MatchType: &networking.StringMatch_Prefix{Prefix: "/foo/"}, + }, + }, + }, + }, + } + + for _, testcase := range tt { + httpMatches := c.generateHttpMatches(testcase.pathType, testcase.path, nil) + for idx, httpMatch := range httpMatches { + if diff := cmp.Diff(httpMatch, testcase.expect[idx]); diff != "" { + t.Errorf("generateHttpMatches() mismatch (-want +got):\n%s", diff) + } + } + } +} diff --git a/plugins/wasm-cpp/.bazelrc b/plugins/wasm-cpp/.bazelrc new file mode 100644 index 0000000000..1a351ed7b0 --- /dev/null +++ b/plugins/wasm-cpp/.bazelrc @@ -0,0 +1,7 @@ +build --config=clang +build:gcc --cxxopt=-std=c++17 + +build:clang --action_env=CC=clang --action_env=CXX=clang++ +build:clang --action_env=BAZEL_COMPILER=clang +build:clang --linkopt=-fuse-ld=lld +build:clang --cxxopt=-std=c++17 \ No newline at end of file diff --git a/plugins/wasm-cpp/common/BUILD b/plugins/wasm-cpp/common/BUILD index 8394d923f8..cccc72b1b3 100644 --- a/plugins/wasm-cpp/common/BUILD +++ b/plugins/wasm-cpp/common/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + cc_library( name = "common_util", hdrs = [ @@ -38,7 +52,7 @@ cc_library( "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_absl//absl/strings:str_format", - "@proxy_wasm_cpp_host//:lib", + "@proxy_wasm_cpp_host//:null_lib", ], ) diff --git a/plugins/wasm-cpp/common/http_util.cc b/plugins/wasm-cpp/common/http_util.cc index be12a3b1b7..320ed916c5 100644 --- a/plugins/wasm-cpp/common/http_util.cc +++ b/plugins/wasm-cpp/common/http_util.cc @@ -20,6 +20,8 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_split.h" +#include "common/common_util.h" + namespace Wasm::Common::Http { std::string_view stripPortFromHost(std::string_view request_host) { @@ -188,7 +190,7 @@ std::vector getAllOfHeader(std::string_view key) { std::vector result; auto headers = getRequestHeaderPairs()->pairs(); for (auto& header : headers) { - if (absl::EqualsIgnoreCase(header.first, key)) { + if (absl::EqualsIgnoreCase(Wasm::Common::stdToAbsl(header.first), Wasm::Common::stdToAbsl(key))) { result.push_back(std::string(header.second)); } } @@ -197,7 +199,7 @@ std::vector getAllOfHeader(std::string_view key) { void forEachCookie( std::string_view cookie_header, - const std::function& + const std::function& cookie_consumer) { auto cookie_headers = getAllOfHeader(cookie_header); @@ -223,7 +225,7 @@ void forEachCookie( v = v.substr(1, v.size() - 2); } - if (!cookie_consumer(k, v)) { + if (!cookie_consumer(Wasm::Common::abslToStd(k), Wasm::Common::abslToStd(v))) { return; } } @@ -263,7 +265,7 @@ std::string buildOriginalUri(std::optional max_path_length) { auto scheme = scheme_ptr->view(); auto host_ptr = getRequestHeader(Header::Host); auto host = host_ptr->view(); - return absl::StrCat(scheme, "://", host, final_path); + return absl::StrCat(Wasm::Common::stdToAbsl(scheme), "://", Wasm::Common::stdToAbsl(host), Wasm::Common::stdToAbsl(final_path)); } } // namespace Wasm::Common::Http diff --git a/plugins/wasm-cpp/common/regex.h b/plugins/wasm-cpp/common/regex.h index 0c10a07051..5071946d00 100644 --- a/plugins/wasm-cpp/common/regex.h +++ b/plugins/wasm-cpp/common/regex.h @@ -29,17 +29,20 @@ class CompiledGoogleReMatcher { bool do_program_size_check = true) : regex_(regex, re2::RE2::Quiet) { if (!regex_.ok()) { - throw std::runtime_error(regex_.error()); + error_ = regex_.error(); + return; } if (do_program_size_check) { const auto regex_program_size = static_cast(regex_.ProgramSize()); if (regex_program_size > 100) { - throw std::runtime_error("too complex regex: " + regex); + error_ = "too complex regex: " + regex; } } } + const std::string& error() const { return error_; } + bool match(std::string_view value) const { return re2::RE2::FullMatch(re2::StringPiece(value.data(), value.size()), regex_); @@ -56,6 +59,7 @@ class CompiledGoogleReMatcher { private: const re2::RE2 regex_; + std::string error_; }; } // namespace Wasm::Common::Regex diff --git a/plugins/wasm-cpp/common/route_rule_matcher.h b/plugins/wasm-cpp/common/route_rule_matcher.h index 61e5f9e13a..506af4b4b2 100644 --- a/plugins/wasm-cpp/common/route_rule_matcher.h +++ b/plugins/wasm-cpp/common/route_rule_matcher.h @@ -126,6 +126,12 @@ class RouteRuleMatcher { LOG_DEBUG("no match config"); return true; } + if (!config.second && global_auth_ && !global_auth_.value()) { + // No allow set, means no need to check auth if global_auth is false + LOG_DEBUG( + "no allow set found, and global auth is false, no need to auth"); + return true; + } return checkPlugin(config.first.value(), config.second); } @@ -220,8 +226,9 @@ class RouteRuleMatcher { break; } } - return is_matched ? std::make_pair(match_config, allow_set) - : std::make_pair(std::nullopt, std::nullopt); + return is_matched || (global_auth_ && global_auth_.value()) + ? std::make_pair(match_config, allow_set) + : std::make_pair(std::nullopt, std::nullopt); } void setEmptyGlobalConfig() { global_config_ = PluginConfig{}; } @@ -288,6 +295,18 @@ class RouteRuleMatcher { has_rules = true; key_count--; } + auto auth_it = config.find("global_auth"); + if (auth_it != config.end()) { + auto global_auth_value = JsonValueAs(auth_it.value()); + if (global_auth_value.second != + Wasm::Common::JsonParserResultDetail::OK || + !global_auth_value.first) { + LOG_WARN( + "failed to parse 'global_auth' field in filter configuration."); + return false; + } + global_auth_ = global_auth_value.first.value(); + } PluginConfig plugin_config; // has other config fields if (key_count > 0 && parsePluginConfig(config, plugin_config)) { @@ -455,6 +474,7 @@ class RouteRuleMatcher { } bool invalid_config_ = false; + std::optional global_auth_ = std::nullopt; std::vector rule_config_; std::vector auth_rule_config_; std::optional global_config_ = std::nullopt; diff --git a/plugins/wasm-cpp/extensions/basic_auth/BUILD b/plugins/wasm-cpp/extensions/basic_auth/BUILD index 79b6ff000c..d36baab029 100644 --- a/plugins/wasm-cpp/extensions/basic_auth/BUILD +++ b/plugins/wasm-cpp/extensions/basic_auth/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -31,7 +45,7 @@ cc_library( visibility = ["//visibility:public"], alwayslink = 1, deps = [ - "//common:rule_util", + "//common:rule_util_nullvm", "//common:json_util", "//common:crypto_util", "@com_google_absl//absl/strings", diff --git a/plugins/wasm-cpp/extensions/basic_auth/plugin.cc b/plugins/wasm-cpp/extensions/basic_auth/plugin.cc index 86baf75f7e..4db843f271 100644 --- a/plugins/wasm-cpp/extensions/basic_auth/plugin.cc +++ b/plugins/wasm-cpp/extensions/basic_auth/plugin.cc @@ -308,8 +308,7 @@ bool PluginRootContext::onConfigure(size_t size) { // Parse configuration JSON string. if (size > 0 && !configure(size)) { LOG_WARN("configuration has errors initialization will not continue."); - setInvalidConfig(); - return true; + return false; } return true; } diff --git a/plugins/wasm-cpp/extensions/basic_auth/plugin_test.cc b/plugins/wasm-cpp/extensions/basic_auth/plugin_test.cc index b6ee7d415c..def1fdb2ba 100644 --- a/plugins/wasm-cpp/extensions/basic_auth/plugin_test.cc +++ b/plugins/wasm-cpp/extensions/basic_auth/plugin_test.cc @@ -909,7 +909,8 @@ TEST_F(BasicAuthTest, GlobalDeny) { } TEST_F(BasicAuthTest, GlobalWithConsumerDeny) { - std::string configuration = R"( + { + std::string configuration = R"( { "consumers" : [ {"credential" : "ok:test", "name" : "consumer_ok"}, @@ -932,36 +933,171 @@ TEST_F(BasicAuthTest, GlobalWithConsumerDeny) { } ] })"; - BufferBase buffer; - buffer.set({configuration.data(), configuration.size()}); + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); - EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) - .WillOnce([&buffer](WasmBufferType) { return &buffer; }); - EXPECT_TRUE(root_context_->configure(configuration.size())); + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); - cred_ = "wrong-cred"; - route_name_ = "config"; - authorization_header_ = "Basic " + Base64::encode(cred_.data(), cred_.size()); - EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, - testing::_, testing::_)); - EXPECT_EQ(context_->onRequestHeaders(0, false), - FilterHeadersStatus::StopIteration); + cred_ = "wrong-cred"; + route_name_ = "not match"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); + + cred_ = "wrong-cred"; + route_name_ = "config"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + + authority_ = "www.example.com"; + cred_ = "admin2:admin2"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + + route_name_ = "config"; + cred_ = "admin4:admin4"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + } + { + std::string configuration = R"( +{ + "global_auth": true, + "consumers" : [ + {"credential" : "ok:test", "name" : "consumer_ok"}, + {"credential" : "admin2:admin2", "name" : "consumer2"}, + {"credential" : "admin:admin", "name" : "consumer"} + ], + "_rules_" : [ + { + "_match_route_" : ["test", "config"], + "consumers" : [ + {"credential" : "admin3:admin3", "name" : "consumer3"}, + {"credential" : "YWRtaW41OmFkbWluNQ==", "name" : "consumer5"} + ] + }, + { + "_match_domain_" : ["test.com", "*.example.com"], + "consumers" : [ + {"credential" : "admin4:admin4", "name" : "consumer4"} + ] + } + ] +})"; + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); - authority_ = "www.example.com"; - cred_ = "admin2:admin2"; - authorization_header_ = "Basic " + Base64::encode(cred_.data(), cred_.size()); - EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, - testing::_, testing::_)); - EXPECT_EQ(context_->onRequestHeaders(0, false), - FilterHeadersStatus::StopIteration); + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); - route_name_ = "config"; - cred_ = "admin4:admin4"; - authorization_header_ = "Basic " + Base64::encode(cred_.data(), cred_.size()); - EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, - testing::_, testing::_)); - EXPECT_EQ(context_->onRequestHeaders(0, false), - FilterHeadersStatus::StopIteration); + cred_ = "wrong-cred"; + route_name_ = "not match"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + + cred_ = "wrong-cred"; + route_name_ = "config"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + + authority_ = "www.example.com"; + cred_ = "admin2:admin2"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + + route_name_ = "config"; + cred_ = "admin4:admin4"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + } +} + +TEST_F(BasicAuthTest, OnConfigureNoRulesAuth) { + // enable global auth + { + std::string configuration = R"( +{ + "consumers" : [ + {"credential" : "getuser1:123456", "name" : "consumer1"} + ] +})"; + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); + + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); + cred_ = "admin:admin"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_CALL(*mock_context_, sendLocalResponse(401, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + cred_ = "getuser1:123456"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); + } + // disable global auth + { + std::string configuration = R"( +{ + "consumers" : [ + {"credential" : "getuser1:123456", "name" : "consumer1"} + ], + "global_auth": false +})"; + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); + + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); + cred_ = "admin:admin"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); + cred_ = "getuser1:123456"; + authorization_header_ = + "Basic " + Base64::encode(cred_.data(), cred_.size()); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); + } } } // namespace basic_auth diff --git a/plugins/wasm-cpp/extensions/bot_detect/BUILD b/plugins/wasm-cpp/extensions/bot_detect/BUILD index baee11c977..e5ba81c26b 100644 --- a/plugins/wasm-cpp/extensions/bot_detect/BUILD +++ b/plugins/wasm-cpp/extensions/bot_detect/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -11,10 +25,10 @@ wasm_cc_binary( "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "//common:json_util", - "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", "//common:http_util", "//common:regex_util", "//common:rule_util", + "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", ], ) @@ -31,9 +45,9 @@ cc_library( "@com_google_absl//absl/strings", "//common:json_util", "@proxy_wasm_cpp_host//:lib", - "//common:http_util", + "//common:http_util_nullvm", "//common:regex_util", - "//common:rule_util", + "//common:rule_util_nullvm", ], ) diff --git a/plugins/wasm-cpp/extensions/bot_detect/plugin.cc b/plugins/wasm-cpp/extensions/bot_detect/plugin.cc index 3b011f4bb2..0d4efdd424 100644 --- a/plugins/wasm-cpp/extensions/bot_detect/plugin.cc +++ b/plugins/wasm-cpp/extensions/bot_detect/plugin.cc @@ -78,13 +78,13 @@ bool PluginRootContext::parsePluginConfig(const json& configuration, LOG_WARN("cannot parse allow"); return false; } - try { - rule.allow.push_back( - std::make_unique(regex.first.value())); - } catch (const std::runtime_error& e) { - LOG_WARN(e.what()); + auto re = std::make_unique(regex.first.value()); + if (!re->error().empty()) { + LOG_WARN(re->error()); return false; } + rule.allow.push_back(std::move(re)); + return true; })) { LOG_WARN("failed to parse configuration for allow."); @@ -96,12 +96,13 @@ bool PluginRootContext::parsePluginConfig(const json& configuration, LOG_WARN("cannot parse deny"); return false; } - try { - rule.deny.push_back(std::make_unique(regex.first.value())); - } catch (const std::runtime_error& e) { - LOG_WARN(e.what()); + auto re = std::make_unique(regex.first.value()); + if (!re->error().empty()) { + LOG_WARN(re->error()); return false; } + rule.deny.push_back(std::move(re)); + return true; })) { LOG_WARN("failed to parse configuration for deny."); @@ -114,8 +115,7 @@ bool PluginRootContext::onConfigure(size_t size) { // Parse configuration JSON string. if (size > 0 && !configure(size)) { LOG_WARN("configuration has errors initialization will not continue."); - setInvalidConfig(); - return true; + return false; } if (size == 0) { // support empty config diff --git a/plugins/wasm-cpp/extensions/custom_response/BUILD b/plugins/wasm-cpp/extensions/custom_response/BUILD index 162eaf1255..d6202d7b08 100644 --- a/plugins/wasm-cpp/extensions/custom_response/BUILD +++ b/plugins/wasm-cpp/extensions/custom_response/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -11,9 +25,9 @@ wasm_cc_binary( "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "//common:json_util", - "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", "//common:http_util", "//common:rule_util", + "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", ], ) diff --git a/plugins/wasm-cpp/extensions/custom_response/plugin.cc b/plugins/wasm-cpp/extensions/custom_response/plugin.cc index dbe0259a23..fc62034e3b 100644 --- a/plugins/wasm-cpp/extensions/custom_response/plugin.cc +++ b/plugins/wasm-cpp/extensions/custom_response/plugin.cc @@ -149,8 +149,7 @@ bool PluginRootContext::onConfigure(size_t size) { // Parse configuration JSON string. if (size > 0 && !configure(size)) { LOG_WARN("configuration has errors initialization will not continue."); - setInvalidConfig(); - return true; + return false; } return true; } diff --git a/plugins/wasm-cpp/extensions/hmac_auth/BUILD b/plugins/wasm-cpp/extensions/hmac_auth/BUILD index a37fe21ec7..9fd9ad93b3 100644 --- a/plugins/wasm-cpp/extensions/hmac_auth/BUILD +++ b/plugins/wasm-cpp/extensions/hmac_auth/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -13,10 +27,10 @@ wasm_cc_binary( "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/time", "//common:json_util", - "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", "//common:crypto_util", "//common:http_util", "//common:rule_util", + "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", ], ) @@ -37,8 +51,8 @@ cc_library( "//common:json_util", "@proxy_wasm_cpp_host//:lib", "//common:crypto_util", - "//common:http_util", - "//common:rule_util", + "//common:http_util_nullvm", + "//common:rule_util_nullvm", ], ) diff --git a/plugins/wasm-cpp/extensions/hmac_auth/plugin.cc b/plugins/wasm-cpp/extensions/hmac_auth/plugin.cc index 8505754258..b72290114e 100644 --- a/plugins/wasm-cpp/extensions/hmac_auth/plugin.cc +++ b/plugins/wasm-cpp/extensions/hmac_auth/plugin.cc @@ -389,8 +389,7 @@ bool PluginRootContext::onConfigure(size_t size) { // Parse configuration JSON string. if (size > 0 && !configure(size)) { LOG_WARN("configuration has errors initialization will not continue."); - setInvalidConfig(); - return true; + return false; } return true; } diff --git a/plugins/wasm-cpp/extensions/jwt_auth/BUILD b/plugins/wasm-cpp/extensions/jwt_auth/BUILD index 729bc5289d..c960158a15 100644 --- a/plugins/wasm-cpp/extensions/jwt_auth/BUILD +++ b/plugins/wasm-cpp/extensions/jwt_auth/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -17,9 +31,9 @@ wasm_cc_binary( "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/time", "//common:json_util", - "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", "//common:http_util", "//common:rule_util", + "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", ], ) diff --git a/plugins/wasm-cpp/extensions/jwt_auth/plugin.cc b/plugins/wasm-cpp/extensions/jwt_auth/plugin.cc index 93fd8e3c5f..d79d272c7b 100644 --- a/plugins/wasm-cpp/extensions/jwt_auth/plugin.cc +++ b/plugins/wasm-cpp/extensions/jwt_auth/plugin.cc @@ -135,11 +135,16 @@ bool PluginRootContext::parsePluginConfig(const json& configuration, [&](const json& from_header) -> bool { JSON_FIND_FIELD(from_header, name); JSON_FIELD_VALUE_AS(std::string, from_header, name); - JSON_FIND_FIELD(from_header, value_prefix); - JSON_FIELD_VALUE_AS(std::string, from_header, - value_prefix); - from_headers.push_back(FromHeader{ - from_header_name, from_header_value_prefix}); + std::string header_value_prefix; + auto from_header_value_prefix_json = + from_header.find("value_prefix"); + if (from_header_value_prefix_json != from_header.end()) { + JSON_FIELD_VALUE_AS(std::string, from_header, + value_prefix); + header_value_prefix = from_header_value_prefix; + } + from_headers.push_back( + FromHeader{from_header_name, header_value_prefix}); return true; })) { LOG_WARN("failed to parse 'from_headers' in consumer: " + @@ -229,6 +234,18 @@ bool PluginRootContext::parsePluginConfig(const json& configuration, LOG_INFO("at least one consumer has to be configured for a rule."); return false; } + std::vector enable_headers; + if (!JsonArrayIterate(configuration, "enable_headers", + [&](const json& enable_header_json) -> bool { + JSON_VALUE_AS(std::string, enable_header_json, + enable_header, "invalid item"); + enable_headers.push_back(enable_header); + return true; + })) { + LOG_WARN("failed to parse 'enable_headers'"); + return false; + } + rule.enable_headers = std::move(enable_headers); return true; } @@ -307,6 +324,20 @@ Status PluginRootContext::consumerVerify( bool PluginRootContext::checkPlugin( const JwtAuthConfigRule& rule, const std::optional>& allow_set) { + if (!rule.enable_headers.empty()) { + bool skip_auth = true; + for (const auto& enable_header : rule.enable_headers) { + auto header_ptr = getRequestHeader(enable_header); + if (header_ptr->size() > 0) { + LOG_DEBUG("enable by header: " + header_ptr->toString()); + skip_auth = false; + break; + } + } + if (skip_auth) { + return true; + } + } std::optional err_status; bool verified = false; uint64_t now = getCurrentTimeNanoseconds() / 1e9; @@ -354,8 +385,7 @@ bool PluginRootContext::onConfigure(size_t size) { // Parse configuration JSON string. if (size > 0 && !configure(size)) { LOG_WARN("configuration has errors initialization will not continue."); - setInvalidConfig(); - return true; + return false; } return true; } diff --git a/plugins/wasm-cpp/extensions/jwt_auth/plugin.h b/plugins/wasm-cpp/extensions/jwt_auth/plugin.h index aff839cbec..f81475d309 100644 --- a/plugins/wasm-cpp/extensions/jwt_auth/plugin.h +++ b/plugins/wasm-cpp/extensions/jwt_auth/plugin.h @@ -73,6 +73,7 @@ struct Consumer { struct JwtAuthConfigRule { std::vector consumers; + std::vector enable_headers; }; // PluginRootContext is the root context for all streams processed by the diff --git a/plugins/wasm-cpp/extensions/jwt_auth/plugin_test.cc b/plugins/wasm-cpp/extensions/jwt_auth/plugin_test.cc index 5b64a920a7..4fdfd9e3a4 100644 --- a/plugins/wasm-cpp/extensions/jwt_auth/plugin_test.cc +++ b/plugins/wasm-cpp/extensions/jwt_auth/plugin_test.cc @@ -84,6 +84,9 @@ class JwtAuthTest : public ::testing::Test { if (header == "Authorization") { *result = jwt_header_; } + if (header == "x-custom-header") { + *result = custom_header_; + } return WasmResult::Ok; }); ON_CALL(*mock_context_, addHeaderMapValue(WasmHeaderMapType::RequestHeaders, @@ -118,6 +121,7 @@ class JwtAuthTest : public ::testing::Test { std::string authority_; std::string route_name_; std::string jwt_header_; + std::string custom_header_; uint64_t current_time_; }; @@ -146,7 +150,8 @@ TEST_F(JwtAuthTest, RSA) { } TEST_F(JwtAuthTest, OCT) { - std::string configuration = R"( + { + std::string configuration = R"( { "consumers": [ { @@ -156,17 +161,65 @@ TEST_F(JwtAuthTest, OCT) { } ] })"; - BufferBase buffer; - buffer.set({configuration.data(), configuration.size()}); + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); - EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) - .WillOnce([&buffer](WasmBufferType) { return &buffer; }); - EXPECT_TRUE(root_context_->configure(configuration.size())); - current_time_ = 1665673819 * 1e9; - jwt_header_ = - R"(Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxNjY1NjczODE5fQ.7BVJOAobz_xYjsenu_CsYhYbgF1gMcqZSpaeQ8HwKmc)"; - EXPECT_EQ(context_->onRequestHeaders(0, false), - FilterHeadersStatus::Continue); + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); + current_time_ = 1665673819 * 1e9; + jwt_header_ = + R"(Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxNjY1NjczODE5fQ.7BVJOAobz_xYjsenu_CsYhYbgF1gMcqZSpaeQ8HwKmc)"; + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); + } + { + std::string configuration = R"( +{ + "consumers": [ + { + "name": "consumer-2", + "issuer": "abcd", + "jwks": "{\"keys\":[{\"kty\":\"oct\",\"kid\":\"123\",\"k\":\"hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew\",\"alg\":\"HS256\"}]}" + } + ] +})"; + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); + + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); + current_time_ = 1665673819 * 1e9; + jwt_header_ = + R"(Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxNjY1NjczODE5fQ.7BVJOAobz_xYjsenu_CsYhYbgF1gMcqZSpaeQ8HwKm1)"; + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + } + { + std::string configuration = R"( +{ + "consumers": [ + { + "name": "consumer-2", + "issuer": "abcd", + "jwks": "{\"keys\":[{\"kty\":\"oct\",\"kid\":\"123\",\"k\":\"hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew\",\"alg\":\"HS256\"}]}" + } + ], + "global_auth": false +})"; + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); + + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); + current_time_ = 1665673819 * 1e9; + jwt_header_ = + R"(Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxNjY1NjczODE5fQ.7BVJOAobz_xYjsenu_CsYhYbgF1gMcqZSpaeQ8HwKm1)"; + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); + } } TEST_F(JwtAuthTest, AuthZ) { @@ -264,6 +317,97 @@ TEST_F(JwtAuthTest, ClaimToHeader) { FilterHeadersStatus::Continue); } +TEST_F(JwtAuthTest, CustomHeader) { + std::string configuration = R"( +{ + "consumers": [ + { + "name": "consumer-2", + "issuer": "abcd", + "from_headers": [ + { + "name": "x-custom-header", + "value_prefix": "token " + }, + { + "name": "Authorization" + } + ], + "jwks": "{\"keys\":[{\"kty\":\"oct\",\"kid\":\"123\",\"k\":\"hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew\",\"alg\":\"HS256\"}]}" + } + ] +})"; + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); + + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); + custom_header_ = + R"(token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxNjY1NjczODE5fQ.7BVJOAobz_xYjsenu_CsYhYbgF1gMcqZSpaeQ8HwKmc)"; + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); + custom_header_.clear(); + jwt_header_ = + R"(eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxNjY1NjczODE5fQ.7BVJOAobz_xYjsenu_CsYhYbgF1gMcqZSpaeQ8HwKmc)"; + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); +} + +TEST_F(JwtAuthTest, SkipAuthHeader) { + std::string configuration = R"( +{ + "consumers": [ + { + "name": "consumer-1", + "issuer": "abc", + "jwks": "{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"123\",\"alg\":\"RS256\",\"n\":\"i0B67f1jggT9QJlZ_8QL9QQ56LfurrqDhpuu8BxtVcfxrYmaXaCtqTn7OfCuca7cGHdrJIjq99rz890NmYFZuvhaZ-LMt2iyiSb9LZJAeJmHf7ecguXS_-4x3hvbsrgUDi9tlg7xxbqGYcrco3anmalAFxsbswtu2PAXLtTnUo6aYwZsWA6ksq4FL3-anPNL5oZUgIp3HGyhhLTLdlQcC83jzxbguOim-0OEz-N4fniTYRivK7MlibHKrJfO3xa_6whBS07HW4Ydc37ZN3Rx9Ov3ZyV0idFblU519nUdqp_inXj1eEpynlxH60Ys_aTU2POGZh_25KXGdF_ZC_MSRw\"}]}" + }, + { + "name": "consumer-2", + "issuer": "abcd", + "jwks": "{\"keys\":[{\"kty\":\"oct\",\"kid\":\"123\",\"k\":\"hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew\",\"alg\":\"HS256\"}]}" + } + ], + "enable_headers": ["x-custom-header"], + "_rules_": [{ + "_match_route_": [ + "test1" + ], + "allow": [ + "consumer-1" + ] + }, + { + "_match_route_": [ + "test2" + ], + "allow": [ + "consumer-2" + ] + } + ] +})"; + BufferBase buffer; + buffer.set({configuration.data(), configuration.size()}); + + EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration)) + .WillOnce([&buffer](WasmBufferType) { return &buffer; }); + EXPECT_TRUE(root_context_->configure(configuration.size())); + current_time_ = 1665673819 * 1e9; + jwt_header_ = + R"(Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxNjY1NjczODE5fQ.7BVJOAobz_xYjsenu_CsYhYbgF1gMcqZSpaeQ8HwKmc)"; + route_name_ = "test1"; + custom_header_ = "123"; + EXPECT_CALL(*mock_context_, sendLocalResponse(403, testing::_, testing::_, + testing::_, testing::_)); + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::StopIteration); + custom_header_ = ""; + EXPECT_EQ(context_->onRequestHeaders(0, false), + FilterHeadersStatus::Continue); +} + } // namespace jwt_auth } // namespace null_plugin } // namespace proxy_wasm diff --git a/plugins/wasm-cpp/extensions/key_auth/BUILD b/plugins/wasm-cpp/extensions/key_auth/BUILD index bac6841e6f..8668bc5fe8 100644 --- a/plugins/wasm-cpp/extensions/key_auth/BUILD +++ b/plugins/wasm-cpp/extensions/key_auth/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -12,9 +26,9 @@ wasm_cc_binary( "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "//common:json_util", - "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", "//common:http_util", "//common:rule_util", + "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", ], ) @@ -33,8 +47,8 @@ cc_library( "@com_google_absl//absl/time", "//common:json_util", "@proxy_wasm_cpp_host//:lib", - "//common:http_util", - "//common:rule_util", + "//common:http_util_nullvm", + "//common:rule_util_nullvm", ], ) diff --git a/plugins/wasm-cpp/extensions/key_auth/README_EN.md b/plugins/wasm-cpp/extensions/key_auth/README_EN.md new file mode 100644 index 0000000000..45a4926456 --- /dev/null +++ b/plugins/wasm-cpp/extensions/key_auth/README_EN.md @@ -0,0 +1,123 @@ +# Features +The `key-auth` plug-in implements the authentication function based on the API Key, supports parsing the API Key from the URL parameter or request header of the HTTP request, and verifies whether the API Key has permission to access. + +# Configuration field + +| Name | Data Type | Parameter requirements | Default| Description | +| ----------- | --------------- | -------------------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------- | +| `consumers` | array of object | Required | - | Configure the caller of the service to authenticate the request. | +| `keys` | array of string | Required | - | The name of the source field of the API Key, which can be a URL parameter or an HTTP request header name. | +| `in_query` | bool | At least one of `in_query` and `in_header` must be true. | true | When configured true, the gateway will try to parse the API Key from the URL parameters. | +| `in_header` | bool | The same as above. | true | The same as above. | +| `_rules_` | array of object | Optional | - | Configure the access list of a specific route or domain name for authenticating requests. | + + +The configuration fields of each item in `consumers` are described as follows: + +| Name | Data Type | Parameter requirements | Default | Description | +| ------------ | --------- | -----------------------| ------ | ------------------------------------------- | +| `credential` | string | Required | - | Configure the consumer's access credentials. | +| `name` | string | Required | - | Configure the name of the consumer. | + +The configuration fields of each item in `_rules_` are described as follows: + +| Name | Data Type | Parameter requirements | Default| Description | +| ---------------- | --------------- | --------------------------------------------------------------------- | ------ | -------------------------------------------------- | +| `_match_route_` | array of string | Optional,Optionally fill in one of `_match_route_`, `_match_domain_`. | - | Configure the route name to match. | +| `_match_domain_` | array of string | Optional,Optionally fill in one of `_match_route_`, `_match_domain_`. | - | Configure the domain name to match. | +| `allow` | array of string | Required | - | For requests that meet the matching conditions, configure the name of the consumer that is allowed to access. | + +**Warning:** +- If the `_rules_` field is not configured, authentication will be enabled for all routes of the current gateway instance by default; +- For a request that passes authentication, an `X-Mse-Consumer` field will be added to the request header to identify the name of the caller. + +# Example configuration + +## Enabled for specific routes or domains + +The following configuration will enable Key Auth authentication and authentication for gateway-specific routes or domain names. Note that the `credential` field can not be repeated. + +```yaml +consumers: +- credential: 2bda943c-ba2b-11ec-ba07-00163e1250b5 + name: consumer1 +- credential: c8c8e9ca-558e-4a2d-bb62-e700dcc40e35 + name: consumer2 +keys: +- apikey +in_query: true +# Use the _rules_ field for fine-grained rule configuration +_rules_: +# Rule 1: Match by route name to take effect +- _match_route_: + - route-a + - route-b + allow: + - consumer1 +# Rule 2: Take effect by domain name matching +- _match_domain_: + - "*.example.com" + - test.com + allow: + - consumer2 +``` + +The `route-a` and `route-b` specified in `_match_route_` in this example are the route names filled in when creating the gateway route. When these two routes are matched, calls whose `name` is `consumer1` will be allowed Access by callers, other callers are not allowed to access; + +`*.example.com` and `test.com` specified in `_match_domain_` in this example are used to match the domain name of the request. When the domain name matches, the caller whose `name` is `consumer2` will be allowed to access, and other calls access is not allowed. + +### Depending on this configuration, the following requests would allow access: + +Assume that the following request will match the route-a route: + +**Set the API Key in the url parameter** +```bash +curl http://xxx.hello.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5 +``` +**Set the API Key in the http request header** +```bash +curl http://xxx.hello.com/test -H 'x-api-key: 2bda943c-ba2b-11ec-ba07-00163e1250b5' +``` + +After the authentication is passed, an `X-Mse-Consumer` field will be added to the header of the request. In this example, its value is `consumer1`, which is used to identify the name of the caller. + +### The following requests will deny access: + +**The request does not provide an API Key, return 401** +```bash +curl http://xxx.hello.com/test +``` +**The API Key provided by the request is not authorized to access, return 401** +```bash +curl http://xxx.hello.com/test?apikey=926d90ac-ba2e-11ec-ab68-00163e1250b5 +``` + +**The caller matched according to the API Key provided in the request has no access rights, return 403** +```bash +# consumer2 is not in the allow list of route-a +curl http://xxx.hello.com/test?apikey=c8c8e9ca-558e-4a2d-bb62-e700dcc40e35 +``` + +## Gateway instance level enabled + +The following configuration does not specify the `_rules_` field, so Key Auth authentication will be enabled at the gateway instance level. + +```yaml +consumers: +- credential: 2bda943c-ba2b-11ec-ba07-00163e1250b5 + name: consumer1 +- credential: c8c8e9ca-558e-4a2d-bb62-e700dcc40e35 + name: consumer2 +keys: +- apikey +in_query: true +``` + +# Error code + +| HTTP status code | Error information | Reason | +| ---------------- | --------------------------------------------------------- | -------------------------------------------- | +| 401 | No API key found in request. | API not provided by request Key. | +| 401 | Request denied by Key Auth check. Invalid API key. | Current API Key access is not allowed. | +| 403 | Request denied by Basic Auth check. Unauthorized consumer. | The requested caller does not have access. | + diff --git a/plugins/wasm-cpp/extensions/key_auth/plugin.cc b/plugins/wasm-cpp/extensions/key_auth/plugin.cc index 0c48f121a5..a88b6bda7a 100644 --- a/plugins/wasm-cpp/extensions/key_auth/plugin.cc +++ b/plugins/wasm-cpp/extensions/key_auth/plugin.cc @@ -211,8 +211,7 @@ bool PluginRootContext::onConfigure(size_t size) { // Parse configuration JSON string. if (size > 0 && !configure(size)) { LOG_WARN("configuration has errors initialization will not continue."); - setInvalidConfig(); - return true; + return false; } return true; } diff --git a/plugins/wasm-cpp/extensions/key_rate_limit/BUILD b/plugins/wasm-cpp/extensions/key_rate_limit/BUILD index 9b2d56a9cc..7f4cd92495 100644 --- a/plugins/wasm-cpp/extensions/key_rate_limit/BUILD +++ b/plugins/wasm-cpp/extensions/key_rate_limit/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -13,9 +27,9 @@ wasm_cc_binary( "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "//common:json_util", - "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", "//common:http_util", "//common:rule_util", + "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", ], ) @@ -34,8 +48,8 @@ cc_library( "@com_google_absl//absl/strings", "//common:json_util", "@proxy_wasm_cpp_host//:lib", - "//common:http_util", - "//common:rule_util", + "//common:http_util_nullvm", + "//common:rule_util_nullvm", ], ) diff --git a/plugins/wasm-cpp/extensions/key_rate_limit/bucket.cc b/plugins/wasm-cpp/extensions/key_rate_limit/bucket.cc index 2d42a1b149..1e2d6fa0ce 100644 --- a/plugins/wasm-cpp/extensions/key_rate_limit/bucket.cc +++ b/plugins/wasm-cpp/extensions/key_rate_limit/bucket.cc @@ -18,6 +18,7 @@ #include #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/str_join.h" namespace { @@ -40,11 +41,16 @@ bool getToken(int rule_id, const std::string &key) { for (int i = 0; i < maxGetTokenRetry; i++) { if (WasmResult::Ok != getSharedData(tokenBucketKey, &token_bucket_data, &cas)) { - return false; + continue; } uint64_t token_left = *reinterpret_cast(token_bucket_data->data()); + LOG_DEBUG(absl::StrFormat( + "ratelimit get token: id:%d, tokenBucketKey:%s, token left:%u", rule_id, + tokenBucketKey, token_left)); if (token_left == 0) { + LOG_DEBUG(absl::StrFormat("get token failed, id:%d, tokenBucketKey:%s", + rule_id, tokenBucketKey)); return false; } token_left -= 1; @@ -52,12 +58,18 @@ bool getToken(int rule_id, const std::string &key) { tokenBucketKey, {reinterpret_cast(&token_left), sizeof(token_left)}, cas); if (res == WasmResult::Ok) { + LOG_DEBUG( + absl::StrFormat("ratelimit token update success: id:%d, " + "tokenBucketKey:%s, token left:%u", + rule_id, tokenBucketKey, token_left)); return true; } if (res == WasmResult::CasMismatch) { continue; } - return false; + LOG_WARN(absl::StrFormat("got invalid result:%d, id:%d, tokenBucketKey:%s", + res, rule_id, tokenBucketKey)); + return true; } LOG_WARN("get token failed with cas mismatch"); @@ -86,12 +98,21 @@ void refillToken(const std::vector> &rules) { if (now - last_update < rule.second.refill_interval_nanosec) { continue; } + LOG_DEBUG( + absl::StrFormat("ratelimit rule need refilled, id:%s, " + "lastRefilledKey:%s, now:%u, last_update:%u", + id, lastRefilledKey, now, last_update)); // Otherwise, try set last updated time. If updated failed because of cas // mismatch, the bucket is going to be refilled by other VMs. auto res = setSharedData( lastRefilledKey, {reinterpret_cast(&now), sizeof(now)}, last_update_cas); if (res == WasmResult::CasMismatch) { + LOG_DEBUG( + absl::StrFormat("ratelimit update lastRefilledKey casmismatch, the " + "bucket is going to be refilled by other VMs, id:%s, " + "lastRefilledKey:%s", + id, lastRefilledKey)); continue; } do { @@ -115,6 +136,10 @@ void refillToken(const std::vector> &rules) { last_update_cas)) { continue; } + LOG_DEBUG( + absl::StrFormat("ratelimit token refilled: id:%s, " + "tokenBucketKey:%s, token left:%u", + id, tokenBucketKey, token_left)); break; } while (true); } @@ -138,6 +163,10 @@ bool initializeTokenBucket( setSharedData(tokenBucketKey, {reinterpret_cast(&rule.second.max_tokens), sizeof(uint64_t)}); + LOG_INFO(absl::StrFormat( + "ratelimit rule created: id:%s, lastRefilledKey:%s, " + "tokenBucketKey:%s, max_tokens:%u", + id, lastRefilledKey, tokenBucketKey, rule.second.max_tokens)); continue; } // reconfigure @@ -172,6 +201,10 @@ bool initializeTokenBucket( } break; } while (true); + LOG_INFO(absl::StrFormat( + "ratelimit rule reconfigured: id:%s, lastRefilledKey:%s, " + "tokenBucketKey:%s, max_tokens:%u", + id, lastRefilledKey, tokenBucketKey, rule.second.max_tokens)); } return true; } diff --git a/plugins/wasm-cpp/extensions/key_rate_limit/plugin.cc b/plugins/wasm-cpp/extensions/key_rate_limit/plugin.cc index ab0e076fbe..5a042a8c4f 100644 --- a/plugins/wasm-cpp/extensions/key_rate_limit/plugin.cc +++ b/plugins/wasm-cpp/extensions/key_rate_limit/plugin.cc @@ -169,6 +169,7 @@ bool PluginRootContext::checkPlugin(int rule_id, return true; } if (!getToken(rule_id, key)) { + LOG_INFO(absl::StrCat("request rate limited by key: ", key)); tooManyRequest(); return false; } @@ -181,8 +182,7 @@ bool PluginRootContext::onConfigure(size_t size) { // Parse configuration JSON string. if (size > 0 && !configure(size)) { LOG_WARN("configuration has errors initialization will not continue."); - setInvalidConfig(); - return true; + return false; } const auto& rules = getRules(); for (const auto& rule : rules) { @@ -191,7 +191,7 @@ bool PluginRootContext::onConfigure(size_t size) { } } initializeTokenBucket(limits_); - proxy_set_tick_period_milliseconds(1000); + proxy_set_tick_period_milliseconds(500); return true; } diff --git a/plugins/wasm-cpp/extensions/request_block/BUILD b/plugins/wasm-cpp/extensions/request_block/BUILD index c6817a4ed5..518209139b 100644 --- a/plugins/wasm-cpp/extensions/request_block/BUILD +++ b/plugins/wasm-cpp/extensions/request_block/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -11,9 +25,9 @@ wasm_cc_binary( "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "//common:json_util", - "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", "//common:http_util", "//common:rule_util", + "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", ], ) @@ -30,8 +44,8 @@ cc_library( "@com_google_absl//absl/strings", "//common:json_util", "@proxy_wasm_cpp_host//:lib", - "//common:http_util", - "//common:rule_util", + "//common:http_util_nullvm", + "//common:rule_util_nullvm", ], ) diff --git a/plugins/wasm-cpp/extensions/request_block/plugin.cc b/plugins/wasm-cpp/extensions/request_block/plugin.cc index fbc7c5a1c5..90c6c92f7c 100644 --- a/plugins/wasm-cpp/extensions/request_block/plugin.cc +++ b/plugins/wasm-cpp/extensions/request_block/plugin.cc @@ -108,24 +108,24 @@ bool PluginRootContext::parsePluginConfig(const json& configuration, return false; } if (!JsonArrayIterate( - configuration, "block_bodies", [&](const json& item) -> bool { + configuration, "block_bodys", [&](const json& item) -> bool { auto body = JsonValueAs(item); if (body.second != Wasm::Common::JsonParserResultDetail::OK) { - LOG_WARN("cannot parse block_bodies"); + LOG_WARN("cannot parse block_bodys"); return false; } if (rule.case_sensitive) { - rule.block_bodies.push_back(std::move(body.first.value())); + rule.block_bodys.push_back(std::move(body.first.value())); } else { - rule.block_bodies.push_back( + rule.block_bodys.push_back( absl::AsciiStrToLower(body.first.value())); } return true; })) { - LOG_WARN("failed to parse configuration for block_bodies."); + LOG_WARN("failed to parse configuration for block_bodys."); return false; } - if (rule.block_bodies.empty() && rule.block_headers.empty() && + if (rule.block_bodys.empty() && rule.block_headers.empty() && rule.block_urls.empty()) { LOG_WARN("there is no block rules"); return false; @@ -137,8 +137,7 @@ bool PluginRootContext::onConfigure(size_t size) { // Parse configuration JSON string. if (size > 0 && !configure(size)) { LOG_WARN("configuration has errors initialization will not continue."); - setInvalidConfig(); - return true; + return false; } return true; } @@ -197,7 +196,7 @@ bool PluginRootContext::checkHeader(const RequestBlockConfigRule& rule, } } } - if (!rule.block_bodies.empty()) { + if (!rule.block_bodys.empty()) { check_body = true; } return true; @@ -212,7 +211,7 @@ bool PluginRootContext::checkBody(const RequestBlockConfigRule& rule, bodystr = absl::AsciiStrToLower(request_body); body = bodystr; } - for (const auto& block_body : rule.block_bodies) { + for (const auto& block_body : rule.block_bodys) { if (absl::StrContains(body, block_body)) { sendLocalResponse(rule.blocked_code, "", rule.blocked_message, {}); return false; diff --git a/plugins/wasm-cpp/extensions/request_block/plugin.h b/plugins/wasm-cpp/extensions/request_block/plugin.h index 29f2d2f9af..4c9288f2a9 100644 --- a/plugins/wasm-cpp/extensions/request_block/plugin.h +++ b/plugins/wasm-cpp/extensions/request_block/plugin.h @@ -45,7 +45,7 @@ struct RequestBlockConfigRule { bool case_sensitive = true; std::vector block_urls; std::vector block_headers; - std::vector block_bodies; + std::vector block_bodys; }; // PluginRootContext is the root context for all streams processed by the diff --git a/plugins/wasm-cpp/extensions/request_block/plugin_test.cc b/plugins/wasm-cpp/extensions/request_block/plugin_test.cc index 2b6dce5aec..40cc327119 100644 --- a/plugins/wasm-cpp/extensions/request_block/plugin_test.cc +++ b/plugins/wasm-cpp/extensions/request_block/plugin_test.cc @@ -128,7 +128,7 @@ TEST_F(RequestBlockTest, CaseSensitive) { { "block_urls": ["?foo=bar", "swagger.html"], "block_headers": ["headerKey", "headerValue"], - "block_bodies": ["Hello World"] + "block_bodys": ["Hello World"] })"; config_.set({configuration.data(), configuration.size()}); @@ -188,7 +188,7 @@ TEST_F(RequestBlockTest, CaseInsensitive) { "blocked_code": 404, "block_urls": ["?foo=bar", "swagger.html"], "block_headers": ["headerKey", "headerValue"], - "block_bodies": ["Hello World"] + "block_bodys": ["Hello World"] })"; config_.set({configuration.data(), configuration.size()}); diff --git a/plugins/wasm-cpp/extensions/sni_misdirect/BUILD b/plugins/wasm-cpp/extensions/sni_misdirect/BUILD index 0a800a0c09..b4b32b4c10 100644 --- a/plugins/wasm-cpp/extensions/sni_misdirect/BUILD +++ b/plugins/wasm-cpp/extensions/sni_misdirect/BUILD @@ -1,3 +1,17 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + load("@proxy_wasm_cpp_sdk//bazel/wasm:wasm.bzl", "wasm_cc_binary") load("//bazel:wasm.bzl", "declare_wasm_image_targets") @@ -10,8 +24,8 @@ wasm_cc_binary( deps = [ "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/strings", - "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", "//common:http_util", + "@proxy_wasm_cpp_sdk//:proxy_wasm_intrinsics", ], ) @@ -30,7 +44,7 @@ cc_library( "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/strings", "@proxy_wasm_cpp_host//:lib", - "//common:http_util", + "//common:http_util_nullvm", ], ) diff --git a/plugins/wasm-go/README.md b/plugins/wasm-go/README.md index 045c47e682..28da884c76 100644 --- a/plugins/wasm-go/README.md +++ b/plugins/wasm-go/README.md @@ -117,7 +117,7 @@ spec: # 跟上面例子一样,这个配置会全局生效,但如果被下面规则匹配到,则会改为执行命中规则的配置 block_urls: - "swagger.html" - matchRules: + matchRules: # 路由级生效配置 - ingress: - default/foo diff --git a/plugins/wasm-go/extensions/http-call/main.go b/plugins/wasm-go/extensions/http-call/main.go index ec668c2f5f..bfc607cdea 100644 --- a/plugins/wasm-go/extensions/http-call/main.go +++ b/plugins/wasm-go/extensions/http-call/main.go @@ -102,8 +102,6 @@ func onHttpRequestHeaders(ctx wrapper.HttpContext, config HttpCallConfig, log wr defer proxywasm.ResumeHttpRequest() if statusCode != http.StatusOK { log.Errorf("http call failed, status: %d", statusCode) - proxywasm.SendHttpResponse(http.StatusInternalServerError, nil, - []byte("http call failed"), -1) return } // avoid protocol error diff --git a/registry/direct/watcher.go b/registry/direct/watcher.go new file mode 100644 index 0000000000..ed3e3f9a95 --- /dev/null +++ b/registry/direct/watcher.go @@ -0,0 +1,164 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package direct + +import ( + "net" + "regexp" + "strconv" + "strings" + "sync" + + "istio.io/api/networking/v1alpha3" + "istio.io/istio/pkg/config/protocol" + "istio.io/pkg/log" + + apiv1 "github.com/alibaba/higress/api/networking/v1" + "github.com/alibaba/higress/pkg/common" + "github.com/alibaba/higress/registry" + provider "github.com/alibaba/higress/registry" + "github.com/alibaba/higress/registry/memory" +) + +type watcher struct { + provider.BaseWatcher + apiv1.RegistryConfig + cache memory.Cache + mutex sync.Mutex +} + +type WatcherOption func(w *watcher) + +func NewWatcher(cache memory.Cache, opts ...WatcherOption) (provider.Watcher, error) { + w := &watcher{ + cache: cache, + } + for _, opt := range opts { + opt(w) + } + return w, nil +} + +func WithType(t string) WatcherOption { + return func(w *watcher) { + w.Type = t + } +} + +func WithName(name string) WatcherOption { + return func(w *watcher) { + w.Name = name + } +} + +func WithDomain(domain string) WatcherOption { + return func(w *watcher) { + w.Domain = domain + } +} + +func WithPort(port uint32) WatcherOption { + return func(w *watcher) { + w.Port = port + } +} + +func (w *watcher) Run() { + w.mutex.Lock() + defer w.mutex.Unlock() + host := strings.Join([]string{w.Name, w.Type}, common.DotSeparator) + serviceEntry := w.generateServiceEntry(host) + if serviceEntry != nil { + w.cache.UpdateServiceEntryWrapper(host, &memory.ServiceEntryWrapper{ + ServiceName: w.Name, + ServiceEntry: serviceEntry, + Suffix: w.Type, + RegistryType: w.Type, + }) + w.UpdateService() + } + w.Ready(true) +} + +func (w *watcher) Stop() { + w.mutex.Lock() + defer w.mutex.Unlock() + host := strings.Join([]string{w.Name, w.Type}, common.DotSeparator) + w.cache.DeleteServiceEntryWrapper(host) + w.Ready(false) +} + +var domainRegex = regexp.MustCompile(`^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$`) + +func (w *watcher) generateServiceEntry(host string) *v1alpha3.ServiceEntry { + endpoints := make([]*v1alpha3.WorkloadEntry, 0) + for _, ep := range strings.Split(w.Domain, common.CommaSeparator) { + var endpoint *v1alpha3.WorkloadEntry + if w.Type == string(registry.Static) { + pair := strings.Split(ep, common.ColonSeparator) + if len(pair) != 2 { + log.Errorf("invalid endpoint:%s with static type", ep) + return nil + } + port, err := strconv.ParseUint(pair[1], 10, 32) + if err != nil { + log.Errorf("invalid port:%s of endpoint:%s", pair[1], ep) + return nil + } + if net.ParseIP(pair[0]) == nil { + log.Errorf("invalid ip:%s of endpoint:%s", pair[0], ep) + return nil + } + endpoint = &v1alpha3.WorkloadEntry{ + Address: pair[0], + Ports: map[string]uint32{"http": uint32(port)}, + } + } else if w.Type == string(registry.DNS) { + if !domainRegex.MatchString(ep) { + log.Errorf("invalid domain format:%s", ep) + return nil + } + endpoint = &v1alpha3.WorkloadEntry{ + Address: ep, + } + } else { + log.Errorf("unknown direct service type:%s", w.Type) + return nil + } + endpoints = append(endpoints, endpoint) + } + if len(endpoints) == 0 { + log.Errorf("empty endpoints will not be pushed, host:%s", host) + return nil + } + var ports []*v1alpha3.Port + ports = append(ports, &v1alpha3.Port{ + Number: w.Port, + Name: "http", + Protocol: string(protocol.HTTP), + }) + se := &v1alpha3.ServiceEntry{ + Hosts: []string{host}, + Ports: ports, + Location: v1alpha3.ServiceEntry_MESH_INTERNAL, + Endpoints: endpoints, + } + if w.Type == string(registry.Static) { + se.Resolution = v1alpha3.ServiceEntry_STATIC + } else if w.Type == string(registry.DNS) { + se.Resolution = v1alpha3.ServiceEntry_DNS + } + return se +} diff --git a/registry/memory/cache.go b/registry/memory/cache.go index 346a4105c0..b8ed2a373a 100644 --- a/registry/memory/cache.go +++ b/registry/memory/cache.go @@ -29,6 +29,7 @@ import ( type Cache interface { UpdateServiceEntryWrapper(service string, data *ServiceEntryWrapper) DeleteServiceEntryWrapper(service string) + PurgeStaleService() UpdateServiceEntryEnpointWrapper(service, ip, regionId, zoneId, protocol string, labels map[string]string) GetServiceByEndpoints(requestVersions, endpoints map[string]bool, versionKey string, protocol common.Protocol) map[string][]string GetAllServiceEntry() []*v1alpha3.ServiceEntry @@ -39,20 +40,22 @@ type Cache interface { func NewCache() Cache { return &store{ - mux: &sync.RWMutex{}, - sew: make(map[string]*ServiceEntryWrapper), - toBeUpdated: make([]*ServiceEntryWrapper, 0), - toBeDeleted: make([]*ServiceEntryWrapper, 0), - ip2services: make(map[string]map[string]bool), + mux: &sync.RWMutex{}, + sew: make(map[string]*ServiceEntryWrapper), + toBeUpdated: make([]*ServiceEntryWrapper, 0), + toBeDeleted: make([]*ServiceEntryWrapper, 0), + ip2services: make(map[string]map[string]bool), + deferedDelete: make(map[string]struct{}), } } type store struct { - mux *sync.RWMutex - sew map[string]*ServiceEntryWrapper - toBeUpdated []*ServiceEntryWrapper - toBeDeleted []*ServiceEntryWrapper - ip2services map[string]map[string]bool + mux *sync.RWMutex + sew map[string]*ServiceEntryWrapper + toBeUpdated []*ServiceEntryWrapper + toBeDeleted []*ServiceEntryWrapper + ip2services map[string]map[string]bool + deferedDelete map[string]struct{} } func (s *store) UpdateServiceEntryEnpointWrapper(service, ip, regionId, zoneId, protocol string, labels map[string]string) { @@ -105,6 +108,12 @@ func (s *store) UpdateServiceEntryWrapper(service string, data *ServiceEntryWrap s.toBeUpdated = append(s.toBeUpdated, data) s.sew[service] = data + // service is updated, should not be deleted + if _, ok := s.deferedDelete[service]; ok { + delete(s.deferedDelete, service) + log.Debugf("service in deferedDelete updated, host:%s", service) + } + log.Infof("ServiceEntry updated, host:%s", service) } func (s *store) DeleteServiceEntryWrapper(service string) { @@ -114,7 +123,18 @@ func (s *store) DeleteServiceEntryWrapper(service string) { if data, exist := s.sew[service]; exist { s.toBeDeleted = append(s.toBeDeleted, data) } - delete(s.sew, service) + s.deferedDelete[service] = struct{}{} +} + +// should only be called when reconcile is done +func (s *store) PurgeStaleService() { + s.mux.Lock() + defer s.mux.Unlock() + for service := range s.deferedDelete { + delete(s.sew, service) + delete(s.deferedDelete, service) + log.Infof("ServiceEntry deleted, host:%s", service) + } } // GetServiceByEndpoints get the list of services of which "address:port" contained by the endpoints diff --git a/registry/nacos/v2/watcher.go b/registry/nacos/v2/watcher.go index 88a3765f50..be76e3a5ed 100644 --- a/registry/nacos/v2/watcher.go +++ b/registry/nacos/v2/watcher.go @@ -60,8 +60,6 @@ type watcher struct { RegistryType provider.ServiceRegistryType `json:"registry_type"` Status provider.WatcherStatus `json:"status"` namingClient naming_client.INamingClient - updateHandler provider.ServiceUpdateHandler - readyHandler provider.ReadyHandler cache memory.Cache mutex *sync.Mutex stop chan struct{} @@ -234,7 +232,7 @@ func (w *watcher) Run() { if err != nil { log.Errorf("first fetch services failed, err:%v", err) } else { - w.readyHandler(true) + w.Ready(true) } for { select { @@ -243,7 +241,7 @@ func (w *watcher) Run() { if err != nil { log.Errorf("fetch services failed, err:%v", err) } else { - w.readyHandler(true) + w.Ready(true) } case <-w.stop: return @@ -399,7 +397,7 @@ func (w *watcher) getSubscribeCallback(groupName string, serviceName string) fun host := strings.Join([]string{serviceName, suffix}, common.DotSeparator) return func(services []model.Instance, err error) { - defer w.updateHandler() + defer w.UpdateService() //log.Info("callback", "serviceName", serviceName, "suffix", suffix, "details", services) @@ -484,8 +482,8 @@ func (w *watcher) Stop() { } w.isStop = true - w.stop <- struct{}{} - w.readyHandler(false) + close(w.stop) + w.Ready(false) } func (w *watcher) IsHealthy() bool { @@ -496,14 +494,6 @@ func (w *watcher) GetRegistryType() string { return w.RegistryType.String() } -func (w *watcher) AppendServiceUpdateHandler(f func()) { - w.updateHandler = f -} - -func (w *watcher) ReadyHandler(f func(bool)) { - w.readyHandler = f -} - func shouldSubscribe(serviceName string) bool { prefixFilters := []string{"consumers:"} fullFilters := []string{""} diff --git a/registry/nacos/watcher.go b/registry/nacos/watcher.go index a473ba01d5..82506ec746 100644 --- a/registry/nacos/watcher.go +++ b/registry/nacos/watcher.go @@ -58,8 +58,6 @@ type watcher struct { RegistryType provider.ServiceRegistryType `json:"registry_type"` Status provider.WatcherStatus `json:"status"` namingClient naming_client.INamingClient - updateHandler provider.ServiceUpdateHandler - readyHandler provider.ReadyHandler cache memory.Cache mutex *sync.Mutex stop chan struct{} @@ -200,7 +198,7 @@ func (w *watcher) Run() { defer ticker.Stop() w.Status = provider.ProbeWatcherStatus(w.Domain, strconv.FormatUint(uint64(w.Port), 10)) w.fetchAllServices() - w.readyHandler(true) + w.Ready(true) for { select { case <-ticker.C: @@ -218,7 +216,6 @@ func (w *watcher) fetchAllServices() error { return nil } fetchedServices := make(map[string]bool) - for _, groupName := range w.NacosGroups { for page := 1; ; page++ { ss, err := w.namingClient.GetAllServicesInfo(vo.GetAllServiceInfoParam{ @@ -305,7 +302,7 @@ func (w *watcher) getSubscribeCallback(groupName string, serviceName string) fun host := strings.Join([]string{serviceName, suffix}, common.DotSeparator) return func(services []model.SubscribeService, err error) { - defer w.updateHandler() + defer w.UpdateService() //log.Info("callback", "serviceName", serviceName, "suffix", suffix, "details", services) @@ -388,8 +385,8 @@ func (w *watcher) Stop() { w.cache.DeleteServiceEntryWrapper(host) } w.isStop = true - w.stop <- struct{}{} - w.readyHandler(false) + close(w.stop) + w.Ready(false) } func (w *watcher) IsHealthy() bool { @@ -400,14 +397,6 @@ func (w *watcher) GetRegistryType() string { return w.RegistryType.String() } -func (w *watcher) AppendServiceUpdateHandler(f func()) { - w.updateHandler = f -} - -func (w *watcher) ReadyHandler(f func(bool)) { - w.readyHandler = f -} - func shouldSubscribe(serviceName string) bool { prefixFilters := []string{"consumers:"} fullFilters := []string{""} diff --git a/registry/reconcile/reconcile.go b/registry/reconcile/reconcile.go index dab5e590b2..a4e214ef70 100644 --- a/registry/reconcile/reconcile.go +++ b/registry/reconcile/reconcile.go @@ -25,6 +25,7 @@ import ( apiv1 "github.com/alibaba/higress/api/networking/v1" v1 "github.com/alibaba/higress/client/pkg/apis/networking/v1" . "github.com/alibaba/higress/registry" + "github.com/alibaba/higress/registry/direct" "github.com/alibaba/higress/registry/memory" "github.com/alibaba/higress/registry/nacos" nacosv2 "github.com/alibaba/higress/registry/nacos/v2" @@ -77,7 +78,15 @@ func (r *Reconciler) Reconcile(mcpbridge *v1.McpBridge) { errHappened := false log.Infof("ReconcileRegistries, toBeCreated: %d, toBeUpdated: %d, toBeDeleted: %d", len(toBeCreated), len(toBeUpdated), len(toBeDeleted)) - for k, v := range toBeCreated { + for k := range toBeDeleted { + r.watchers[k].Stop() + delete(r.registries, k) + delete(r.watchers, k) + } + for k, v := range toBeUpdated { + r.watchers[k].Stop() + delete(r.registries, k) + delete(r.watchers, k) watcher, err := r.generateWatcherFromRegistryConfig(v, &wg) if err != nil { errHappened = true @@ -89,10 +98,7 @@ func (r *Reconciler) Reconcile(mcpbridge *v1.McpBridge) { r.watchers[k] = watcher r.registries[k] = v } - for k, v := range toBeUpdated { - go r.watchers[k].Stop() - delete(r.registries, k) - delete(r.watchers, k) + for k, v := range toBeCreated { watcher, err := r.generateWatcherFromRegistryConfig(v, &wg) if err != nil { errHappened = true @@ -104,16 +110,12 @@ func (r *Reconciler) Reconcile(mcpbridge *v1.McpBridge) { r.watchers[k] = watcher r.registries[k] = v } - for k := range toBeDeleted { - go r.watchers[k].Stop() - delete(r.registries, k) - delete(r.watchers, k) - } if errHappened { log.Error("ReconcileRegistries failed, Init Watchers failed") return } wg.Wait() + r.Cache.PurgeStaleService() log.Infof("Registries is reconciled") } @@ -158,6 +160,14 @@ func (r *Reconciler) generateWatcherFromRegistryConfig(registry *apiv1.RegistryC zookeeper.WithPort(registry.Port), zookeeper.WithZkServicesPath(registry.ZkServicesPath), ) + case string(Static), string(DNS): + watcher, err = direct.NewWatcher( + r.Cache, + direct.WithType(registry.Type), + direct.WithName(registry.Name), + direct.WithDomain(registry.Domain), + direct.WithPort(registry.Port), + ) default: return nil, errors.New("unsupported registry type:" + registry.Type) } @@ -172,7 +182,7 @@ func (r *Reconciler) generateWatcherFromRegistryConfig(registry *apiv1.RegistryC once.Do(func() { wg.Done() if ready { - log.Infof("Registry Watcher is ready, type:%s, name:%s", registry.Type, registry.Name) + log.Infof("Registry Watcher is ready, type:%s, name:%s", registry.Type, registry.Name) } }) }) diff --git a/registry/watcher.go b/registry/watcher.go index 942b15909b..129ec0ec96 100644 --- a/registry/watcher.go +++ b/registry/watcher.go @@ -25,6 +25,8 @@ const ( Consul ServiceRegistryType = "consul" Nacos ServiceRegistryType = "nacos" Nacos2 ServiceRegistryType = "nacos2" + Static ServiceRegistryType = "static" + DNS ServiceRegistryType = "dns" Healthy WatcherStatus = "healthy" UnHealthy WatcherStatus = "unhealthy" @@ -52,14 +54,21 @@ type Watcher interface { ReadyHandler(f func(bool)) } -type BaseWatcher struct{} +type BaseWatcher struct { + UpdateService ServiceUpdateHandler + Ready ReadyHandler +} -func (w *BaseWatcher) Run() {} -func (w *BaseWatcher) Stop() {} -func (w *BaseWatcher) IsHealthy() bool { return true } -func (w *BaseWatcher) GetRegistryType() string { return "" } -func (w *BaseWatcher) AppendServiceUpdateHandler(f func()) {} -func (w *BaseWatcher) ReadyHandler(f func(bool)) {} +func (w *BaseWatcher) Run() {} +func (w *BaseWatcher) Stop() {} +func (w *BaseWatcher) IsHealthy() bool { return true } +func (w *BaseWatcher) GetRegistryType() string { return "" } +func (w *BaseWatcher) AppendServiceUpdateHandler(f func()) { + w.UpdateService = f +} +func (w *BaseWatcher) ReadyHandler(f func(bool)) { + w.Ready = f +} type ServiceUpdateHandler func() type ReadyHandler func(bool) diff --git a/registry/zookeeper/watcher.go b/registry/zookeeper/watcher.go index 60a59d94b8..c9921cdf49 100644 --- a/registry/zookeeper/watcher.go +++ b/registry/zookeeper/watcher.go @@ -50,8 +50,6 @@ type watcher struct { RegistryType provider.ServiceRegistryType `json:"registry_type"` Status provider.WatcherStatus `json:"status"` serviceRemaind *atomic.Int32 - updateHandler provider.ServiceUpdateHandler - readyHandler provider.ReadyHandler cache memory.Cache mutex *sync.Mutex stop chan struct{} @@ -339,7 +337,7 @@ func (w *watcher) DataChange(eventType Event) bool { Suffix: "zookeeper", RegistryType: w.Type, }) - w.updateHandler() + w.UpdateService() } else if eventType.Action == EventTypeDel { w.seMux.Lock() value, ok := w.serviceEntry[host] @@ -370,7 +368,7 @@ func (w *watcher) DataChange(eventType Event) bool { RegistryType: w.Type, }) } - w.updateHandler() + w.UpdateService() } return true } @@ -580,7 +578,7 @@ func (w *watcher) ChildToServiceEntry(children []string, interfaceName, zkPath s } } w.seMux.Unlock() - w.updateHandler() + w.UpdateService() } } @@ -681,7 +679,7 @@ func (w *watcher) Run() { case <-ticker.C: var needNewFetch bool if w.IsReady() { - w.readyHandler(true) + w.Ready(true) needNewFetch = true } if firstFetchErr != nil || needNewFetch { @@ -712,15 +710,13 @@ func (w *watcher) Stop() { for key := range w.serviceEntry { w.cache.DeleteServiceEntryWrapper(key) } - w.updateHandler() + w.UpdateService() w.seMux.Unlock() - w.stop <- struct{}{} - w.Done <- struct{}{} close(w.stop) close(w.Done) w.zkClient.Close() - w.readyHandler(false) + w.Ready(false) } func (w *watcher) IsHealthy() bool { @@ -731,14 +727,6 @@ func (w *watcher) GetRegistryType() string { return w.RegistryType.String() } -func (w *watcher) AppendServiceUpdateHandler(f func()) { - w.updateHandler = f -} - -func (w *watcher) ReadyHandler(f func(bool)) { - w.readyHandler = f -} - func (w *watcher) IsReady() bool { if w.serviceRemaind == nil { return true diff --git a/test/ingress/conformance/tests/httproute-canary-header.go b/test/ingress/conformance/tests/httproute-canary-header.go index c41708ee06..7957a87985 100644 --- a/test/ingress/conformance/tests/httproute-canary-header.go +++ b/test/ingress/conformance/tests/httproute-canary-header.go @@ -64,6 +64,74 @@ var HTTPRouteCanaryHeader = suite.ConformanceTest{ StatusCode: 200, }, }, + }, { + Meta: http.AssertionMeta{ + TargetBackend: "infra-backend-v2", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/foo", + Host: "canary.higress.io", + Headers: map[string]string{"traffic-split-higress": "true"}, + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, { + Meta: http.AssertionMeta{ + TargetBackend: "infra-backend-v1", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/foo/bar", + Host: "canary.higress.io", + Headers: map[string]string{"traffic-split-higress": "true"}, + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, + { + Meta: http.AssertionMeta{ + TargetBackend: "infra-backend-v3", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/foo", + Host: "canary.higress.io", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, + { + Meta: http.AssertionMeta{ + TargetBackend: "infra-backend-v3", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/foo/bar", + Host: "canary.higress.io", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, }, } diff --git a/test/ingress/conformance/tests/httproute-canary-header.yaml b/test/ingress/conformance/tests/httproute-canary-header.yaml index 5d0c4bbb87..f20ddc09cf 100644 --- a/test/ingress/conformance/tests/httproute-canary-header.yaml +++ b/test/ingress/conformance/tests/httproute-canary-header.yaml @@ -53,3 +53,59 @@ spec: name: infra-backend-v2 port: number: 8080 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/canary: "true" + nginx.ingress.kubernetes.io/canary-by-header: "traffic-split-higress" + nginx.ingress.kubernetes.io/canary-by-header-value: "true" + name: ingress-echo-canary-value-prefix + namespace: higress-conformance-infra +spec: + ingressClassName: higress + rules: + - host: canary.higress.io + http: + paths: + - path: /foo + pathType: Exact + backend: + service: + name: infra-backend-v2 + port: + number: 8080 + - path: /foo + pathType: Prefix + backend: + service: + name: infra-backend-v1 + port: + number: 8080 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-echo-prefix + namespace: higress-conformance-infra +spec: + ingressClassName: higress + rules: + - host: canary.higress.io + http: + paths: + - path: /foo + pathType: Exact + backend: + service: + name: infra-backend-v3 + port: + number: 8080 + - path: /foo + pathType: Prefix + backend: + service: + name: infra-backend-v3 + port: + number: 8080 diff --git a/test/ingress/conformance/tests/httproute-ignore-case-match.go b/test/ingress/conformance/tests/httproute-enable-ignore-case.go similarity index 67% rename from test/ingress/conformance/tests/httproute-ignore-case-match.go rename to test/ingress/conformance/tests/httproute-enable-ignore-case.go index 37e03a92c6..c3855c5189 100644 --- a/test/ingress/conformance/tests/httproute-ignore-case-match.go +++ b/test/ingress/conformance/tests/httproute-enable-ignore-case.go @@ -22,13 +22,13 @@ import ( ) func init() { - HigressConformanceTests = append(HigressConformanceTests, HTTPRouteIgnoreCaseMatch) + HigressConformanceTests = append(HigressConformanceTests, HTTPRouteEnableIgnoreCase) } -var HTTPRouteIgnoreCaseMatch = suite.ConformanceTest{ - ShortName: "HTTPRouteIgnoreCaseMatch", +var HTTPRouteEnableIgnoreCase = suite.ConformanceTest{ + ShortName: "HTTPRouteEnableIgnoreCase", Description: "A Ingress in the higress-conformance-infra namespace that ignores URI case in HTTP match.", - Manifests: []string{"tests/httproute-ignore-case-match.yaml"}, + Manifests: []string{"tests/httproute-enable-ignore-case.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { testcases := []http.Assertion{ { @@ -65,6 +65,40 @@ var HTTPRouteIgnoreCaseMatch = suite.ConformanceTest{ StatusCode: 200, }, }, + }, { + Meta: http.AssertionMeta{ + TestCaseName: "case3: enable ignoreCase", + TargetBackend: "infra-backend-v2", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/BAR", + Host: "foo.com", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, { + Meta: http.AssertionMeta{ + TestCaseName: "case4: enable ignoreCase", + TargetBackend: "infra-backend-v3", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/CAT/ok", + Host: "foo.com", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, }, } diff --git a/test/ingress/conformance/tests/httproute-ignore-case-match.yaml b/test/ingress/conformance/tests/httproute-enable-ignore-case.yaml similarity index 76% rename from test/ingress/conformance/tests/httproute-ignore-case-match.yaml rename to test/ingress/conformance/tests/httproute-enable-ignore-case.yaml index 4320102226..07d0227bc9 100644 --- a/test/ingress/conformance/tests/httproute-ignore-case-match.yaml +++ b/test/ingress/conformance/tests/httproute-enable-ignore-case.yaml @@ -32,3 +32,17 @@ spec: name: infra-backend-v1 port: number: 8080 + - pathType: Prefix + path: "/bar" + backend: + service: + name: infra-backend-v2 + port: + number: 8080 + - pathType: Prefix + path: "/cat/" + backend: + service: + name: infra-backend-v3 + port: + number: 8080 diff --git a/test/ingress/conformance/tests/httproute-match-path.go b/test/ingress/conformance/tests/httproute-match-path.go new file mode 100644 index 0000000000..dc9ca1f034 --- /dev/null +++ b/test/ingress/conformance/tests/httproute-match-path.go @@ -0,0 +1,143 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tests + +import ( + "testing" + + "github.com/alibaba/higress/test/ingress/conformance/utils/http" + "github.com/alibaba/higress/test/ingress/conformance/utils/suite" +) + +func init() { + HigressConformanceTests = append(HigressConformanceTests, HTTPRouteMatchPath) +} + +var HTTPRouteMatchPath = suite.ConformanceTest{ + ShortName: "HTTPRouteMatchPath", + Description: "A Ingress in the higress-conformance-infra namespace that match different path.", + Manifests: []string{"tests/httproute-match-path.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + testcases := []http.Assertion{ + { + Meta: http.AssertionMeta{ + TestCaseName: "case1: normal request", + TargetBackend: "infra-backend-v1", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/foo", + Host: "foo.com", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, { + Meta: http.AssertionMeta{ + TestCaseName: "case2: path is '/bar' and match prefix path successfully", + TargetBackend: "infra-backend-v2", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/bar", + Host: "foo.com", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, { + Meta: http.AssertionMeta{ + TestCaseName: "case2: path is '/bar' and match prefix path failed", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/bard", + Host: "foo.com", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 404, + }, + }, + }, { + Meta: http.AssertionMeta{ + TestCaseName: "case3: path is '/cat/' and match prefix path successfully", + TargetBackend: "infra-backend-v3", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/cat", + Host: "foo.com", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, { + Meta: http.AssertionMeta{ + TestCaseName: "case4: path is '/cat/' and match prefix path successfully", + TargetBackend: "infra-backend-v3", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/cat/ok", + Host: "foo.com", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, { + Meta: http.AssertionMeta{ + TargetBackend: "infra-backend-v2", + TargetNamespace: "higress-conformance-infra", + }, + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Path: "/foo/", + Host: "foo.com", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, + } + + t.Run("HTTPRoute Match different path Cases", func(t *testing.T) { + for _, testcase := range testcases { + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, suite.GatewayAddress, testcase) + } + }) + + }, +} diff --git a/test/ingress/conformance/tests/httproute-match-path.yaml b/test/ingress/conformance/tests/httproute-match-path.yaml new file mode 100644 index 0000000000..227a6e012e --- /dev/null +++ b/test/ingress/conformance/tests/httproute-match-path.yaml @@ -0,0 +1,53 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: httproute-match-path + namespace: higress-conformance-infra +spec: + ingressClassName: higress + rules: + - host: "foo.com" + http: + paths: + - pathType: Prefix + path: "/foo" + backend: + service: + name: infra-backend-v2 + port: + number: 8080 + - pathType: Exact + path: "/foo" + backend: + service: + name: infra-backend-v1 + port: + number: 8080 + - pathType: Prefix + path: "/bar" + backend: + service: + name: infra-backend-v2 + port: + number: 8080 + - pathType: Prefix + path: "/cat/" + backend: + service: + name: infra-backend-v3 + port: + number: 8080 diff --git a/test/ingress/e2e_test.go b/test/ingress/e2e_test.go index b7672069ba..91478e27a3 100644 --- a/test/ingress/e2e_test.go +++ b/test/ingress/e2e_test.go @@ -57,7 +57,7 @@ func TestHigressConformanceTests(t *testing.T) { tests.HTTPRouteRewriteHost, tests.HTTPRouteCanaryHeader, tests.HTTPRouteEnableCors, - tests.HTTPRouteIgnoreCaseMatch, + tests.HTTPRouteEnableIgnoreCase, tests.HTTPRouteMatchMethods, tests.HTTPRouteMatchQueryParams, tests.HTTPRouteMatchHeaders, @@ -69,6 +69,7 @@ func TestHigressConformanceTests(t *testing.T) { tests.HTTPRouteCanaryHeaderWithCustomizedHeader, tests.HTTPRouteWhitelistSourceRange, tests.HTTPRouteCanaryWeight, + tests.HTTPRouteMatchPath, } cSuite.Run(t, higressTests) diff --git a/tools/hack/get-hgctl.sh b/tools/hack/get-hgctl.sh new file mode 100644 index 0000000000..4ef44b5844 --- /dev/null +++ b/tools/hack/get-hgctl.sh @@ -0,0 +1,183 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http:www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/usr/bin/env bash + +: "${BINARY_NAME:="hgctl"}" +: "${hgctl_INSTALL_DIR:="/usr/local/bin"}" + +export VERSION + +HAS_CURL="$(type "curl" &> /dev/null && echo true || echo false)" +HAS_WGET="$(type "wget" &> /dev/null && echo true || echo false)" +HAS_GIT="$(type "git" &> /dev/null && echo true || echo false)" + +# initArch discovers the architecture for this system. +initArch() { + ARCH=$(uname -m) + case $ARCH in + armv5*) ARCH="armv5";; + armv6*) ARCH="armv6";; + armv7*) ARCH="arm";; + aarch64) ARCH="arm64";; + x86) ARCH="386";; + x86_64) ARCH="amd64";; + i686) ARCH="386";; + i386) ARCH="386";; + esac +} + +# initOS discovers the operating system for this system. +initOS() { + OS="$(uname|tr '[:upper:]' '[:lower:]')" + + case "$OS" in + # Minimalist GNU for Windows + mingw*|cygwin*) OS='windows';; + esac +} + +# runs the given command as root (detects if we are root already) +runAsRoot() { + if [ $EUID -ne 0 ]; then + sudo "${@}" + else + "${@}" + fi +} + +# verifySupported checks that the os/arch combination is supported for +# binary builds, as well whether or not necessary tools are present. +verifySupported() { + local supported="darwin-amd64\ndarwin-arm64\nlinux-amd64\nlinux-arm64\n" + if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then + echo "No prebuilt binary for ${OS}-${ARCH}." + echo "To build from source, go to https://github.com/alibaba/higress" + exit 1 + fi + + if [ "${HAS_CURL}" != "true" ] && [ "${HAS_WGET}" != "true" ]; then + echo "Either curl or wget is required" + exit 1 + fi + + if [ "${HAS_GIT}" != "true" ]; then + echo "[WARNING] Could not find git. It is required for plugin installation." + fi +} + +# checkDesiredVersion checks if the desired version is available. +checkDesiredVersion() { + if [ "$VERSION" == "" ]; then + # Get tag from release URL + local latest_release_url="https://github.com/alibaba/higress/releases" + if [ "${HAS_CURL}" == "true" ]; then + VERSION=$(curl -Ls $latest_release_url | grep 'href="/alibaba/higress/releases/tag/v[0-9]*.[0-9]*.[0-9]*\"' | sed -E 's/.*\/alibaba\/higress\/releases\/tag\/(v[0-9\.]+)".*/\1/g' | head -1) + elif [ "${HAS_WGET}" == "true" ]; then + VERSION=$(wget $latest_release_url -O - 2>&1 | grep 'href="/alibaba/higress/releases/tag/v[0-9]*.[0-9]*.[0-9]*\"' | sed -E 's/.*\/alibaba\/higress\/releases\/tag\/(v[0-9\.]+)".*/\1/g' | head -1) + fi + fi +} + +# checkhgctlInstalledVersion checks which version of hgctl is installed and +# if it needs to be changed. +checkhgctlInstalledVersion() { + if [[ -f "${hgctl_INSTALL_DIR}/${BINARY_NAME}" ]]; then + version=$("${hgctl_INSTALL_DIR}/${BINARY_NAME}" version --client | grep -Eo "v[0-9]+\.[0-9]+.*" ) + if [[ "$version" == "$VERSION" ]]; then + echo "hgctl ${version} is already ${VERSION:-latest}" + return 0 + else + echo "hgctl ${VERSION} is available. Changing from version ${version}." + return 1 + fi + else + return 1 + fi +} + +# downloadFile downloads the latest binary package +# for that binary. +downloadFile() { + hgctl_DIST="hgctl_${VERSION}_${OS}_${ARCH}.tar.gz" + DOWNLOAD_URL="https://github.com/alibaba/higress/releases/download/$VERSION/$hgctl_DIST" + hgctl_TMP_ROOT="$(mktemp -dt hgctl-installer-XXXXXX)" + hgctl_TMP_FILE="$hgctl_TMP_ROOT/$hgctl_DIST" + echo "Downloading $DOWNLOAD_URL" + if [ "${HAS_CURL}" == "true" ]; then + curl -SsL "$DOWNLOAD_URL" -o "$hgctl_TMP_FILE" + elif [ "${HAS_WGET}" == "true" ]; then + wget -q -O "$hgctl_TMP_FILE" "$DOWNLOAD_URL" + fi +} + +# installFile installs the hgctl binary. +installFile() { + hgctl_TMP="$hgctl_TMP_ROOT/$BINARY_NAME" + mkdir -p "$hgctl_TMP" + tar xf "$hgctl_TMP_FILE" -C "$hgctl_TMP" + hgctl_TMP_BIN="$hgctl_TMP/out/${OS}_${ARCH}/hgctl" + echo "Preparing to install $BINARY_NAME into ${hgctl_INSTALL_DIR}" + runAsRoot cp "$hgctl_TMP_BIN" "$hgctl_INSTALL_DIR/$BINARY_NAME" + echo "$BINARY_NAME installed into $hgctl_INSTALL_DIR/$BINARY_NAME" +} + +# fail_trap is executed if an error occurs. +fail_trap() { + result=$? + if [ "$result" != "0" ]; then + if [[ -n "$INPUT_ARGUMENTS" ]]; then + echo "Failed to install $BINARY_NAME with the arguments provided: $INPUT_ARGUMENTS" + else + echo "Failed to install $BINARY_NAME" + fi + echo -e "\tFor support, go to https://github.com/alibaba/higress." + fi + cleanup + exit $result +} + +# testVersion tests the installed client to make sure it is working. +testVersion() { + set +e + if ! [ "$(command -v $BINARY_NAME)" ]; then + echo "$BINARY_NAME not found. Is $hgctl_INSTALL_DIR on your PATH?" + exit 1 + fi + set -e +} + +# cleanup temporary files. +cleanup() { + if [[ -d "${hgctl_TMP_ROOT:-}" ]]; then + rm -rf "$hgctl_TMP_ROOT" + fi +} + +# Execution + +#Stop execution on any error +trap "fail_trap" EXIT +set -e + +initArch +initOS +verifySupported +checkDesiredVersion +if ! checkhgctlInstalledVersion; then + downloadFile + installFile +fi +testVersion +cleanup