Compare commits

...

34 Commits

Author SHA1 Message Date
澄潭
3e68ae75d1 update version to 1.0.0 (#348) 2023-05-22 20:58:19 +08:00
Ffyyt
18ad817edb Add goproxy environment variable for build-image (#347) 2023-05-22 20:57:53 +08:00
Xunzhuo
d48e0ce773 e2e: rename some cases name to make it sync with others (#344) 2023-05-22 11:05:22 +08:00
Kent Dong
9734ffeb3e feat: Refactor skywalking configuration structure (#333) 2023-05-21 15:44:07 +08:00
Ffyyt
1421ce8667 e2e:add test for ssl redirect annotations (#341) 2023-05-21 15:20:00 +08:00
Jun
625c06e58f get upstream serviceSource from RouteCluster information and update docs (#337) 2023-05-19 10:40:24 +08:00
澄潭
e4a47dfb46 compatiable with tinygo 0.25 (#330) 2023-05-15 19:22:05 +08:00
WeixinX
6b483189ac docs: fix some plugin READMEs (#327) 2023-05-12 14:23:58 +08:00
刘晓瑞
74ad9a555a extend wasm go sdk with OnHttpStreamDone (#325) 2023-05-10 14:58:04 +08:00
Kent Dong
f6e181ecb6 fix: Sync Chart.lock file (#321) 2023-05-09 21:14:22 +08:00
Kent Dong
30a5b2ab2b feat: Upgrade Higress Console to v1.0.0-rc.2 (#320) 2023-05-09 17:24:15 +08:00
澄潭
91a23cc27e Update README_EN.md 2023-05-09 16:49:51 +08:00
澄潭
51e515d53e Update README.md 2023-05-09 16:49:10 +08:00
Kent Dong
67274bfa0d feat: Simplify Dockerfile for wasm-go-builder (#319) 2023-05-09 09:51:28 +08:00
Kent Dong
4f24979579 fix: Use tinygo 0.25.0 (#309) 2023-05-08 19:28:23 +08:00
Tom Kerkhove
1f4bf8e0b2 feat: Provide link to Higress in Helm chart (#318) 2023-05-08 17:03:00 +08:00
Kent Dong
05608128e2 feat: Use the 1.0.0-rc version of Higress Console (#317) 2023-05-08 10:47:11 +08:00
Kent Dong
fbdc301f94 feat: Add LICENSE and README.md to helm charts (#315) 2023-05-08 10:46:54 +08:00
Ffyyt
cf69234eff Add environment variable goproxy (#313) 2023-05-08 10:46:30 +08:00
Kent Dong
461f7ed675 fix: Fix the NEW ISSUE link in CONTRIBUTING pages (#314) 2023-05-06 13:59:01 +08:00
澄潭
7e358eb1db add commercial info (#310) 2023-05-04 15:57:05 +08:00
jiahao zhang
daffd18674 add plugin gw-error-format (#116)
Co-authored-by: 澄潭 <zty98751@alibaba-inc.com>
2023-05-04 09:42:41 +08:00
Kent Dong
48978e5135 feat: Use new wasm-go-builder with oras in the Makefile (#308) 2023-04-28 10:26:56 +08:00
Jun
311d5c21c2 Add Plugin de-graphql (#303) 2023-04-27 18:45:19 +08:00
Xunzhuo
e2b4a52c9e Add myself to pkg owners to take reviews of hgctl (#302)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-04-27 18:39:30 +08:00
Kent Dong
51cd5e830e feat: Add oras binary into wasm-go-builder image for OCI image building (#304) 2023-04-27 18:39:12 +08:00
Ffyyt
10d2b41ad5 README translation of the hmac-auth plugin (#306) 2023-04-27 18:38:42 +08:00
Kent Dong
4f16d6b70f feat: Support installing higress to a K8s cluster with kernel version < 4.11 (#301) 2023-04-24 15:29:39 +08:00
Tom Kerkhove
8c41dbc376 fix: Bug issue template is broken (#292) 2023-04-12 21:03:43 +08:00
Tom Kerkhove
e98788a75c chore: Introduce issue chooser for better issue reporting (#294) 2023-04-12 21:03:22 +08:00
Tom Kerkhove
3b5850a5ba docs: Move Console details after core features in README (#291) 2023-04-12 21:02:39 +08:00
澄潭
df60dd4307 add intro gif (#283) 2023-04-10 17:12:08 +08:00
澄潭
283432b6eb Fix destination rule issues (#282) 2023-04-10 13:41:43 +08:00
澄潭
a9742bbae1 Update README.md 2023-04-10 11:53:28 +08:00
66 changed files with 2931 additions and 181 deletions

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -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.

View File

@@ -10,14 +10,6 @@ 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.**
---
name: Bug Report
about: If you would like to report an issue to Higress, please use this template.
---
- [ ] I have searched the [issues](https://github.com/alibaba/higress/issues) of this repository and believe that this is not a duplicate.
### . Issue Description

View File

@@ -1,7 +1,7 @@
/api @johnlanni
/envoy @gengleilei @johnlanni @Lynskylate
/istio @SpecialYang @johnlanni
/pkg @SpecialYang @johnlanni @Charlie17Li
/pkg @SpecialYang @johnlanni @Charlie17Li @Xunzhuo
/plugins @johnlanni
/registry @NameHaibinZhang @johnlanni
/test @Xunzhuo

View File

@@ -27,7 +27,7 @@
## 报告一般问题
老实说,我们把每一个 Higress 用户都视为非常善良的贡献者。在体验了 Higress 之后,您可能会对项目有一些反馈。然后随时通过 [NEW ISSUE](https://github. com/alibaba/higress/issues/new/choose)打开一个问题。
老实说,我们把每一个 Higress 用户都视为非常善良的贡献者。在体验了 Higress 之后,您可能会对项目有一些反馈。然后随时通过 [NEW ISSUE](https://github.com/alibaba/higress/issues/new/choose)打开一个问题。
因为我们在一个分布式的方式合作项目Higress我们欣赏写得很好的详细的准确的问题报告。为了让沟通更高效我们希望每个人都可以搜索您的问题是否在搜索列表中。如果您发现它存在请在现有问题下的评论中添加您的详细信息而不是打开一个全新的问题。

View File

@@ -28,8 +28,7 @@ Security issues are always treated seriously. As our usual principle, we discour
## Reporting general issues
To be honest, we regard every user of Higress as a very kind contributor. After experiencing Higress, you may have
some feedback for the project. Then feel free to open an issue via [NEW ISSUE](https://github.
com/alibaba/higress/issues/new/choose).
some feedback for the project. Then feel free to open an issue via [NEW ISSUE](https://github.com/alibaba/higress/issues/new/choose).
Since we collaborate project Higress in a distributed way, we appreciate **WELL-WRITTEN**, **DETAILED**, **EXPLICIT** issue reports. To make the communication more efficient, we wish everyone could search if your issue is an existing one in the searching list. If you find it existing, please add your details in comments under the existing issue instead of opening a brand new one.

View File

@@ -139,8 +139,8 @@ install: pre-install
cd helm/higress; helm dependency build
helm install higress helm/higress -n higress-system --create-namespace --set 'global.local=true'
ENVOY_LATEST_IMAGE_TAG ?= 1.0.0-rc
ISTIO_LATEST_IMAGE_TAG ?= 1.0.0-rc
ENVOY_LATEST_IMAGE_TAG ?= 1.0.0
ISTIO_LATEST_IMAGE_TAG ?= 1.0.0
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.local=true'

View File

@@ -8,9 +8,10 @@
[![license](https://img.shields.io/github/license/alibaba/higress.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[**官网**](https://higress.io/) &nbsp; |
&nbsp; [**文档**](https://higress.io/zh-cn/docs/overview/what-is-higress.html) &nbsp; |
&nbsp; [**博客**](https://higress.io/zh-cn/blog/index.html) &nbsp; |
&nbsp; [**开发指引**](https://higress.io/zh-cn/docs/dev/code.html) &nbsp;
&nbsp; [**文档**](https://higress.io/zh-cn/docs/overview/what-is-higress) &nbsp; |
&nbsp; [**博客**](https://higress.io/zh-cn/blog) &nbsp; |
&nbsp; [**开发指引**](https://higress.io/zh-cn/docs/developers/developers_dev) &nbsp; |
&nbsp; [**Higress 企业版**](https://www.aliyun.com/product/aliware/mse?spm=higress-website.topbar.0.0.0) &nbsp;
<p>
@@ -20,15 +21,17 @@
Higress 是基于阿里内部两年多的 Envoy Gateway 实践沉淀,以开源 [Istio](https://github.com/istio/istio) 与 [Envoy](https://github.com/envoyproxy/envoy) 为核心构建的下一代云原生网关。Higress 实现了安全防护网关、流量网关、微服务网关三层网关合一,可以显著降低网关的部署和运维成本。
![arch](https://img.alicdn.com/imgextra/i4/O1CN01OgGP1728t0xeRfRYJ_!!6000000007989-0-tps-1726-1366.jpg)
![arch](https://img.alicdn.com/imgextra/i1/O1CN01iO9ph825juHbOIg75_!!6000000007563-2-tps-2483-2024.png)
## Summary
- [**功能展示**](#功能展示)
- [**使用场景**](#使用场景)
- [**核心优势**](#核心优势)
- [**Quick Start**](https://higress.io/zh-cn/docs/user/quickstart)
- [**社区**](#社区)
## 使用场景
- **Kubernetes Ingress 网关**:
@@ -73,6 +76,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)
## 社区

View File

@@ -4,6 +4,16 @@
Next-generation Cloud Native Gateway
</h1>
[![Build Status](https://github.com/alibaba/higress/workflows/build%20and%20codecov/badge.svg?branch=main)](https://github.com/alibaba/higress/actions)
[![license](https://img.shields.io/github/license/alibaba/higress.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[**Official Site**](https://higress.io/en-us/) &nbsp; |
&nbsp; [**Docs**](https://higress.io/en-us/docs/overview/what-is-higress) &nbsp; |
&nbsp; [**Blog**](https://higress.io/en-us/blog) &nbsp; |
&nbsp; [**Developer**](https://higress.io/en-us/docs/developers/developers_dev) &nbsp; |
&nbsp; [**Higress in Cloud**](https://www.alibabacloud.com/product/microservices-engine?spm=higress-website.topbar.0.0.0) &nbsp;
<p>
English | <a href="README.md">中文<a/>
</p>
@@ -13,7 +23,7 @@ Higress is a next-generation cloud-native gateway based on Alibaba's internal ga
Powered by [Istio](https://github.com/istio/istio) and [Envoy](https://github.com/envoyproxy/envoy), Higress realizes the integration of the triple gateway architecture of traffic gateway, microservice gateway and security gateway, thereby greatly reducing the costs of deployment, operation and maintenance.
<h1 align="center">
<img src="https://img.alicdn.com/imgextra/i1/O1CN01vnNawh26mU5C9py9w_!!6000000007704-0-tps-1726-1366.jpg" alt="Higress Architecture">
<img src="https://img.alicdn.com/imgextra/i1/O1CN01iO9ph825juHbOIg75_!!6000000007563-2-tps-2483-2024.png" alt="Higress Architecture">
</h1>

View File

@@ -1 +1 @@
v1.0.0-rc
v1.0.0

BIN
docs/images/domain.gif Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
docs/images/monitor.gif Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

BIN
docs/images/plugin.gif Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@@ -1,7 +1,8 @@
apiVersion: v2
appVersion: 1.0.0-rc
appVersion: 1.0.0
description: Helm chart for deploying higress gateways
icon: https://higress.io/img/higress_logo_small.png
home: http://higress.io/
keywords:
- higress
- gateways
@@ -9,4 +10,4 @@ name: higress-core
sources:
- http://github.com/alibaba/higress
type: application
version: 1.0.0-rc
version: 1.0.0

407
helm/core/LICENSE Normal file
View File

@@ -0,0 +1,407 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
========================================================================
Higress Subcomponents:
The Higress project contains subcomponents with separate copyright
notices and license terms. Your use of the source code for the these
subcomponents is subject to the terms and conditions of the following
licenses.
========================================================================
Apache-2.0 licenses
========================================================================
cloud.google.com/go v0.97.0 Apache-2.0
cloud.google.com/go/logging v1.4.2 Apache-2.0
contrib.go.opencensus.io/exporter/prometheus v0.4.0 Apache-2.0
github.com/Azure/go-autorest v14.2.0+incompatible Apache-2.0
github.com/Azure/go-autorest/autorest v0.11.20 Apache-2.0
github.com/Azure/go-autorest/autorest/adal v0.9.15 Apache-2.0
github.com/Azure/go-autorest/autorest/date v0.3.0 Apache-2.0
github.com/Azure/go-autorest/logger v0.2.1 Apache-2.0
github.com/Azure/go-autorest/tracing v0.6.0 Apache-2.0
github.com/Masterminds/goutils v1.1.1 Apache-2.0
github.com/aws/aws-sdk-go v1.41.7 Apache-2.0
github.com/census-instrumentation/opencensus-proto v0.3.0 Apache-2.0
github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa Apache-2.0
github.com/containerd/continuity v0.1.0 Apache-2.0
github.com/docker/cli v20.10.7+incompatible Apache-2.0
github.com/docker/distribution v0.0.0-20191216044856-a8371794149d Apache-2.0
github.com/docker/go-units v0.4.0 Apache-2.0
github.com/envoyproxy/protoc-gen-validate v0.1.0 Apache-2.0
github.com/go-logr/logr v0.4.0 Apache-2.0
github.com/go-openapi/jsonpointer v0.19.5 Apache-2.0
github.com/go-openapi/jsonreference v0.19.5 Apache-2.0
github.com/go-openapi/swag v0.19.14 Apache-2.0
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da Apache-2.0
github.com/google/btree v1.0.1 Apache-2.0
github.com/google/go-containerregistry v0.6.0 Apache-2.0
github.com/google/gofuzz v1.2.0 Apache-2.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 Apache-2.0
github.com/googleapis/gnostic v0.5.5 Apache-2.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 Apache-2.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 Apache-2.0
github.com/inconshreveable/mousetrap v1.0.0 Apache-2.0
github.com/jmespath/go-jmespath v0.4.0 Apache-2.0
github.com/jonboulle/clockwork v0.2.2 Apache-2.0
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 Apache-2.0
github.com/moby/moby v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible Apache-2.0
github.com/moby/spdystream v0.2.0 Apache-2.0
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 Apache-2.0
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd Apache-2.0
github.com/modern-go/reflect2 v1.0.1 Apache-2.0
github.com/opencontainers/go-digest v1.0.0 Apache-2.0
github.com/opencontainers/image-spec v1.0.1 Apache-2.0
github.com/opencontainers/runc v1.0.2 Apache-2.0
github.com/openshift/api v0.0.0-20200713203337-b2494ecb17dd Apache-2.0
github.com/prometheus/client_golang v1.11.0 Apache-2.0
github.com/prometheus/client_model v0.2.0 Apache-2.0
github.com/prometheus/common v0.32.1 Apache-2.0
github.com/prometheus/procfs v0.6.0 Apache-2.0
github.com/prometheus/statsd_exporter v0.21.0 Apache-2.0
github.com/spf13/cobra v1.2.1 Apache-2.0
go.opencensus.io v0.23.0 Apache-2.0
go.opentelemetry.io/proto/otlp v0.7.0 Apache-2.0
gomodules.xyz/jsonpatch/v2 v2.2.0 Apache-2.0
gomodules.xyz/jsonpatch/v3 v3.0.1 Apache-2.0
google.golang.org/appengine v1.6.7 Apache-2.0
google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a Apache-2.0
google.golang.org/grpc v1.42.0 Apache-2.0
gopkg.in/square/go-jose.v2 v2.6.0 Apache-2.0
gopkg.in/yaml.v2 v2.4.0 Apache-2.0
istio.io/gogo-genproto v0.0.0-20211115195057-0e34bdd2be67 Apache-2.0
k8s.io/api v0.22.2 Apache-2.0
k8s.io/apiextensions-apiserver v0.22.2 Apache-2.0
k8s.io/apimachinery v0.22.2 Apache-2.0
k8s.io/cli-runtime v0.22.2 Apache-2.0
k8s.io/client-go v0.22.2 Apache-2.0
k8s.io/component-base v0.22.2 Apache-2.0
k8s.io/klog/v2 v2.10.0 Apache-2.0
k8s.io/kube-openapi v0.0.0-20211020163157-7327e2aaee2b Apache-2.0
k8s.io/kubectl v0.22.2 Apache-2.0
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b Apache-2.0
sigs.k8s.io/controller-runtime v0.10.2 Apache-2.0
sigs.k8s.io/gateway-api v0.4.0 Apache-2.0
sigs.k8s.io/kustomize/api v0.8.11 Apache-2.0
sigs.k8s.io/kustomize/kyaml v0.11.0 Apache-2.0
sigs.k8s.io/mcs-api v0.1.0 Apache-2.0
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 Apache-2.0
========================================================================
BSD-2-Clause licenses
========================================================================
github.com/pkg/errors v0.9.1 BSD-2-Clause
github.com/russross/blackfriday v1.5.2 BSD-2-Clause
========================================================================
BSD-3-Clause licenses
========================================================================
github.com/PuerkitoBio/purell v1.1.1 BSD-3-Clause
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 BSD-3-Clause
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 BSD-3-Clause
github.com/evanphx/json-patch v4.11.0+incompatible BSD-3-Clause
github.com/evanphx/json-patch/v5 v5.6.0 BSD-3-Clause
github.com/fsnotify/fsnotify v1.5.1 BSD-3-Clause
github.com/gogo/protobuf v1.3.2 BSD-3-Clause
github.com/golang/protobuf v1.5.2 BSD-3-Clause
github.com/google/go-cmp v0.5.6 BSD-3-Clause
github.com/google/uuid v1.3.0 BSD-3-Clause
github.com/googleapis/gax-go/v2 v2.1.1 BSD-3-Clause
github.com/imdario/mergo v0.3.5 BSD-3-Clause
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de BSD-3-Clause
github.com/pmezard/go-difflib v1.0.0 BSD-3-Clause
github.com/spaolacci/murmur3 v1.1.0 BSD-3-Clause
github.com/spf13/pflag v1.0.5 BSD-3-Clause
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 BSD-3-Clause
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 BSD-3-Clause
golang.org/x/net v0.0.0-20211020060615-d418f374d309 BSD-3-Clause
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 BSD-3-Clause
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c BSD-3-Clause
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 BSD-3-Clause
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d BSD-3-Clause
golang.org/x/text v0.3.6 BSD-3-Clause
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac BSD-3-Clause
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 BSD-3-Clause
google.golang.org/api v0.59.0 BSD-3-Clause
google.golang.org/protobuf v1.27.1 BSD-3-Clause
gopkg.in/inf.v0 v0.9.1 BSD-3-Clause
========================================================================
ISC licenses
========================================================================
github.com/davecgh/go-spew v1.1.1 ISC
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 ISC
========================================================================
MIT licenses
========================================================================
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 MIT
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd MIT
github.com/Masterminds/semver/v3 v3.1.1 MIT
github.com/Masterminds/sprig/v3 v3.2.2 MIT
github.com/Microsoft/go-winio v0.5.0 MIT
github.com/Microsoft/hcsshim v0.8.21 MIT
github.com/beorn7/perks v1.0.1 MIT
github.com/cenkalti/backoff/v4 v4.1.1 MIT
github.com/cespare/xxhash/v2 v2.1.1 MIT
github.com/docker/docker-credential-helpers v0.6.3 MIT
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d MIT
github.com/fvbommel/sortorder v1.0.1 MIT
github.com/go-errors/errors v1.0.1 MIT
github.com/go-kit/log v0.1.0 MIT
github.com/go-logfmt/logfmt v0.5.0 MIT
github.com/goccy/go-json v0.4.8 MIT
github.com/golang-jwt/jwt/v4 v4.0.0 MIT
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 MIT
github.com/huandu/xstrings v1.3.2 MIT
github.com/josharian/intern v1.0.0 MIT
github.com/json-iterator/go v1.1.11 MIT
github.com/lestrrat-go/backoff/v2 v2.0.7 MIT
github.com/lestrrat-go/blackmagic v1.0.0 MIT
github.com/lestrrat-go/httpcc v1.0.0 MIT
github.com/lestrrat-go/iter v1.0.1 MIT
github.com/lestrrat-go/jwx v1.2.0 MIT
github.com/lestrrat-go/option v1.0.0 MIT
github.com/mailru/easyjson v0.7.6 MIT
github.com/mitchellh/copystructure v1.2.0 MIT
github.com/mitchellh/go-wordwrap v1.0.0 MIT
github.com/mitchellh/reflectwalk v1.0.2 MIT
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 MIT
github.com/natefinch/lumberjack v2.0.0+incompatible MIT
github.com/peterbourgon/diskv v2.0.1+incompatible MIT
github.com/shopspring/decimal v1.2.0 MIT
github.com/sirupsen/logrus v1.8.1 MIT
github.com/spf13/cast v1.3.1 MIT
github.com/stretchr/testify v1.7.0 MIT
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca MIT
github.com/yl2chen/cidranger v1.0.2 MIT
go.uber.org/atomic v1.9.0 MIT
go.uber.org/multierr v1.7.0 MIT
go.uber.org/zap v1.19.1 MIT
gomodules.xyz/orderedmap v0.1.0 MIT
========================================================================
MIT and Apache-2.0 licenses
========================================================================
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b MIT and Apache-2.0
========================================================================
MIT and BSD-3-Clause licenses
========================================================================
github.com/ghodss/yaml v1.0.0 MIT and BSD-3-Clause
sigs.k8s.io/yaml v1.3.0 MIT and BSD-3-Clause
========================================================================
MPL-2.0 licenses
========================================================================
github.com/hashicorp/errwrap v1.0.0 MPL-2.0
github.com/hashicorp/go-multierror v1.1.1 MPL-2.0
github.com/hashicorp/go-version v1.3.0 MPL-2.0
github.com/hashicorp/golang-lru v0.5.4 MPL-2.0

5
helm/core/README.md Normal file
View File

@@ -0,0 +1,5 @@
# Higress Core Helm Chart
Installs the core components of cloud-native gateway [Higress](http://higress.io/)
**Note:** It is highly recommended to install the whole package of Higress. Please visit https://higress.io/docs/user/quickstart/ for details.

View File

@@ -95,3 +95,9 @@ higress: {{ include "controller.name" . }}
{{- print "first-party-jwt" }}
{{- end }}
{{- end }}
{{- define "skywalking.enabled" -}}
{{- if and .Values.skywalking.enabled .Values.skywalking.service.address }}
true
{{- end }}
{{- end }}

View File

@@ -122,7 +122,7 @@ data:
{{- include "mesh" . }}
{{- end }}
---
{{- if .Values.enableSkywalking }}
{{- if include "skywalking.enabled" . }}
apiVersion: v1
kind: ConfigMap
metadata:
@@ -154,7 +154,6 @@ data:
"type": "LOGICAL_DNS",
"connect_timeout": "5s",
"http2_protocol_options": {
},
"dns_lookup_family": "V4_ONLY",
"lb_policy": "ROUND_ROBIN",
@@ -167,8 +166,8 @@ data:
"endpoint": {
"address": {
"socket_address": {
"address": "{{ .Values.Skywalking.address }}",
"port_value": "{{ .Values.Skywalking.port }}"
"address": "{{ .Values.skywalking.service.address }}",
"port_value": "{{ .Values.skywalking.service.port }}"
}
}
}

View File

@@ -1,3 +1,13 @@
{{- $unprivilegedPortSupported := true }}
{{- range $index, $node := (lookup "v1" "Node" "default" "").items }}
{{- $kernelVersion := $node.status.nodeInfo.kernelVersion }}
{{- if $kernelVersion }}
{{- $kernelVersion = regexFind "^(\\d+\\.\\d+\\.\\d+)" $kernelVersion }}
{{- if and $kernelVersion (semverCompare "<4.11.0" $kernelVersion) }}
{{- $unprivilegedPortSupported = false }}
{{- end }}
{{- end }}
{{- end -}}
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -50,7 +60,7 @@ spec:
securityContext:
{{- if .Values.gateway.securityContext }}
{{- toYaml .Values.gateway.securityContext | nindent 8 }}
{{- else if and (not .Values.gateway.hostNetwork) (semverCompare ">=1.22-0" .Capabilities.KubeVersion.GitVersion) }}
{{- else if and $unprivilegedPortSupported (and (not .Values.gateway.hostNetwork) (semverCompare ">=1.22-0" .Capabilities.KubeVersion.GitVersion)) }}
# Safe since 1.22: https://github.com/kubernetes/kubernetes/pull/103326
sysctls:
- name: net.ipv4.ip_unprivileged_port_start
@@ -71,7 +81,7 @@ spec:
securityContext:
{{- if .Values.gateway.containerSecurityContext }}
{{- toYaml .Values.gateway.containerSecurityContext | nindent 12 }}
{{- else if and (not .Values.gateway.hostNetwork) (semverCompare ">=1.22-0" .Capabilities.KubeVersion.GitVersion) }}
{{- else if and $unprivilegedPortSupported (and (not .Values.gateway.hostNetwork) (semverCompare ">=1.22-0" .Capabilities.KubeVersion.GitVersion)) }}
# Safe since 1.22: https://github.com/kubernetes/kubernetes/pull/103326
capabilities:
drop:
@@ -136,7 +146,7 @@ spec:
value: "{{ $.Values.clusterName | default `Kubernetes` }}"
- name: INSTANCE_NAME
value: "higress-gateway"
{{- if .Values.enableSkywalking }}
{{- if include "skywalking.enabled" . }}
- name: ISTIO_BOOTSTRAP_OVERRIDE
value: /etc/istio/custom-bootstrap/custom_bootstrap.json
{{- end }}
@@ -192,7 +202,7 @@ spec:
mountPath: /etc/istio/pod
- name: proxy-socket
mountPath: /etc/istio/proxy
{{- if .Values.enableSkywalking }}
{{- if include "skywalking.enabled" . }}
- mountPath: /etc/istio/custom-bootstrap
name: custom-bootstrap-volume
{{- end }}
@@ -232,7 +242,7 @@ spec:
- name: config
configMap:
name: higress-config
{{- if .Values.enableSkywalking }}
{{- if include "skywalking.enabled" . }}
- configMap:
defaultMode: 420
name: higress-custom-bootstrap

View File

@@ -45,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: 1.0.0-rc
tag: 1.0.0
# Specify image pull policy if default behavior isn't desired.
# Default behavior: latest images will be Always else IfNotPresent.
@@ -369,7 +369,7 @@ gateway:
name: "higress-gateway"
replicas: 2
image: gateway
tag: "1.0.0-rc"
tag: "1.0.0"
# revision declares which revision this gateway is a part of
revision: ""
@@ -457,7 +457,7 @@ controller:
name: "higress-controller"
replicas: 1
image: higress
tag: "1.0.0-rc"
tag: "1.0.0"
env: {}
labels: {}
@@ -547,7 +547,7 @@ pilot:
rollingMaxUnavailable: 25%
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
tag: 1.0.0-rc
tag: 1.0.0
# Can be a full hub/image:tag
image: pilot
@@ -610,7 +610,8 @@ pilot:
# Skywalking config settings
enableSkywalking: false
Skywalking:
address: "skywalking-oap.higress-system.svc"
port: 11800
skywalking:
enabled: false
service:
address: ~
port: 11800

View File

@@ -1,9 +1,9 @@
dependencies:
- name: higress-core
repository: file://../core
version: 1.0.0-rc
version: 1.0.0
- name: higress-console
repository: https://higress.io/helm-charts/
version: 0.2.0
digest: sha256:0a34765ab2125ccf397e81566b4d81a8dc0742a2477d225aad77d9450e4add94
generated: "2023-04-08T23:17:37.193119+08:00"
version: 1.0.0
digest: sha256:fb0f1b6816df5f5ac6888a93fb148b55b669affc9ac99336dd1ac818b8f84ace
generated: "2023-05-22T17:42:02.506864+08:00"

View File

@@ -1,7 +1,8 @@
apiVersion: v2
appVersion: 1.0.0-rc
description: Helm chart for deploying higress gateways
appVersion: 1.0.0
description: Helm chart for deploying Higress gateways
icon: https://higress.io/img/higress_logo_small.png
home: http://higress.io/
keywords:
- higress
- gateways
@@ -11,9 +12,9 @@ sources:
dependencies:
- name: higress-core
repository: "file://../core"
version: 1.0.0-rc
version: 1.0.0
- name: higress-console
repository: "https://higress.io/helm-charts/"
version: 0.2.0
version: 1.0.0
type: application
version: 1.0.0-rc
version: 1.0.0

407
helm/higress/LICENSE Normal file
View File

@@ -0,0 +1,407 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
========================================================================
Higress Subcomponents:
The Higress project contains subcomponents with separate copyright
notices and license terms. Your use of the source code for the these
subcomponents is subject to the terms and conditions of the following
licenses.
========================================================================
Apache-2.0 licenses
========================================================================
cloud.google.com/go v0.97.0 Apache-2.0
cloud.google.com/go/logging v1.4.2 Apache-2.0
contrib.go.opencensus.io/exporter/prometheus v0.4.0 Apache-2.0
github.com/Azure/go-autorest v14.2.0+incompatible Apache-2.0
github.com/Azure/go-autorest/autorest v0.11.20 Apache-2.0
github.com/Azure/go-autorest/autorest/adal v0.9.15 Apache-2.0
github.com/Azure/go-autorest/autorest/date v0.3.0 Apache-2.0
github.com/Azure/go-autorest/logger v0.2.1 Apache-2.0
github.com/Azure/go-autorest/tracing v0.6.0 Apache-2.0
github.com/Masterminds/goutils v1.1.1 Apache-2.0
github.com/aws/aws-sdk-go v1.41.7 Apache-2.0
github.com/census-instrumentation/opencensus-proto v0.3.0 Apache-2.0
github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa Apache-2.0
github.com/containerd/continuity v0.1.0 Apache-2.0
github.com/docker/cli v20.10.7+incompatible Apache-2.0
github.com/docker/distribution v0.0.0-20191216044856-a8371794149d Apache-2.0
github.com/docker/go-units v0.4.0 Apache-2.0
github.com/envoyproxy/protoc-gen-validate v0.1.0 Apache-2.0
github.com/go-logr/logr v0.4.0 Apache-2.0
github.com/go-openapi/jsonpointer v0.19.5 Apache-2.0
github.com/go-openapi/jsonreference v0.19.5 Apache-2.0
github.com/go-openapi/swag v0.19.14 Apache-2.0
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da Apache-2.0
github.com/google/btree v1.0.1 Apache-2.0
github.com/google/go-containerregistry v0.6.0 Apache-2.0
github.com/google/gofuzz v1.2.0 Apache-2.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 Apache-2.0
github.com/googleapis/gnostic v0.5.5 Apache-2.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 Apache-2.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 Apache-2.0
github.com/inconshreveable/mousetrap v1.0.0 Apache-2.0
github.com/jmespath/go-jmespath v0.4.0 Apache-2.0
github.com/jonboulle/clockwork v0.2.2 Apache-2.0
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 Apache-2.0
github.com/moby/moby v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible Apache-2.0
github.com/moby/spdystream v0.2.0 Apache-2.0
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 Apache-2.0
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd Apache-2.0
github.com/modern-go/reflect2 v1.0.1 Apache-2.0
github.com/opencontainers/go-digest v1.0.0 Apache-2.0
github.com/opencontainers/image-spec v1.0.1 Apache-2.0
github.com/opencontainers/runc v1.0.2 Apache-2.0
github.com/openshift/api v0.0.0-20200713203337-b2494ecb17dd Apache-2.0
github.com/prometheus/client_golang v1.11.0 Apache-2.0
github.com/prometheus/client_model v0.2.0 Apache-2.0
github.com/prometheus/common v0.32.1 Apache-2.0
github.com/prometheus/procfs v0.6.0 Apache-2.0
github.com/prometheus/statsd_exporter v0.21.0 Apache-2.0
github.com/spf13/cobra v1.2.1 Apache-2.0
go.opencensus.io v0.23.0 Apache-2.0
go.opentelemetry.io/proto/otlp v0.7.0 Apache-2.0
gomodules.xyz/jsonpatch/v2 v2.2.0 Apache-2.0
gomodules.xyz/jsonpatch/v3 v3.0.1 Apache-2.0
google.golang.org/appengine v1.6.7 Apache-2.0
google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a Apache-2.0
google.golang.org/grpc v1.42.0 Apache-2.0
gopkg.in/square/go-jose.v2 v2.6.0 Apache-2.0
gopkg.in/yaml.v2 v2.4.0 Apache-2.0
istio.io/gogo-genproto v0.0.0-20211115195057-0e34bdd2be67 Apache-2.0
k8s.io/api v0.22.2 Apache-2.0
k8s.io/apiextensions-apiserver v0.22.2 Apache-2.0
k8s.io/apimachinery v0.22.2 Apache-2.0
k8s.io/cli-runtime v0.22.2 Apache-2.0
k8s.io/client-go v0.22.2 Apache-2.0
k8s.io/component-base v0.22.2 Apache-2.0
k8s.io/klog/v2 v2.10.0 Apache-2.0
k8s.io/kube-openapi v0.0.0-20211020163157-7327e2aaee2b Apache-2.0
k8s.io/kubectl v0.22.2 Apache-2.0
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b Apache-2.0
sigs.k8s.io/controller-runtime v0.10.2 Apache-2.0
sigs.k8s.io/gateway-api v0.4.0 Apache-2.0
sigs.k8s.io/kustomize/api v0.8.11 Apache-2.0
sigs.k8s.io/kustomize/kyaml v0.11.0 Apache-2.0
sigs.k8s.io/mcs-api v0.1.0 Apache-2.0
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 Apache-2.0
========================================================================
BSD-2-Clause licenses
========================================================================
github.com/pkg/errors v0.9.1 BSD-2-Clause
github.com/russross/blackfriday v1.5.2 BSD-2-Clause
========================================================================
BSD-3-Clause licenses
========================================================================
github.com/PuerkitoBio/purell v1.1.1 BSD-3-Clause
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 BSD-3-Clause
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 BSD-3-Clause
github.com/evanphx/json-patch v4.11.0+incompatible BSD-3-Clause
github.com/evanphx/json-patch/v5 v5.6.0 BSD-3-Clause
github.com/fsnotify/fsnotify v1.5.1 BSD-3-Clause
github.com/gogo/protobuf v1.3.2 BSD-3-Clause
github.com/golang/protobuf v1.5.2 BSD-3-Clause
github.com/google/go-cmp v0.5.6 BSD-3-Clause
github.com/google/uuid v1.3.0 BSD-3-Clause
github.com/googleapis/gax-go/v2 v2.1.1 BSD-3-Clause
github.com/imdario/mergo v0.3.5 BSD-3-Clause
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de BSD-3-Clause
github.com/pmezard/go-difflib v1.0.0 BSD-3-Clause
github.com/spaolacci/murmur3 v1.1.0 BSD-3-Clause
github.com/spf13/pflag v1.0.5 BSD-3-Clause
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 BSD-3-Clause
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 BSD-3-Clause
golang.org/x/net v0.0.0-20211020060615-d418f374d309 BSD-3-Clause
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 BSD-3-Clause
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c BSD-3-Clause
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 BSD-3-Clause
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d BSD-3-Clause
golang.org/x/text v0.3.6 BSD-3-Clause
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac BSD-3-Clause
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 BSD-3-Clause
google.golang.org/api v0.59.0 BSD-3-Clause
google.golang.org/protobuf v1.27.1 BSD-3-Clause
gopkg.in/inf.v0 v0.9.1 BSD-3-Clause
========================================================================
ISC licenses
========================================================================
github.com/davecgh/go-spew v1.1.1 ISC
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 ISC
========================================================================
MIT licenses
========================================================================
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 MIT
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd MIT
github.com/Masterminds/semver/v3 v3.1.1 MIT
github.com/Masterminds/sprig/v3 v3.2.2 MIT
github.com/Microsoft/go-winio v0.5.0 MIT
github.com/Microsoft/hcsshim v0.8.21 MIT
github.com/beorn7/perks v1.0.1 MIT
github.com/cenkalti/backoff/v4 v4.1.1 MIT
github.com/cespare/xxhash/v2 v2.1.1 MIT
github.com/docker/docker-credential-helpers v0.6.3 MIT
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d MIT
github.com/fvbommel/sortorder v1.0.1 MIT
github.com/go-errors/errors v1.0.1 MIT
github.com/go-kit/log v0.1.0 MIT
github.com/go-logfmt/logfmt v0.5.0 MIT
github.com/goccy/go-json v0.4.8 MIT
github.com/golang-jwt/jwt/v4 v4.0.0 MIT
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 MIT
github.com/huandu/xstrings v1.3.2 MIT
github.com/josharian/intern v1.0.0 MIT
github.com/json-iterator/go v1.1.11 MIT
github.com/lestrrat-go/backoff/v2 v2.0.7 MIT
github.com/lestrrat-go/blackmagic v1.0.0 MIT
github.com/lestrrat-go/httpcc v1.0.0 MIT
github.com/lestrrat-go/iter v1.0.1 MIT
github.com/lestrrat-go/jwx v1.2.0 MIT
github.com/lestrrat-go/option v1.0.0 MIT
github.com/mailru/easyjson v0.7.6 MIT
github.com/mitchellh/copystructure v1.2.0 MIT
github.com/mitchellh/go-wordwrap v1.0.0 MIT
github.com/mitchellh/reflectwalk v1.0.2 MIT
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 MIT
github.com/natefinch/lumberjack v2.0.0+incompatible MIT
github.com/peterbourgon/diskv v2.0.1+incompatible MIT
github.com/shopspring/decimal v1.2.0 MIT
github.com/sirupsen/logrus v1.8.1 MIT
github.com/spf13/cast v1.3.1 MIT
github.com/stretchr/testify v1.7.0 MIT
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca MIT
github.com/yl2chen/cidranger v1.0.2 MIT
go.uber.org/atomic v1.9.0 MIT
go.uber.org/multierr v1.7.0 MIT
go.uber.org/zap v1.19.1 MIT
gomodules.xyz/orderedmap v0.1.0 MIT
========================================================================
MIT and Apache-2.0 licenses
========================================================================
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b MIT and Apache-2.0
========================================================================
MIT and BSD-3-Clause licenses
========================================================================
github.com/ghodss/yaml v1.0.0 MIT and BSD-3-Clause
sigs.k8s.io/yaml v1.3.0 MIT and BSD-3-Clause
========================================================================
MPL-2.0 licenses
========================================================================
github.com/hashicorp/errwrap v1.0.0 MPL-2.0
github.com/hashicorp/go-multierror v1.1.1 MPL-2.0
github.com/hashicorp/go-version v1.3.0 MPL-2.0
github.com/hashicorp/golang-lru v0.5.4 MPL-2.0

56
helm/higress/README.md Normal file
View File

@@ -0,0 +1,56 @@
# Higress Helm Chart
Installs the cloud-native gateway [Higress](http://higress.io/)
## Get Repo Info
```console
helm repo add higress.io https://higress.io/helm-charts
helm repo update
```
_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._
## Installing the Chart
To install the chart with the release name `higress`:
```console
helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes
```
## Uninstalling the Chart
To uninstall/delete the higress deployment:
```console
helm delete higress -n higress-system
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Configuration
| **Parameter** | **Description** | **Default** |
|---|---|---|
| **Global Parameters** | | |
| global.local | Set to `true` if installing to a local K8s cluster (e.g.: Kind, Rancher Desktop, etc.) | false |
| global.ingressClass | [IngressClass](https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/#ingress-class) which is used to filter Ingress resources Higress Controller watches.<br />If there are multiple gateway instances deployed in the cluster, this parameter can be used to distinguish the scope of each gateway instance.<br />There are some special cases for special IngressClass values:<br />1. If set to "nginx", Higress Controller will watch Ingress resources with the `nginx` IngressClass or without any Ingress class.<br />2. If set to empty, Higress Controller will watch all Ingress resources in the K8s cluster. | higress |
| global.watchNamespace | If not empty, Higress Controller will only watch resources in the specified namespace. When isolating different business systems using K8s namespace, if each namespace requires a standalone gateway instance, this parameter can be used to confine the Ingress watching of Higress within the given namespace. | "" |
| global.disableAlpnH2 | Whether to disable HTTP/2 in ALPN | true |
| global.enableStatus | If `true`, Higress Controller will update the `status` field of Ingress resources.<br />When migrating from Nginx Ingress, in order to avoid `status` field of Ingress objects being overwritten, this parameter needs to be set to false, so Higress won't write the entry IP to the `status` field of the corresponding Ingress object. | true |
| global.enableIstioAPI | If `true`, Higress Controller will monitor istio resources as well | false |
| global.istioNamespace | The namespace istio is installed to | istio-system |
| **Core Paramters** | | |
| higress-core.gateway.replicas | Number of Higress Gateway pods | 2 |
| higress-core.controller.replicas | Number of Higress Controller pods | 1 |
| **Console Paramters** | | |
| higress-console.replicaCount | Number of Higress Console pods | 1 |
| higress-console.service.type | K8s service type used by Higress Console | ClusterIP |
| higress-console.domain | Domain used to access Higress Console | console.higress.io |
| higress-console.tlsSecretName | Name of Secret resource used by TLS connections. | "" |
| higress-console.web.login.prompt | Prompt message to be displayed on the login page | "" |
| higress-console.admin.password.value | If not empty, the admin password will be configured to the specified value. | "" |
| higress-console.admin.password.length | The length of random admin password generated during installation. Only works when `higress-console.admin.password.value` is not set. | 8 |
| higress-console.o11y.enabled | If `true`, o11y suite (Grafana + Promethues) will be installed. | false |
| higress-console.pvc.rwxSupported | Set to `false` when installing to a standard K8s cluster and the target cluster doesn't support the ReadWriteMany access mode of PersistentVolumeClaim. | true |

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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)
}

View File

@@ -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 {

View File

@@ -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")
}

View File

@@ -75,6 +75,20 @@ func (u upstreamTLS) Parse(annotations Annotations, config *Ingress, _ *GlobalCo
}
}
if sslVerify, err := annotations.ParseStringASAP(proxySSLVerify); err == nil {
if OnOffRegex.MatchString(sslVerify) {
upstreamTLSConfig.SSLVerify = onOffToBool(sslVerify)
}
}
upstreamTLSConfig.SNI, _ = annotations.ParseStringASAP(proxySSLName)
if enableSNI, err := annotations.ParseStringASAP(proxySSLServerName); err == nil {
if OnOffRegex.MatchString(enableSNI) {
upstreamTLSConfig.EnableSNI = onOffToBool(enableSNI)
}
}
secretName, _ := annotations.ParseStringASAP(proxySSLSecret)
namespacedName := util.SplitNamespacedName(secretName)
if namespacedName.Name == "" {
@@ -86,32 +100,19 @@ func (u upstreamTLS) Parse(annotations Annotations, config *Ingress, _ *GlobalCo
}
upstreamTLSConfig.SecretName = namespacedName.String()
if sslVerify, err := annotations.ParseStringASAP(proxySSLVerify); err == nil {
if OnOffRegex.MatchString(sslVerify) {
upstreamTLSConfig.SSLVerify = onOffToBool(sslVerify)
}
}
upstreamTLSConfig.SNI, _ = annotations.ParseStringASAP(proxySSLName)
if enableSNI, err := annotations.ParseStringASAP(proxySSLServerName); err == nil {
if OnOffRegex.MatchString(enableSNI) {
upstreamTLSConfig.SSLVerify = onOffToBool(enableSNI)
}
}
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 {

View File

@@ -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)
}

View File

@@ -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 {

View File

@@ -848,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)
}
}
@@ -871,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),
},
@@ -895,7 +908,6 @@ func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions,
}
}
}
return nil
}

View File

@@ -848,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)
}
}
@@ -871,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),
},
@@ -895,7 +908,6 @@ func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions,
}
}
}
return nil
}

View File

@@ -0,0 +1,286 @@
# Function Description
The `hmac-auth` plugin implements the generation of tamper-proof signatures for HTTP requests based on HMAC algorithm, and uses the signature for identity authentication and authorization.
# Configuration Fields
| Name | Data Type | Required | Default | Description |
| ------------- | --------------- | -------------| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `consumers` | array of object | Required | - | Configures the caller of the service to authenticate the request. |
| `date_offset` | number | Optional | - | Configures the maximum allowed time deviation of the client, in seconds. It is used to parse the client's UTC time from `the Date` header of the request, and can be used to prevent replay attacks. If not configured, no validation is performed. |
| `_rules_` | array of object | Optional | - | Configures the access control list for specific routes or domains, used for authorization of requests. |
The configuration fields for each item in `consumers` are as follows :
| Name | Data Type| Required | Default| Description |
| -------- | -------- | ------------ | ------ | ----------------------------------------------------------------------- |
| `key` | string | Required | - | Configures the key extracted from the `x-ca-key` header of the request. |
| `secret` | string | Required | - | Configures the secret used to generate the signature. |
| `name` | string | Required | - | Configures the name of the consumer. |
The configuration fields for each item in `_rules_` are as follows:
| Name | Data Type | Required | Default | Description |
| ---------------- | --------------- | ------------------------------------------------- | ---------------------------- | -------------------------------------------------- |
| `_match_route_` | array of string | Optional, either `_match_route_` or `_match_domain_` must be provided | - | Configures the name of the route to match. |
| `_match_domain_` | array of string | Optional, either `_match_route_` or `_match_domain_` must be provided | - | Configures the name of the domain to match. |
| `allow` | array of string | Required | - | Configures the name of the consumer to allow for requests that match the specified route or domain. |
**Note**
- If `_rules_` is not configured, authentication is enabled for all routes on the current gateway instance by default
- For requests that pass authentication and authorization, a `X-Mse-Consumer` header will be added to the request headers to identify the name of the consumer.
# Configuration Example
The following configuration enables Hmac Auth authentication and authorization for specific routes or domains on the gateway. Note that the `key` field should not be duplicated.
## Enabling for specific routes or domains
```yaml
consumers:
- key: appKey-example-1
secret: appSecret-example-1
name: consumer-1
- key: appKey-example-2
secret: appSecret-example-2
name: consumer-2
# Configuring Fine-Grained Rules using _rules_ Field
_rules_:
# Rule 1: Matching by route name.
- _match_route_:
- route-a
- route-b
allow:
- consumer-1
# Rule 2: Applies based on domain name matching.
- _match_domain_:
- "*.example.com"
- test.com
allow:
- consumer-2
```
The `allow` field under each matching rule specifies the list of callers allowed to access under that matching condition;
In this example, `route-a` and `route-b` specified in `_match_route_` are the route names filled in when creating the gateway route. When either of these routes is matched, it will allow access to the caller named `consumer-1`, while denying access to other callers
In` _match_domain_`, `*.example.com` and `test.com` are used to match the requested domain name. When a match is found, it will allow access to the caller named `consumer-2`, while denying access to other callers
Upon successful authentication, the `X-Mse-Consumer` field will be added to the request header with the value set to the caller's name, such as `consumer-1`.。
## Enable at the Gateway Instance Level
The following configuration enables HMAC authentication at the gateway instance level.
```yaml
consumers:
- key: appKey-example-1
secret: appSecret-example-1
name: consumer-1
- key: appKey-example-2
secret: appSecret-example-2
name: consumer-2
```
# Description of Signing Mechanism
## Configuration Preparation
As mentioned in the guide above, configure the credential settings required for generating and validating signatures in the plugin configuration.
- key: Used for setting in the request header `x-ca-key`.
- secret: Used for generating the request signature.
## Client Signature Generation Method
### Overview of the Process
The process for generating a signature on the client side consists of three steps:
1. Extracting key data from the original request to obtain a string to be signed.
2. Using encryption algorithms and the configured `secret` to encrypt the key data signing string and obtain a signature.
3. Adding all headers related to the signature to the original HTTP request to obtain the final HTTP request.
As shown below :
![](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/1745707061/p188113.png)
### Process for Extracting Signing String
To generate a signature, the client needs to extract key data from the HTTP request and combine it into a signing string. The format of the generated signing string is as follows:
```text
HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters
```
The signing string consists of the above 7 fields separated by \n. If Headers is empty, no \n is needed. If other fields are empty, the \n should still be retained. The signature is case-sensitive. Below are the rules for extracting each field:
- HTTPMethod: The HTTP method used in the request, in all capital letters, such as POST.
- Accept: The value of the Accept header in the request, which can be empty. It is recommended to explicitly set the Accept header. When Accept is empty, some HTTP clients will set the default value of `*/*`, which may cause signature verification to fail.
- Content-MD5: The value of the Content-MD5 header in the request, which can be empty. It is only calculated when there is a non-form body in the request. The following is a reference calculation method for Content-MD5 values in
```java
String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
```
- Content-Type: The value of the Content-Type header in the request, which can be empty.
- Date: The value of the Date header in the request. When the` date_offset` configuration is not enabled, it can be empty. Otherwise, it will be used for time offset verification.
- Headers: Users can select specific headers to participate in the signature. There are the following rules for concatenating the signature string with headers:
- The keys of the headers participating in the signature calculation are sorted in alphabetical order and concatenated as follows:
```text
HeaderKey1 + ":" + HeaderValue1 + "\n"\+
HeaderKey2 + ":" + HeaderValue2 + "\n"\+
...
HeaderKeyN + ":" + HeaderValueN + "\n"
```
- If the value of a header is empty, it will participate in the signature with the `HeaderKey+":"+"\n"` only, and the key and english colon should be retained.
- The set of keys for all headers participating in the signature is separated by a comma and placed in the `X-Ca-Signature-Headers header`.
- The following headers are not included in the header signature calculation: X-Ca-Signature, X-Ca-Signature-Headers, Accept, Content-MD5, Content-Type, Date.
- PathAndParameters: This field contains all parameters in the path, query, and form. The specific format is as follows:
```text
Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
```
Notes:
1. The keys of the query and form parameter pairs are sorted alphabetically, and the same format as above is used for concatenation.
2. If there are no query and form parameters, use the path directly without adding `?` .
3. If the value of a parameter is empty, only the key will be included in the signature. The equal sign should not be included in the signature.
4. If there are array parameters in the query or form (parameters with the same key but different values), only the first value should be included in the signature calculation.
### Example of Extracting Signing String
The initial HTTP request :
```text
POST /http2test/test?param1=test HTTP/1.1
host:api.aliyun.com
accept:application/json; charset=utf-8
ca_version:1
content-type:application/x-www-form-urlencoded; charset=utf-8
x-ca-timestamp:1525872629832
date:Wed, 09 May 2018 13:30:29 GMT+00:00
user-agent:ALIYUN-ANDROID-DEMO
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
content-length:33
username=xiaoming&password=123456789
```
The correct generated signature string is :
```text
POST
application/json; charset=utf-8
application/x-www-form-urlencoded; charset=utf-8
Wed, 09 May 2018 13:30:29 GMT+00:00
x-ca-key:203753385
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
x-ca-signature-method:HmacSHA256
x-ca-timestamp:1525872629832
/http2test/test?param1=test&password=123456789&username=xiaoming
```
### Signature Calculation Process
After extracting the key data from the HTTP request and assembling it into a signature string, the client needs to encrypt and encode the signature string to form the final signature.
The specific encryption format is as follows, where `stringToSign` is the extracted signature string, `secret` is the one filled in the plugin configuration, and `sign` is the final generated signature:
```java
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] secretBytes = secret.getBytes("UTF-8");
hmacSha256.init(new SecretKeySpec(secretBytes, 0, secretBytes.length, "HmacSHA256"));
byte[] result = hmacSha256.doFinal(stringToSign.getBytes("UTF-8"));
String sign = Base64.encodeBase64String(result);
```
In summary, the `stringToSign` is decoded using UTF-8 to obtain a Byte array. Then, an encryption algorithm is used to encrypt the Byte array, and finally, the Base64 algorithm is used to encode the encrypted data, resulting in the final signature.
### The Process of Adding a Signature
The client needs to include the following four headers in the HTTP request to be transmitted to the API gateway for signature verification:
- x-ca-key: The value is the APP Key and is required.
- x-ca-signature-method: The signature algorithm, the value can be HmacSHA256 or HmacSHA1, optional. The default value is HmacSHA256.
- x-ca-signature-headers: The collection of keys for all signature headers, separated by commas. Optional.
- x-ca-signature: The signature and it is required.
Here is an example of a complete HTTP request with a signature :
```text
POST /http2test/test?param1=test HTTP/1.1
host:api.aliyun.com
accept:application/json; charset=utf-8
ca_version:1
content-type:application/x-www-form-urlencoded; charset=utf-8
x-ca-timestamp:1525872629832
date:Wed, 09 May 2018 13:30:29 GMT+00:00
user-agent:ALIYUN-ANDROID-DEMO
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
x-ca-key:203753385
x-ca-signature-method:HmacSHA256
x-ca-signature-headers:x-ca-timestamp,x-ca-key,x-ca-nonce,x-ca-signature-method
x-ca-signature:xfX+bZxY2yl7EB/qdoDy9v/uscw3Nnj1pgoU+Bm6xdM=
content-length:33
username=xiaoming&password=123456789
```
## Server-side Signature Verification Method
### Overview of the Process
The server-side signature verification of the client's request involves four steps :
1. Extract crucial data from the received request to obtain a string for signing.
2. Retrieve the `key` from the received request and use it to query its corresponding `secret`.
3. Encrypt the string for signing using the encryption algorithm and `secret`.
4. Retrieve the client's signature from the received request, and compare the consistency of the server-side signature with the client's signature.
As shown below :
![](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/1745707061/p188116.png)
## Troubleshooting Signature Errors
When the gateway signature verification fails, the server-side signing string (StringToSign) will be returned to the client in the HTTP Response Header. The key is X-Ca-Error-Message. Users only need to compare the locally calculated signing string with the server-side signing string returned to locate the problem;
If the StringToSign on the server side is consistent with that on the client side, please check whether the APP Secret used for signature calculation is correct
Because line breaks cannot be represented in HTTP headers, all line breaks in the StringToSign are replaced with #, as shown below:
```text
X-Ca-Error-Message: Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`
```
# Related Error Codes
| HTTP Status Code | Error Message | Reason |
| ----------- | ---------------------- | -------------------------------------------------------------------------------- |
| 401 | Invalid Key | The x-ca-key request header is not provided or is invalid. |
| 401 | Empty Signature | The x-ca-signature request header does not contain a signature. |
| 400 | Invalid Signature | The x-ca-signature request header contains a signature that does not match the server-calculated signature. |
| 400 | Invalid Content-MD5 | The content-md5 request header is incorrect. |
| 400 | Invalid Date | The time offset calculated based on the date request header exceeds the configured date_offset. |
| 413 | Request Body Too Large | The request body exceeds the size limit of 32 MB. |
| 413 | Payload Too Large | The request body exceeds the DownstreamConnectionBufferLimits global configuration. |
| 403 | Unauthorized Consumer | The requesting party does not have access permission. |

View File

@@ -244,12 +244,14 @@ public class GenerateJwtDemo {
- 只有当`from_headers`,`from_params`,`from_cookies`均未配置时,才会使用默认值
`from_headers` 中每一项的配置字段说明如下:
| 名称 | 数据类型 | 填写要求| 默认值 | 描述 |
| ---------------- | --------------- | ------- | ------ | --------------------------------------------------------- |
| `name` | string | 必填 | - | 抽取JWT的请求header |
| `value_prefix` | string | 必填 | - | 对请求header的value去除此前缀剩余部分作为JWT |
`claims_to_headers` 中每一项的配置字段说明如下:
| 名称 | 数据类型 | 填写要求| 默认值 | 描述 |
| ---------------- | --------------- | ------- | ------ | --------------------------------------------------------- |
| `claim` | string | 必填 | - | JWT payload中的指定字段要求必须是字符串或无符号整数类型 |

View File

@@ -390,10 +390,10 @@ consumers:
```
# Common Error Codes
|
HTTP Status Code | Error Message | Reason Description|
| ----------- | ---------------------- | -------------------------------------------------------------------------------- |
| 401 | JWT missing | The JWT is not provided in the request header. |
| 401 | JWT expired | The JWT has expired. |
| 401 | JWT verification fails | The JWT payload verification failed, such as the iss mismatch. |
| 403 | Access denied | Access to the current route is denied. |
| HTTP Status Code | Error Message | Reason Description|
|------------------| ---------------------- | -------------------------------------------------------------------------------- |
| 401 | JWT missing | The JWT is not provided in the request header. |
| 401 | JWT expired | The JWT has expired. |
| 401 | JWT verification fails | The JWT payload verification failed, such as the iss mismatch. |
| 403 | Access denied | Access to the current route is denied. |

View File

@@ -14,6 +14,7 @@
| limit_keys | array of object | 必填 | - | 配置匹配键值后的限流次数 |
`limit_keys`中每一项的配置字段说明
| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
| -------- | -------- | -------- | -------- | -------- |
| key | string | 必填 | - | 匹配的键值 |

View File

@@ -14,6 +14,7 @@
| limit_keys | array of object | Required | - | Rate-limiting thresholds when matching specific key-values |
Field descriptions of `limit_keys` items:
| Name | Type | Requirement | Default Value | Description |
| -------- | -------- | -------- | -------- | -------- |
| key | string | Required | - | Value to match of the specific key |

View File

@@ -1,6 +1,10 @@
ARG BUILDER=higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/wasm-go-builder:go1.19-tinygo0.27.0
ARG BUILDER=higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/wasm-go-builder:go1.19-tinygo0.25.0-oras1.0.0
FROM $BUILDER as builder
ARG GOPROXY
ENV GOPROXY=${GOPROXY}
ARG PLUGIN_NAME=hello-world
WORKDIR /workspace

View File

@@ -1,84 +1,115 @@
# The Dockerfile for wasm-go builder only support amd64 and arm64 yet.
# If you want to build on another architecture, the following information may be helpful.
#
# - arch: amd64 \
# - arch: amd64
# base image: docker.io/ubuntu
# go_url: https://golang.google.cn/dl/go1.20.1.linux-amd64.tar.gz"
# tinygo_url: https://github.com/tinygo-org/tinygo/releases/download/v0.27.0/tinygo_0.27.0_amd64.deb
# tinygo_url: https://github.com/alibaba/higress/releases/download/v1.0.0-rc/higress-tinygo0.25.0.linux-amd64.tar.gz
# oras_url: https://github.com/oras-project/oras/releases/download/v1.0.0/oras_1.0.0_linux_amd64.tar.gz
#
# - arch: arm64
# base image: docker.io/ubuntu
# go_url: https://golang.google.cn/dl/go1.20.1.linux-arm64.tar.gz
# tinygo_url: https://github.com/tinygo-org/tinygo/releases/download/v0.27.0/tinygo_0.27.0_arm64.deb
# tinygo_url: https://github.com/alibaba/higress/releases/download/v1.0.0-rc/higress-tinygo0.25.0.linux-arm64.tar.gz
# oras_url: https://github.com/oras-project/oras/releases/download/v1.0.0/oras_1.0.0_linux_arm64.tar.gz
#
# - arch: armel
# base image: build yourself
# go_url: install from source code
# tinygo_url: build yourself
# oras_url: build your self
#
# - arch: i386
# base image: build yourself
# go_url: https://dl.google.com/go/go1.20.1.linux-386.tar.gz
# tinygo_url: build yourself
# oras_url: build your self
#
# - arch: mips64el
# base image: build your self
# go_url: https://dl.google.com/go/go1.20.1.linux-386.tar.gz
# tinygo_url: build your self
# oras_url: build your self
#
# - arch: ppc64el
# base image: build your self
# go_url: https://dl.google.com/go/go1.20.1.linux-ppc64le.tar.gz
# tinygo_url: build your self
# oras_url: build your self
#
# - arch: s390x
# base image: docker.io/ubuntu
# go_url: https://dl.google.com/go/go1.20.1.linux-s390x.tar.gz
# tinygo_url: build your self
# oras_url: build your self
#
# - arch: armhf
# base image: build your self
# go_url: https://golang.google.cn/dl/go1.20.1.linux-armv6l.tar.gz
# tinygo_url: https://github.com/tinygo-org/tinygo/releases/download/v0.27.0/tinygo_0.27.0_armhf.deb
# tinygo_url: https://github.com/tinygo-org/tinygo/releases/download/v0.25.0/tinygo_0.25.0_armhf.deb
# oras_url: build your self
ARG BASE_IMAGE=docker.io/ubuntu
FROM $BASE_IMAGE
ARG GO_VERSION
ARG TINYGO_VERSION
ARG ORAS_VERSION
ARG HIGRESS_VERSION
ARG USE_HIGRESS_TINYGO
LABEL go_version=$GO_VERSION tinygo_version=$TINYGO_VERSION
LABEL go_version=$GO_VERSION tinygo_version=$TINYGO_VERSION oras_version=$ORAS_VERSION
RUN apt-get update \
&& apt-get install -y wget build-essential \
&& apt-get install -y wget \
&& rm -rf /var/lib/apt/lists/*
RUN arch="$(dpkg --print-architecture)"; arch="${arch##*-}"; \
go_url=; \
go_url=; \
tinygo_url=; \
go_version=${GO_VERSION:-1.19}; \
tinygo_version=${TINYGO_VERSION:-0.27.0}; \
tinygo_version=${TINYGO_VERSION:-0.25.0}; \
oras_version=${ORAS_VERSION:-1.0.0}; \
higress_version=${HIGRESS_VERSION:-1.0.0-rc}; \
use_higress_tinygo=${USE_HIGRESS_TINYGO:-false}; \
echo "arch: '$arch'"; \
echo "go go_version: '$go_version'"; \
echo "tinygo_version: '$tinygo_version'"; \
case "$arch" in \
'amd64') \
echo "oras_version: '$oras_version'"; \
echo "higress_version: '$higress_version'"; \
echo "use_higress_tinygo: '$use_higress_tinygo'"; \
case "$arch" in \
'amd64') \
go_url="https://golang.google.cn/dl/go$go_version.linux-amd64.tar.gz"; \
tinygo_url="https://github.com/tinygo-org/tinygo/releases/download/v$tinygo_version/tinygo_${tinygo_version}_amd64.deb"; \
;; \
'arm64') \
if [ "$use_higress_tinygo" = "true" ]; \
then \
tinygo_url="https://github.com/alibaba/higress/releases/download/v$higress_version/higress-tinygo${tinygo_version}.linux-amd64.tar.gz"; \
else \
tinygo_url="https://github.com/tinygo-org/tinygo/releases/download/v$tinygo_version/tinygo${tinygo_version}.linux-amd64.tar.gz"; \
fi; \
oras_url="https://github.com/oras-project/oras/releases/download/v$oras_version/oras_${oras_version}_linux_amd64.tar.gz"; \
;; \
'arm64') \
go_url="https://golang.google.cn/dl/go$go_version.linux-arm64.tar.gz"; \
tinygo_url="https://github.com/tinygo-org/tinygo/releases/download/v$tinygo_version/tinygo_${tinygo_version}_arm64.deb"; \
;; \
*) echo >&2 "error: unsupported architecture '$arch' "; exit 1 ;; \
esac; \
if [ "$use_higress_tinygo" = "true" ]; \
then \
tinygo_url="https://github.com/alibaba/higress/releases/download/v$higress_version/higress-tinygo${tinygo_version}.linux-arm64.tar.gz"; \
else \
tinygo_url="https://github.com/tinygo-org/tinygo/releases/download/v$tinygo_version/tinygo${tinygo_version}.linux-arm64.tar.gz"; \
fi; \
oras_url="https://github.com/oras-project/oras/releases/download/v$oras_version/oras_${oras_version}_linux_arm64.tar.gz"; \
;; \
*) echo >&2 "error: unsupported architecture '$arch' "; exit 1 ;; \
esac; \
echo "go_url: '$go_url'"; \
echo "tinygo_url: '$tinygo_url'"; \
wget -O go.tgz "$go_url" --progress=dot:giga; \
wget -O tinygo.deb "$tinygo_url" --progress=dot:giga; \
echo "Download complete"; \
rm -rf /usr/local/go && tar -C /usr/local -xzf go.tgz && rm -rf go.tgz; \
dpkg -i tinygo.deb && rm -rf tinygo.deb
echo "tinygo_url: '$tinygo_url'"; \
wget -O tinygo.tgz "$tinygo_url" --progress=dot:giga; \
rm -rf /usr/local/tinygo && tar -C /usr/local -xzf tinygo.tgz && rm -rf tinygo.tgz; \
echo "oras_url: '$oras_url'"; \
wget -O oras.tgz "$oras_url" --progress=dot:giga; \
tar -C /usr/local/bin -xzf oras.tgz && rm -rf oras.tgz; \
echo "done";
ENV PATH=$PATH:/usr/local/go/bin:/usr/local/bin
ENV PATH=$PATH:/usr/local/go/bin:/usr/local/tinygo/bin:/usr/local/bin

View File

@@ -1,41 +1,58 @@
PLUGIN_NAME ?= hello-world
REGISTRY ?= higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/
GO_VERSION ?= 1.19
TINYGO_VERSION ?= 0.27.0
BUILDER ?= ${REGISTRY}wasm-go-builder:go${GO_VERSION}-tinygo${TINYGO_VERSION}
TINYGO_VERSION ?= 0.25.0
ORAS_VERSION ?= 1.0.0
HIGRESS_VERSION ?= 1.0.0-rc
USE_HIGRESS_TINYGO ?= true
BUILDER ?= ${REGISTRY}wasm-go-builder:go${GO_VERSION}-tinygo${TINYGO_VERSION}-oras${ORAS_VERSION}
BUILD_TIME := $(shell date "+%Y%m%d-%H%M%S")
COMMIT_ID := $(shell git rev-parse --short HEAD 2>/dev/null)
IMG ?= ${REGISTRY}${PLUGIN_NAME}:${BUILD_TIME}-${COMMIT_ID}
IMAGE_TAG = $(if $(strip $(PLUGIN_VERSION)),${PLUGIN_VERSION},${BUILD_TIME}-${COMMIT_ID})
IMG ?= ${REGISTRY}${PLUGIN_NAME}:${IMAGE_TAG}
GOPROXY := $(shell go env GOPROXY)
.DEFAULT:
build:
DOCKER_BUILDKIT=1 docker build --build-arg PLUGIN_NAME=${PLUGIN_NAME} \
--build-arg BUILDER=${BUILDER} \
--build-arg GOPROXY=$(GOPROXY) \
-t ${IMG} \
--output extensions/${PLUGIN_NAME} \
.
@echo ""
@echo "image: ${IMG}"
@echo "output wasm file: extensions/${PLUGIN_NAME}/plugin.wasm"
build-push: build
build-image:
DOCKER_BUILDKIT=1 docker build --build-arg PLUGIN_NAME=${PLUGIN_NAME} \
--build-arg BUILDER=${BUILDER} \
--build-arg GOPROXY=$(GOPROXY) \
-t ${IMG} \
--load \
.
@echo ""
@echo "image: ${IMG}"
build-push: build-image
docker push ${IMG}
# builder:
# To build a wasm-go-builder image.
# e.g.
# REGISTRY=<your_docker_registry> make builder
# If you want to use Go/TinyGo with another version, please modify GO_VERSION/TINYGO_VERSION.
# If you want to use Go/TinyGo/Oras with another version, please modify GO_VERSION/TINYGO_VERSION/ORAS_VERSION.
# After your wasm-go-builder image is built, you can use it to build plugin image.
# e.g.
# PLUGIN_NAME=request-block BUILDER=<your-wasm-go-builder> make
builder:
BUILDER=$(REGISTRY)wasm-go-builder:go$(GO_VERSION)-tinygo$(TINYGO_VERSION)
docker buildx build --no-cache \
--platform linux/amd64,linux/arm64 \
--build-arg BASE_IMAGE=docker.io/ubuntu \
--build-arg GO_VERSION=$(GO_VERSION) \
--build-arg TINYGO_VERSION=$(TINYGO_VERSION) \
--build-arg ORAS_VERSION=$(ORAS_VERSION) \
--build-arg HIGRESS_VERSION=$(HIGRESS_VERSION) \
--build-arg USE_HIGRESS_TINYGO=$(USE_HIGRESS_TINYGO) \
-f DockerfileBuilder \
-t ${BUILDER} \
--push \

View File

@@ -0,0 +1,195 @@
# DeGraphQL
## GraphQL
### GraphQL 端点
REST API 有多个端点GraphQL API 只有一个端点。
```shell
https://api.github.com/graphql
```
### 与 GraphQL 通信
由于 GraphQL 操作由多行 JSON 组成,可以使用 curl 或任何其他采用 HTTP 的库。
在 REST 中HTTP 谓词确定执行的操作。 在 GraphQL 中,执行查询要提供 JSON 请求体,因此 HTTP 谓词为 POST。 唯一的例外是内省查询,它是一种简单的 GET 到终结点查询。
### GraphQL POST 请求参数
标准的 GraphQL POST 请求情况如下:
- 添加 HTTP 请求头: Content-Type: application/json
- 使用 JSON 格式的请求体
- JSON 请求体包含三个字段
- query查询文档必填
- variables变量选填
- operationName操作名称选填查询文档有多个操作时必填
```json
{
"query": "{viewer{name}}",
"operationName": "",
"variables": {
"name": "value"
}
}
```
### GraphQL 基本参数类型
- 基本参数类型包含: String, Int, Float, Boolean
- [类型]代表数组,例如:[Int]代表整型数组
- GraphQL 基本参数传递
- 小括号内定义形参,注意:参数需要定义类型
- !(叹号)代表参数不能为空
```shell
query ($owner : String!, $name : String!) {
repository(owner: $owner, name: $name) {
name
forkCount
description
}
}
```
### GitHub GraphQL 测试
使用 curl 命令查询 GraphQL 用有效 JSON 请求体发出 POST 请求。 有效请求体必须包含一个名为 query 的字符串。
```shell
curl https://api.github.com/graphql -X POST \
-H "Authorization: bearer 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" \
-d "{\"query\": \"query { viewer { login }}\"}"
{
"data": {
"viewer": {
"login": "2456868764"
}
}
}
```
```shell
curl 'https://api.github.com/graphql' -X POST \
-H 'Authorization: bearer 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' \
-d '{"query":"query ($owner: String!, $name: String!) {\n repository(owner: $owner, name: $name) {\n name\n forkCount\n description\n }\n}\n","variables":{"owner":"2456868764","name":"higress"}}'
{
"data": {
"repository": {
"name": "higress",
"forkCount": 149,
"description": "Next-generation Cloud Native Gateway | 下一代云原生网关"
}
}
}
```
## DeGraphQL 插件
### 参数配置
| 参数 | 描述 | 默认 |
|:----------------|:------------------------|:-----------|
| `gql` | graphql 查询 | 不能为空 |
| `endpoint` | graphql 查询端点 | `/graphql` |
| `timeout` | 查询连接超时,单位毫秒 | `5000` |
| `domain` | 服务域名当服务来源是dns配置 | |
### 插件使用
https://github.com/alibaba/higress/issues/268
- 测试配置
```yaml
apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
name: default
namespace: higress-system
spec:
registries:
- domain: api.github.com
name: github
port: 443
type: dns
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.io/destination: github.dns
higress.io/upstream-vhost: "api.github.com"
higress.io/backend-protocol: HTTPS
name: github-api
namespace: higress-system
spec:
ingressClassName: higress
rules:
- http:
paths:
- backend:
resource:
apiGroup: networking.higress.io
kind: McpBridge
name: default
path: /api
pathType: Prefix
---
apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
name: de-graphql-github-api
namespace: higress-system
spec:
matchRules:
- ingress:
- github-api
config:
timeout: 5000
endpoint: /graphql
domain: api.github.com
gql: |
query ($owner:String! $name:String!){
repository(owner:$owner, name:$name) {
name
forkCount
description
}
}
url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/de-graphql:1.0.0
```
- 测试结果
```shell
curl "http://localhost/api?owner=alibaba&name=higress" -H "Authorization: Bearer some-token"
{
"data": {
"repository": {
"description": "Next-generation Cloud Native Gateway",
"forkCount": 149,
"name": "higress"
}
}
}
```
## 参考文档
- https://github.com/graphql/graphql-spec
- https://docs.github.com/zh/graphql/guides/forming-calls-with-graphql
- https://github.com/altair-graphql/altair

View File

@@ -0,0 +1 @@
1.0.0

View File

@@ -0,0 +1,198 @@
// 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 config
import (
"errors"
"net/url"
"regexp"
"strings"
)
const (
DefaultEndpoint string = "/graphql"
DefaultConnectionTimeout uint32 = 5000
)
var gqlVariableRegex = regexp.MustCompile(`\$(\w+)\s*:\s*(String|Float|Int|Boolean)(!?)`)
type VariableType string
const (
StringType VariableType = "String"
IntType VariableType = "Int"
FloatType VariableType = "Float"
BooleanType VariableType = "Boolean"
)
type Variable struct {
name string
typ VariableType
blank bool
value string
}
type DeGraphQLConfig struct {
gql string
endpoint string
timeout uint32
domain string
variables []Variable
}
func (d *DeGraphQLConfig) SetEndpoint(endpoint string) error {
endpoint = strings.TrimSpace(endpoint)
if endpoint == "" {
d.endpoint = DefaultEndpoint
} else {
d.endpoint = endpoint
}
return nil
}
func (d *DeGraphQLConfig) GetDomain() string {
return d.domain
}
func (d *DeGraphQLConfig) SetDomain(domain string) {
d.domain = domain
}
func (d *DeGraphQLConfig) GetEndpoint() string {
return d.endpoint
}
func (d *DeGraphQLConfig) GetTimeout() uint32 {
return d.timeout
}
func (d *DeGraphQLConfig) SetTimeout(timeout uint32) {
if timeout <= 0 {
d.timeout = DefaultConnectionTimeout
} else {
d.timeout = timeout
}
}
func (d *DeGraphQLConfig) SetGql(gql string) error {
if strings.TrimSpace(gql) == "" {
return errors.New("gql can't be empty")
}
d.gql = gql
d.variables = make([]Variable, 0)
matches := gqlVariableRegex.FindAllStringSubmatch(d.gql, -1)
if len(matches) > 0 {
for _, subMatch := range matches {
variable := Variable{}
variable.name = subMatch[1]
switch subMatch[2] {
case "String":
variable.typ = StringType
case "Float":
variable.typ = FloatType
case "Int":
variable.typ = IntType
case "Boolean":
variable.typ = BooleanType
}
variable.blank = subMatch[3] != "!"
d.variables = append(d.variables, variable)
}
}
return nil
}
func (d *DeGraphQLConfig) GetGql() string {
return d.gql
}
func (d *DeGraphQLConfig) GetVersion() string {
return "1.0.0"
}
func (d *DeGraphQLConfig) ParseGqlFromUrl(requestUrl string) (string, error) {
if strings.TrimSpace(requestUrl) == "" {
return "", errors.New("request url can't be empty")
}
url, _ := url.Parse(requestUrl)
queryValues := url.Query()
values := make(map[string]string, len(queryValues))
for k, v := range queryValues {
var v1 string
if len(v) > 1 {
v1 = strings.Join(v, ",")
} else {
v1 = v[0]
}
values[k] = v1
}
variables := make([]Variable, 0, len(d.variables))
for _, variable := range d.variables {
val, ok := values[variable.name]
// TODO validate variable type and blank
if ok {
variables = append(variables, Variable{
name: variable.name,
typ: variable.typ,
blank: variable.blank,
value: val,
})
}
}
var build strings.Builder
// write query
build.WriteString("{\"query\":")
build.WriteString("\"")
build.WriteString(getJsonStr(d.gql))
build.WriteString("\"")
// write varialbes
if len(variables) > 0 {
index := 0
build.WriteString(",")
build.WriteString("\"variables\":{")
for _, variable := range variables {
build.WriteString("\"")
build.WriteString(variable.name)
build.WriteString("\":")
if variable.typ == StringType {
build.WriteString("\"")
build.WriteString(getJsonStr(variable.value))
build.WriteString("\"")
} else {
build.WriteString(variable.value)
}
if index < len(variables)-1 {
build.WriteString(",")
}
index++
}
build.WriteString("}")
}
build.WriteString("}")
return build.String(), nil
}
func getJsonStr(str string) string {
d := strings.ReplaceAll(str, "\"", "\\\"")
return strings.ReplaceAll(d, "\n", "\\n")
}

View File

@@ -0,0 +1,177 @@
// 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 config
import (
"errors"
"github.com/stretchr/testify/assert"
"testing"
)
func TestDeGraphQLConfig_SetGql(t *testing.T) {
tests := []struct {
name string
gql string
wantVariables []Variable
wantErr error
}{
{
name: "empty gql",
gql: "",
wantErr: errors.New("gql can't be empty"),
},
{
name: "no params",
gql: "query",
wantVariables: []Variable{},
wantErr: nil,
},
{
name: "four params",
gql: "query ($owner:String $num:Float! $int : Int! $boolean : Boolean )",
wantErr: nil,
wantVariables: []Variable{
{
name: "owner",
typ: StringType,
blank: true,
},
{
name: "num",
typ: FloatType,
blank: false,
},
{
name: "int",
typ: IntType,
blank: false,
},
{
name: "boolean",
typ: BooleanType,
blank: true,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := &DeGraphQLConfig{}
err := d.SetGql(tt.gql)
assert.Equal(t, tt.wantErr, err)
if err != nil {
return
}
assert.Equal(t, tt.wantVariables, d.variables)
})
}
}
func TestDeGraphQLConfig_ParseGqlFromUrl(t *testing.T) {
tests := []struct {
name string
gql string
url string
want string
wantErr error
}{
{
name: "empty url",
gql: "query ($owner:String! $name:String!)",
url: "",
want: "",
wantErr: errors.New("request url can't be empty"),
},
{
name: "no params",
gql: "query HeroNameQuery {\n hero {\n name\n }\n}",
url: "/api?owner=a",
want: "{\"query\":\"query HeroNameQuery {\\n hero {\\n name\\n }\\n}\"}",
wantErr: nil,
},
{
name: "one string variable",
gql: "query FetchSomeIDQuery($someId: String!) {\n human(id: $someId) {\n name\n }\n}",
url: "/api?someId=a",
want: "{\"query\":\"query FetchSomeIDQuery($someId: String!) {\\n human(id: $someId) {\\n name\\n }\\n}\",\"variables\":{\"someId\":\"a\"}}",
wantErr: nil,
},
{
name: "multi variables",
gql: "query FetchSomeIDQuery($someId: String! $num: Int $price: Float! $need:Boolean!) {\n human(id: $someId) {\n name\n }\n}",
url: "/api?someId=a&num=10&price=12.0&need=false&hee=1",
want: "{\"query\":\"query FetchSomeIDQuery($someId: String! $num: Int $price: Float! $need:Boolean!) {\\n human(id: $someId) {\\n name\\n }\\n}\",\"variables\":{\"someId\":\"a\",\"num\":10,\"price\":12.0,\"need\":false}}",
wantErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := &DeGraphQLConfig{}
d.SetGql(tt.gql)
body, err := d.ParseGqlFromUrl(tt.url)
assert.Equal(t, tt.wantErr, err)
if err != nil {
return
}
assert.Equal(t, tt.want, body)
})
}
}
func TestDeGraphQLConfig_SetEndpoint(t *testing.T) {
tests := []struct {
name string
endPoint string
wantErr error
want string
}{
{
name: "empty endpoint",
endPoint: "",
wantErr: nil,
want: "/graphql",
},
{
name: "empty endpoint with blank",
endPoint: " ",
wantErr: nil,
want: "/graphql",
},
{
name: "with value",
endPoint: " /graphql2 ",
wantErr: nil,
want: "/graphql2",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := &DeGraphQLConfig{}
err := d.SetEndpoint(tt.endPoint)
assert.Equal(t, tt.wantErr, err)
if err != nil {
return
}
assert.Equal(t, tt.want, d.endpoint)
})
}
}

View File

@@ -0,0 +1,122 @@
static_resources:
listeners:
- name: main
address:
socket_address:
address: 0.0.0.0
port_value: 18000
filter_chains:
- filters:
- name: envoy.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: auto
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "*"
routes:
- match:
prefix: "/api"
route:
cluster: github
http_filters:
- name: envoy.filters.http.wasm
typed_config:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
value:
config:
configuration:
"@type": type.googleapis.com/google.protobuf.StringValue
value: |-
{
"gql": "query ($owner:String! $name:String!){\n repository(owner:$owner, name:$name) {\n name\n forkCount\n description\n}\n}",
"domain": "api.github.com",
"endpoint": "/graphql",
"timeout": 2000
}
vm_config:
runtime: "envoy.wasm.runtime.v8"
code:
local:
filename: "./main.wasm"
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
- name: staticreply
address:
socket_address:
address: 127.0.0.1
port_value: 8099
filter_chains:
- filters:
- name: envoy.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: auto
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "*"
routes:
- match:
prefix: "/"
direct_response:
status: 200
body:
inline_string: "example body\n"
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: mock_service
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: mock_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8099
- name: github
connect_timeout: 0.5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
dns_refresh_rate: 5s
dns_lookup_family: V4_ONLY
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
load_assignment:
cluster_name: github
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: api.github.com
port_value: 443
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 8001

View File

@@ -0,0 +1,22 @@
module de-graphql
go 1.19
replace github.com/alibaba/higress/plugins/wasm-go => ../..
require (
github.com/alibaba/higress/plugins/wasm-go v0.0.0-20230410091208-df60dd43079c
github.com/stretchr/testify v1.8.0
github.com/tetratelabs/proxy-wasm-go-sdk v0.22.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/tetratelabs/wazero v1.0.0-rc.1 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -0,0 +1,29 @@
github.com/alibaba/higress/plugins/wasm-go v0.0.0-20230410091208-df60dd43079c h1:W1QzLx6pefqDWi4peW2HKcZY0rgEy11+JCuWtssp1Ew=
github.com/alibaba/higress/plugins/wasm-go v0.0.0-20230410091208-df60dd43079c/go.mod h1:AzSnkuon5c26nIePTiJQIAFsKdhkNdncLcTuahpGtQs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/tetratelabs/proxy-wasm-go-sdk v0.22.0 h1:kS7BvMKN+FiptV4pfwiNX8e3q14evxAWkhYbxt8EI1M=
github.com/tetratelabs/proxy-wasm-go-sdk v0.22.0/go.mod h1:qkW5MBz2jch2u8bS59wws65WC+Gtx3x0aPUX5JL7CXI=
github.com/tetratelabs/wazero v1.0.0-rc.1 h1:ytecMV5Ue0BwezjKh/cM5yv1Mo49ep2R2snSsQUyToc=
github.com/tetratelabs/wazero v1.0.0-rc.1/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,59 @@
apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
name: default
namespace: higress-system
spec:
registries:
- domain: api.github.com
name: github
port: 443
type: dns
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.io/destination: github.dns
higress.io/upstream-vhost: "api.github.com"
higress.io/backend-protocol: HTTPS
name: github-api
namespace: higress-system
spec:
ingressClassName: higress
rules:
- http:
paths:
- backend:
resource:
apiGroup: networking.higress.io
kind: McpBridge
name: default
path: /api
pathType: Prefix
---
apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
name: de-graphql-github-api
namespace: higress-system
spec:
defaultConfigDisable: true
matchRules:
- config:
domain: api.github.com
endpoint: /graphql
gql: |-
query ($owner:String! $name:String!){
repository(owner:$owner, name:$name) {
name
forkCount
description
}
}
timeout: 5000
configDisable: false
ingress:
- github-api
url: oci://docker.io/2456868764/de-graphql:1.0.0

View File

@@ -0,0 +1,117 @@
// 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"
"net/http"
"de-graphql/config"
"github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
"github.com/tidwall/gjson"
)
func main() {
wrapper.SetCtx(
"de-graphql",
wrapper.ParseConfigBy(parseConfig),
wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
wrapper.ProcessRequestBodyBy(onHttpRequestBody),
wrapper.ProcessResponseBodyBy(onHttpResponseBody),
wrapper.ProcessResponseHeadersBy(onHttpResponseHeaders),
)
}
func parseConfig(json gjson.Result, config *config.DeGraphQLConfig, log wrapper.Log) error {
log.Debug("parseConfig()")
gql := json.Get("gql").String()
endpoint := json.Get("endpoint").String()
timeout := json.Get("timeout").Int()
domain := json.Get("domain").String()
log.Debugf("gql:%s endpoint:%s timeout:%d domain:%s", gql, endpoint, timeout, domain)
err := config.SetGql(gql)
if err != nil {
return err
}
err = config.SetEndpoint(endpoint)
if err != nil {
return err
}
config.SetTimeout(uint32(timeout))
config.SetDomain(domain)
return nil
}
func onHttpRequestHeaders(ctx wrapper.HttpContext, config config.DeGraphQLConfig, log wrapper.Log) types.Action {
log.Debug("onHttpRequestHeaders()")
log.Debugf("schema:%s host:%s path:%s", ctx.Scheme(), ctx.Host(), ctx.Path())
requestUrl, _ := proxywasm.GetHttpRequestHeader(":path")
method, _ := proxywasm.GetHttpRequestHeader(":method")
log.Debugf("method:%s, request:%s", method, requestUrl)
if err := proxywasm.RemoveHttpRequestHeader("content-length"); err != nil {
log.Debug("can not reset content-length")
}
replaceBody, err := config.ParseGqlFromUrl(requestUrl)
if err != nil {
log.Warnf("failed to parse request url %s : %v", requestUrl, err)
}
log.Debugf("replace body:%s", replaceBody)
// Pass headers to upstream cluster
headers, _ := proxywasm.GetHttpRequestHeaders()
for i := len(headers) - 1; i >= 0; i-- {
key := headers[i][0]
if key == ":method" || key == ":path" || key == ":authority" {
headers = append(headers[:i], headers[i+1:]...)
}
}
// Add header Content-Type: application/json
headers = append(headers, [2]string{"Content-Type", "application/json"})
client := wrapper.NewClusterClient(wrapper.RouteCluster{Host: config.GetDomain()})
// Call upstream graphql endpoint
client.Post(config.GetEndpoint(), headers, []byte(replaceBody),
func(statusCode int, responseHeaders http.Header, responseBody []byte) {
// Pass response headers and body to client
headers := make([][2]string, 0, len(responseHeaders)+3)
for headK, headV := range responseHeaders {
headers = append(headers, [2]string{headK, headV[0]})
}
// Add debug headers
headers = append(headers, [2]string{"x-degraphql-endpoint", config.GetEndpoint()})
headers = append(headers, [2]string{"x-degraphql-timeout", fmt.Sprintf("%d", config.GetTimeout())})
headers = append(headers, [2]string{"x-degraphql-version", config.GetVersion()})
proxywasm.SendHttpResponse(uint32(statusCode), headers, responseBody, -1)
return
}, config.GetTimeout())
return types.ActionPause
}
func onHttpRequestBody(ctx wrapper.HttpContext, config config.DeGraphQLConfig, body []byte, log wrapper.Log) types.Action {
log.Debug("onHttpRequestBody()")
return types.ActionContinue
}
func onHttpResponseHeaders(ctx wrapper.HttpContext, config config.DeGraphQLConfig, log wrapper.Log) types.Action {
log.Debug("onHttpResponseHeaders()")
return types.ActionContinue
}
func onHttpResponseBody(ctx wrapper.HttpContext, config config.DeGraphQLConfig, body []byte, log wrapper.Log) types.Action {
log.Debug("onHttpResponseBody()")
return types.ActionContinue
}

View File

@@ -0,0 +1,50 @@
# 功能说明
`gw-error-format`本插件实现了匹配网关未转发到后端服务时的响应状态码和响应内容体并替换返回自定义响应内容
# 配置字段
| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
| -------- | -------- | -------- | -------- | -------- |
| rules.match.statuscode | string | 必填 | - | 匹配响应状态码 |
| rules.match.responsebody | string | 必填 | - | 匹配响应体 |
| rules.replace.statuscode | string | 必填 | - | 替换后的响应状态码 |
| rules.replace.responsebody | string | 必填 | - | 替换后的响应体 |
| set_header | array of object | 选填 | - | 添加/替换响应头,例如:- content-type: "application/json" |
# 配置示例
```yaml
rules:
- match:
statuscode: "403"
responsebody: "RBAC: access denied"
replace:
statuscode: "200"
responsebody: "{\"code\":401,\"message\":\"User is not authenticated\"}"
- match:
statuscode: "503"
responsebody: "no healthy upstream"
replace:
statuscode: "200"
responsebody: "{\"code\":404,\"message\":\"No Healthy Service\"}"
set_header:
- Access-Control-Allow-Credentials: "true"
- Access-Control-Allow-Origin: "*"
- Access-Control-Allow-Headers: "*"
- Access-Control-Allow-Methods: "*"
- Access-Control-Expose-Headers: "*"
- Content-Type: "application/json;charset=UTF-8"
```
## 示例说明:
以上配置示例作用于当前实例全局生效
match下指定的statuscode和responsebody将被替换为同级中的replace下的statuscode和responsebody
以上示例当某个请求返回的响应状态码是403并且响应内容体是RBAC: access denied的则替换状态码为200和响应内容体为json格式"{"code":401,"message":"User is not authenticated"}"
如果需要新增/替换response header则可以在rules同级中添加set_header字段当有match下的statuscode匹配上之后会将set_header的内容带在response header
## 小提示:
当envoy网关还未转发至后端服务时response header里面不会带有这个headerx-envoy-upstream-service-time
本插件只在没有获取到此x-envoy-upstream-service-time响应头时生效

View File

@@ -0,0 +1 @@
1.0.0

View File

@@ -0,0 +1,20 @@
module wasm-demo
go 1.18
require (
github.com/mse-group/wasm-extensions-go v1.0.1
github.com/tetratelabs/proxy-wasm-go-sdk v0.19.1-0.20220822060051-f9d179a57f8c
github.com/tidwall/gjson v1.14.3
)
require (
github.com/alibaba/higress/plugins/wasm-go v0.0.0-20221116034346-4eb91e6918b8
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-redis/redis v6.15.9+incompatible // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
)

View File

@@ -0,0 +1,24 @@
github.com/alibaba/higress/plugins/wasm-go v0.0.0-20221116034346-4eb91e6918b8 h1:mpxRyDnAED+3xv5Lx92jVJZyEm1lKlTpryNnGK/Ikz4=
github.com/alibaba/higress/plugins/wasm-go v0.0.0-20221116034346-4eb91e6918b8/go.mod h1:JZEtmL2/oa24moc8fVXug1gMsOd/dnQM38e3pR5tZ/M=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/mse-group/wasm-extensions-go v1.0.0 h1:hYkU8sIs8/rTEThrG8kEl8woh3tklEWeljGJS11rJe0=
github.com/mse-group/wasm-extensions-go v1.0.0/go.mod h1:N9MtZ4Oreog4gx67BBVJGM+cl/SgRy1Vm5OEKidQEYM=
github.com/mse-group/wasm-extensions-go v1.0.1 h1:9AotUmzsc6R0X8uezQj3OHgId0YCNPCPubXT+8ciY0E=
github.com/mse-group/wasm-extensions-go v1.0.1/go.mod h1:N9MtZ4Oreog4gx67BBVJGM+cl/SgRy1Vm5OEKidQEYM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/tetratelabs/proxy-wasm-go-sdk v0.19.1-0.20220822060051-f9d179a57f8c h1:OCUFXVGixHLfNjg6/QYEhv+jHJ5mRGhpEUVFv9eWPJE=
github.com/tetratelabs/proxy-wasm-go-sdk v0.19.1-0.20220822060051-f9d179a57f8c/go.mod h1:5t/pWFNJ9eMyu/K/Z+OeGhDJ9sN9eCo8fc2pyM/Qjg4=
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@@ -0,0 +1,30 @@
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: gw-error-format
namespace: higress-system
spec:
selector:
matchLabels:
higress: higress-system-higress-gateway
pluginConfig:
rules:
- match:
statuscode: "200"
responsebody: "bar"
replace:
statuscode: "401"
responsebody: "{\"code\":401,\"message\":\"User is not authenticated\"}"
- match:
statuscode: "503"
responsebody: "no healthy upstream"
replace:
statuscode: "200"
responsebody: "{\"code\":404,\"message\":\"No Healthy Service\"}"
set_header:
- access-control-allow-credentials: "true"
- access-control-allow-origin: "*"
- access-control-expose-headers: "*"
- content-type: "application/json;charset=UTF-8"
- custom-header: "HelloWorld"
url: oci://docker.io/zhangjiahaol/envoy-plugin:gw-error-format-2.0.0

View File

@@ -0,0 +1,98 @@
package main
import (
"errors"
"github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
"github.com/tidwall/gjson"
)
func main() {
wrapper.SetCtx(
"gw-error-format",
wrapper.ParseConfigBy(parseConfig),
wrapper.ProcessResponseHeadersBy(onHttpResponseHeader),
wrapper.ProcessResponseBodyBy(onHttpResponseBody),
)
}
type MyConfig struct {
rules []gjson.Result
set_header []gjson.Result
}
func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
config.set_header = json.Get("set_header").Array()
config.rules = json.Get("rules").Array()
for _, item := range config.rules {
log.Info("config.rules: " + item.String())
if item.Get("match.statuscode").String() == "" {
return errors.New("missing match.statuscode in config")
}
if item.Get("replace.statuscode").String() == "" {
return errors.New("missing replace.statuscode in config")
}
}
return nil
}
func onHttpResponseHeader(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
dontReadResponseBody := false
currentStatuscode, _ := proxywasm.GetHttpResponseHeader(":status")
for _, item := range config.rules {
configMatchStatuscode := item.Get("match.statuscode").String()
configReplaceStatuscode := item.Get("replace.statuscode").String()
switch currentStatuscode {
// configMatchStatuscode value example: "403" or "503":
case configMatchStatuscode:
// If the response header `x-envoy-upstream-service-time` is not found, the request has not been forwarded to the backend service
_, err := proxywasm.GetHttpResponseHeader("x-envoy-upstream-service-time")
if err != nil {
proxywasm.RemoveHttpResponseHeader("content-length")
proxywasm.ReplaceHttpResponseHeader(":status", configReplaceStatuscode)
for _, item_header := range config.set_header {
item_header.ForEach(func(key, value gjson.Result) bool {
err := proxywasm.ReplaceHttpResponseHeader(key.String(), value.String())
if err != nil {
log.Critical("failed ReplaceHttpResponseHeader" + item_header.String())
}
return true
})
}
// goto func onHttpResponseBody
return types.ActionContinue
} else {
dontReadResponseBody = true
break
}
default:
// There is no matching rule
dontReadResponseBody = true
}
}
// If there is no rule match or no header for x-envoy-upstream-service-time, the onHttpResponseBody is not exec
if dontReadResponseBody == true {
ctx.DontReadResponseBody()
}
return types.ActionContinue
}
func onHttpResponseBody(ctx wrapper.HttpContext, config MyConfig, body []byte, log wrapper.Log) types.Action {
bodyStr := string(body)
for _, item := range config.rules {
configMatchResponsebody := item.Get("match.responsebody").String()
configReplaceResponsebody := item.Get("replace.responsebody").String()
if bodyStr == configMatchResponsebody {
proxywasm.ReplaceHttpResponseBody([]byte(configReplaceResponsebody))
return types.ActionContinue
}
}
return types.ActionContinue
}

View File

@@ -17,6 +17,8 @@ package wrapper
import (
"fmt"
"strings"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
)
type Cluster interface {
@@ -24,6 +26,25 @@ type Cluster interface {
HostName() string
}
type RouteCluster struct {
Host string
}
func (c RouteCluster) ClusterName() string {
routeName, err := proxywasm.GetProperty([]string{"cluster_name"})
if err != nil {
proxywasm.LogErrorf("get route cluster failed, err:%v", err)
}
return string(routeName)
}
func (c RouteCluster) HostName() string {
if c.Host != "" {
return c.Host
}
return GetRequestHost()
}
type K8sCluster struct {
ServiceName string
Namespace string

View File

@@ -115,7 +115,7 @@ func HttpCall(cluster Cluster, method, path string, headers [][2]string, body []
requestID, code, normalResponse, respBody)
callback(code, headers, respBody)
})
proxywasm.LogDebugf("http call start, id: %s, cluster: %+v, method: %s, path: %s, body: %s, timeout: %d",
requestID, cluster, method, path, body, timeout)
proxywasm.LogDebugf("http call start, id: %s, cluster: %s, method: %s, path: %s, body: %s, timeout: %d",
requestID, cluster.ClusterName(), method, path, body, timeout)
return err
}

View File

@@ -40,6 +40,7 @@ type HttpContext interface {
type ParseConfigFunc[PluginConfig any] func(json gjson.Result, config *PluginConfig, log Log) error
type onHttpHeadersFunc[PluginConfig any] func(context HttpContext, config PluginConfig, log Log) types.Action
type onHttpBodyFunc[PluginConfig any] func(context HttpContext, config PluginConfig, body []byte, log Log) types.Action
type onHttpStreamDoneFunc[PluginConfig any] func(context HttpContext, config PluginConfig, log Log)
type CommonVmCtx[PluginConfig any] struct {
types.DefaultVMContext
@@ -51,6 +52,7 @@ type CommonVmCtx[PluginConfig any] struct {
onHttpRequestBody onHttpBodyFunc[PluginConfig]
onHttpResponseHeaders onHttpHeadersFunc[PluginConfig]
onHttpResponseBody onHttpBodyFunc[PluginConfig]
onHttpStreamDone onHttpStreamDoneFunc[PluginConfig]
}
func SetCtx[PluginConfig any](pluginName string, setFuncs ...SetPluginFunc[PluginConfig]) {
@@ -89,6 +91,12 @@ func ProcessResponseBodyBy[PluginConfig any](f onHttpBodyFunc[PluginConfig]) Set
}
}
func ProcessStreamDoneBy[PluginConfig any](f onHttpStreamDoneFunc[PluginConfig]) SetPluginFunc[PluginConfig] {
return func(ctx *CommonVmCtx[PluginConfig]) {
ctx.onHttpStreamDone = f
}
}
func parseEmptyPluginConfig[PluginConfig any](gjson.Result, *PluginConfig, Log) error {
return nil
}
@@ -289,3 +297,13 @@ func (ctx *CommonHttpCtx[PluginConfig]) OnHttpResponseBody(bodySize int, endOfSt
}
return ctx.plugin.vm.onHttpResponseBody(ctx, *ctx.config, body, ctx.plugin.vm.log)
}
func (ctx *CommonHttpCtx[PluginConfig]) OnHttpStreamDone() {
if ctx.config == nil {
return
}
if ctx.plugin.vm.onHttpStreamDone == nil {
return
}
ctx.plugin.vm.onHttpStreamDone(ctx, *ctx.config, ctx.plugin.vm.log)
}

View File

@@ -0,0 +1,67 @@
// 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/roundtripper"
"github.com/alibaba/higress/test/ingress/conformance/utils/suite"
)
func init() {
HigressConformanceTests = append(HigressConformanceTests, HttpForceRedirectHttps)
}
var HttpForceRedirectHttps = suite.ConformanceTest{
ShortName: "HttpForceRedirectHttps",
Description: " The ingress in the higress-conformance-infra namespace enforces server-side HTTPS with forced redirection.",
Manifests: []string{"tests/httproute-force-redirect-https.yaml"},
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
testcases := []http.Assertion{
{
Meta: http.AssertionMeta{
TargetBackend: "infra-backend-v1",
TargetNamespace: "higress-conformance-infra",
},
Request: http.AssertionRequest{
ActualRequest: http.Request{
Host: "test.com",
Path: "/test",
UnfollowRedirect: true,
},
RedirectRequest: &roundtripper.RedirectRequest{
Scheme: "https",
Host: "test.com",
Path: "/test",
},
},
Response: http.AssertionResponse{
ExpectedResponse: http.Response{
StatusCode: 308,
},
},
},
}
t.Run("HTTPFORCEREDIRCTHTTPS", func(t *testing.T) {
for _, testcase := range testcases {
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, suite.GatewayAddress, testcase)
}
})
},
}

View File

@@ -0,0 +1,49 @@
# 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:
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
name: http-redirect-as-https
namespace: higress-conformance-infra
spec:
ingressClassName: higress
tls:
- hosts:
- "test.com"
secretName: my-app-tls-secret
rules:
- host: "test.com"
http:
paths:
- pathType: Prefix
path: "/test"
backend:
service:
name: infra-backend-v1
port:
number: 8080
---
apiVersion: v1
kind: Secret
metadata:
name: my-app-tls-secret
namespace: higress-conformance-infra
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQxekNDQXIrZ0F3SUJBZ0lVWXh4dE1Ia0tIQXpxM25yUG0rd0Y2UEtNdmw4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd2V6RUxNQWtHQTFVRUJoTUNRMDR4Q3pBSkJnTlZCQWdNQWxOWU1Rc3dDUVlEVlFRSERBSllRVEVOTUFzRwpBMVVFQ2d3RVdGVlFWREVUTUJFR0ExVUVDd3dLVEVsT1ZWaEhVazlWVURFTU1Bb0dBMVVFQXd3RFJsbFVNU0F3CkhnWUpLb1pJaHZjTkFRa0JGaEZtWjNrNE9UTTJRR2R0WVdsc0xtTnZiVEFlRncweU16QTFNRGd4TkRVM016UmEKRncweU5EQTFNRGN4TkRVM016UmFNSHN4Q3pBSkJnTlZCQVlUQWtOT01Rc3dDUVlEVlFRSURBSlRXREVMTUFrRwpBMVVFQnd3Q1dFRXhEVEFMQmdOVkJBb01CRmhWVUZReEV6QVJCZ05WQkFzTUNreEpUbFZZUjFKUFZWQXhEREFLCkJnTlZCQU1NQTBaWlZERWdNQjRHQ1NxR1NJYjNEUUVKQVJZUlptZDVPRGt6TmtCbmJXRnBiQzVqYjIwd2dnRWkKTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEUEVHaDJxeFpFMmpJUnMvNkFXYkI2b3oxZQpic0c4enE0YWxLTzVUcjgzWFlrUzhOa2g4UkdiU1l3ODlVR3NBWmZ0WkFqT0M2Mml1aEVOUTUzZjhwTmoySWQ1Ck9PNGVhVDN6bndKQ0xGMmRHcThRZE90c1RjU09FZE11N2dORWVOZkxVeWRFNitnYjcxSi9PRkNlZTlQM1dWWWgKQ05adG1nYWcyWm0wQUZxT0F2b1hUV3lGdDBzWEYyVG90VENnWFhNM1kydmdCY3JRMHRTbllHZmVqOVRUcmpENgpGQTBTYmFlL0F6Y001cC9FNmdKNWFXREhLekY5c2lvOHRUOUZuN1Fzb3djR1BSTElOL1o3OGxhaEZITGpsVFBtCmZqUEFmdWVUWVYzY05ZNXRGNjZlV1duazI0WG4vTEFaSlhHU0hXRm5aWHhxZWIxQlBQQlRKSFpWNmFScEFnTUIKQUFHalV6QlJNQjBHQTFVZERnUVdCQlFScHRWS3hCNGpGTjJnZTAwVStBd3FLM2czTkRBZkJnTlZIU01FR0RBVwpnQlFScHRWS3hCNGpGTjJnZTAwVStBd3FLM2czTkRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUdTSWIzCkRRRUJDd1VBQTRJQkFRQ2tJTVJKYzRqZWtCazZUTUVUckFmOWJiKzBMcVkyYi9EMUlXdjUycFZzRkNmeWRDQ0wKRS9KVU1USGpTUXZvd1FRSHh1S291d3VHd2VoVFVocHJISzNzUXptUnZLTkpMVGlkT0tlNWJSUEZuTEVCa1JMRQpnQ1hrRXFNY2dvSjlMdzQvWW5sVm5UakRxK1lVN21QUkJlV3U3WDNFTXE4MWpjNHg1RWtubDZXem95MjIxd1RKCkhMTEl2OGFsbTBuYzAzV2lBbVBsUGpLL3Z3N0lRNDlKMTlydnROMXNDQ2xyUDBSVyt1NjRQL0luL3pBeE1HMC8KeGkwTTdjYk1GYjh5UGFDeERPWVQ0enljdWRUWlhNS0FReDRxLzRhYVpRK1oxV2FBTkVtQi9OM1hNTHBTTUZJaApEdjdCbUVVOWRSUkx6dklQMHIxNDlKNnlaZ2VQYzc2WWR5R0oKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRFBFR2gycXhaRTJqSVIKcy82QVdiQjZvejFlYnNHOHpxNGFsS081VHI4M1hZa1M4TmtoOFJHYlNZdzg5VUdzQVpmdFpBak9DNjJpdWhFTgpRNTNmOHBOajJJZDVPTzRlYVQzem53SkNMRjJkR3E4UWRPdHNUY1NPRWRNdTdnTkVlTmZMVXlkRTYrZ2I3MUovCk9GQ2VlOVAzV1ZZaENOWnRtZ2FnMlptMEFGcU9Bdm9YVFd5RnQwc1hGMlRvdFRDZ1hYTTNZMnZnQmNyUTB0U24KWUdmZWo5VFRyakQ2RkEwU2JhZS9BemNNNXAvRTZnSjVhV0RIS3pGOXNpbzh0VDlGbjdRc293Y0dQUkxJTi9aNwo4bGFoRkhMamxUUG1malBBZnVlVFlWM2NOWTV0RjY2ZVdXbmsyNFhuL0xBWkpYR1NIV0ZuWlh4cWViMUJQUEJUCkpIWlY2YVJwQWdNQkFBRUNnZ0VBRSs5UzkxWEtXNCtjTVdzZ1RmQVVsd0gvUndlbnZFc3pwTmg1bUw0Vmw3bDQKR0d3Nm8xTm5yQWtkS01NOTh0Ym1ieExwN0JoZ3U2RnBRZHNvS0diY3ZNaWNabFhPU3Z3NzNDZ0xXaDZXVnFrNgpnSDJaS3NDajh6K1JFdHdVVVhQRzVzclhKWUlHd3lXN3pnYTRjRUdncXhnZFBDbnpKdk1rdnppajNSb0puZEZNCktMMjBjeDArUDROMnZLem1FSDJaYmZLUUo0bXlpTlUzdTFjWE14L1hhU04yczJNSExqNHVZemFJV0Q1clU0S1YKOHVrTmNnT3ZFSHl1eUFYcGgyYlVXdjVMcWIvWnFuQnVqVDI1ZFF6Zk43NC81a3grR1dNVkpVMXM1cUFqOEVyMApWZXhhK0FkMU9hM2JTMktEVGt4MHROQVZ1NGprT2tLSkZxVWJjc2RtendLQmdRRHl1T2diSW9CcVY2NjRLTVhlCk1lendkRGVLdTV3dkhUUEhDQStnQlRkbE5Kb1orS3g2Z2FVOXhsN0o2Q0pIcXB2Ti8xdGZFdVY1bzMySmhMdzEKQWtJMDY1ODQ3Slgyb1BvWDFYdU4xelJNUjk4bW05YWkvNk10d20vYWpoOVdKNnhKV2tCYUpyVXB1UGV5K2d5QQp6cDRhSXFCY2xXUjJWK0dkS3RHODROeWNKd0tCZ1FEYVpDUjVMVzBSMmc2bTNHUk9nQS9vY0RMTEM3V0ovVzliCkxUcTZLcndWYlVKUFUvRk1IbG1wb3NBOHY0dUp2MklnM0FwTXphL0JJd2FCUHMvUXArN1hrZVI1em5MbEg2RlEKK3VNQnVRRDhBRXQxZTZiVzJYQkpCcDZjemJXMmF1bjYvUEd3WmpCZkdYT0RQNXJVWHFQNkpiZ2pqMjdwL2RYMwpFVzUrVGlyRTd3S0JnRjdLSzRyOVRGMDdaUFp5cGVPQ1o5LzM0d0VCQjV1MnNkUFdxQk44TmdnR0pQQmpseWc0Cm5VbWt3THZsTmczNjZPSG9DY3oxV2p6SXhtd0FOR2dYTzdmakZNbHNTNXlIZldQMWNVMFJjRkVoK0ZuaG5rOEYKdXJwU0p0Q1psRTlYS3dkeWdaTXpicWllbmMxOXJZaFlLSkpZVjN3UXM2MHI0T1k2SkxLNHRpOGRBb0dCQUpjeQpyK0hKWm5MdWtpaEorNVF4cTFIVXBBWFpkSFUxcGl2czAzVGljMWN1VHJOWFBYN2lvRmNHbTZzelBlcy9PalBmCnc2M0sxYnlVZ0VObzlqM1NsbFJlNkZ6QVp1RmtsYTNZRk9RemJwQUpzRFNGU0V3RlBHMENqVHVvVy84UVpDL2wKZ1hzTU5MOFNndHZDWkhKVmw1ZHZGOTVleG41dncvd0s4SUczb25xM0FvR0FiYVV6UGZJWkRiTlJvM2tKeEZxawoxellzd3ZUUTdqU1lvMGlSbUVNSG9KTStvYWJPaFZjN0NZSjFoK1ZXelBmWXJCUFE5VEZjZEI3b1hueW9OTlZOClBjdGtUYXc1LyszNWdJWThHcmJsdzlqWmtmalFFVDJPNkFmMG5tQTd4a1F2djZkZkgzQTI0WlRyTExrY0pJTzYKZGVtNFpXbitiUWFRNnBvYThJdngvelU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K

View File

@@ -0,0 +1,50 @@
# 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:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
name: http-redirect-as-https
namespace: higress-conformance-infra
spec:
ingressClassName: higress
tls:
- hosts:
- "test.com"
secretName: my-app-tls-secret
rules:
- host: "test.com"
http:
paths:
- pathType: Prefix
path: "/test"
backend:
service:
name: infra-backend-v1
port:
number: 8080
---
apiVersion: v1
kind: Secret
metadata:
name: my-app-tls-secret
namespace: higress-conformance-infra
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURzVENDQXBtZ0F3SUJBZ0lVUGRDZENSdm1pbVZwK2VCcTMxUm9oZ1JsYTBzd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2FERUxNQWtHQTFVRUJoTUNZWE14RERBS0JnTlZCQWdNQTJSaGN6RU1NQW9HQTFVRUJ3d0RZWE5rTVF3dwpDZ1lEVlFRS0RBTmhaSE14RERBS0JnTlZCQXNNQTNwNFl6RU5NQXNHQTFVRUF3d0VZWGRsY2pFU01CQUdDU3FHClNJYjNEUUVKQVJZRGNYZGxNQjRYRFRJek1EVXlNREEzTVRRd09Wb1hEVEkwTURVeE9UQTNNVFF3T1Zvd2FERUwKTUFrR0ExVUVCaE1DWVhNeEREQUtCZ05WQkFnTUEyUmhjekVNTUFvR0ExVUVCd3dEWVhOa01Rd3dDZ1lEVlFRSwpEQU5oWkhNeEREQUtCZ05WQkFzTUEzcDRZekVOTUFzR0ExVUVBd3dFWVhkbGNqRVNNQkFHQ1NxR1NJYjNEUUVKCkFSWURjWGRsTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUExeHB6Z21UVzdwQmUKa3ZlRkRBU0JZLzdpZmxvWFk1T0x3OUZwOXJqZHNMRmh5Y1dPR0U5NHJ1RmhDSkVqYmNzQW5URHZOKzg4WVRzOApkV2tWbVArQ1RQQjVoN2EvZmJtelJPYVE5SjVDQXhqaGJuRGhCc3YrYVpzeVlhVzBHQkp3Y3h6U1RoVUJpbm9aCmJwYUhvU1QxUjBlZ0FHQ2lkWk4wU2xDMW9KYmxOMHJoOGxKNUROcWxWSnBYejUxaGdLU1NmSm1UcElRQkhBQVkKSDVMUU1CTCtQem9INy83cWhUSUVaWWJvU0o2ajV1ZDc1YUZzVVhndmdLWFgvZ2JZTHlaQ0ljTXUyR2YzRjQ5bwoyc1QwdFZzQmxHbWsrVkswcmgxSi9xQjBWNDBheU8xR3NFalRhelBLUitrYTZJS1N6SjJLVkJadCtHQTdGMUkrCmlHOXcrVDQwVFFJREFRQUJvMU13VVRBZEJnTlZIUTRFRmdRVTFLZSs3aHZTaTljRjhXM2hZTW5hd0NKblcwVXcKSHdZRFZSMGpCQmd3Rm9BVTFLZSs3aHZTaTljRjhXM2hZTW5hd0NKblcwVXdEd1lEVlIwVEFRSC9CQVV3QXdFQgovekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBQ3JGQU1KV3g1QThsaXVLY1NETmlWY0Rvem5sU1p6cFYyeGRNCnpkSU5SRytFVXFzV3lpekNtWk5rSUMyV0lKTWhNdVBkOWhJdTZ3cWd5YjJaNnN3MmdjOXpwVnpsbkRKYlUwSlUKZEZJZDFuYmtQRG01ekk3NzAyRTk0eVZqUUs5ZllRVDU3cHFTdlkvOUpSeXRpcGdpdnAxMGR2UC95NUpocDVBawo3VHNQcnZ2K3gzWGhLYTRwRG40eEhzZHp4MGx0ZHdUdExiaWFGU1IwUHpBZzdpOUNsbjQ5aWRRd3YxaHpaNTV5CkFtOStESHhmTkgreGFIYk9zWTJFRHpiZ0FxR0JMaTNEMmtxMkdRREFmRDdOdGovRUNlODl1bG5zSWpMajB5YmUKNWR0QzRXYndBNER3UHBFWUJvbTFTZmdxQlJSSG5seTVIMUxZMS80ZnpUZkNIYkFtdWc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRFhHbk9DWk5idWtGNlMKOTRVTUJJRmovdUorV2hkams0dkQwV24ydU4yd3NXSEp4WTRZVDNpdTRXRUlrU050eXdDZE1PODM3enhoT3p4MQphUldZLzRKTThIbUh0cjk5dWJORTVwRDBua0lER09GdWNPRUd5LzVwbXpKaHBiUVlFbkJ6SE5KT0ZRR0tlaGx1CmxvZWhKUFZIUjZBQVlLSjFrM1JLVUxXZ2x1VTNTdUh5VW5rTTJxVlVtbGZQbldHQXBKSjhtWk9raEFFY0FCZ2YKa3RBd0V2NC9PZ2Z2L3VxRk1nUmxodWhJbnFQbTUzdmxvV3hSZUMrQXBkZitCdGd2SmtJaHd5N1laL2NYajJqYQp4UFMxV3dHVWFhVDVVclN1SFVuK29IUlhqUnJJN1Vhd1NOTnJNOHBINlJyb2dwTE1uWXBVRm0zNFlEc1hVajZJCmIzRDVQalJOQWdNQkFBRUNnZ0VBTVRZT2ZpTDIzejV0UEo5Zk0zZ21hQXVzb3E2VzBrT3p3cGw2N2lTdUoxbjEKbnRWUkpIT3VEd2htRERFMFUwNlJ0ZVMzbmVyZ08vaHk1UU9sR3NzOThyOURkbzZUTWI3VjZpbjd1Tk1xRkE1UgpxTlF2VDBCRlZNRGFYbWVzRTZQSVVUV2pVWlRSdE80cE9sazY3MTJHdGdlSGJmNnR2RXQvVys4cUZuTGZQdTQ1Cm50Nld6NzgrRkVuUW5qWVk3R1N4bTlaVFEraUw3VGMyR09MMUFjdkxVcmV1VS9aMXNwTVFPTFRUUzBLbkJka0YKY0FVeFBkNGpnZ3lwbGNpSHBQaktNNG1VRGkvSDluTWFjNyt4K08zZFZCNXlpb2xLREJCOHUybDIvb3BPSzVVZwpTSUg0ajVqU1NJY3lNNUNSdkFpR2Q3eE9HaE1Zb3hQV1FNNnduNGMyMFFLQmdRRFpEbkc5TmNTeHVSbnNUSVFMCnZIMForUWFMZmZ4WGF6eWswM21NMldiOWd3NEoxOGF5ZlF4STk2RU13VXd5ODJkRFh5QldzWFgxK0NxMnd2ZUUKMnB1cU1kV3pvUWI4UnZlOVJ6RDlwM0Z1V2kyR3BmL3JsWkVmZ1lRek1FWENtWnN0VlVDZXo5aVZVdW5ZQzRoZQovNU83Zm12VkVlQ1k3TUFIT2JtWUNOWmNtUUtCZ1FEOXNreTdqNjViai9ZYzlER2pQVzNraUZKeWl5YU9rb2dQCnVtbk5vQ2w4bHhIZ2d1Ym8wT3pubEFZQ0M5V3pxTmdBa3E4eWNlMkdTVkFEOTNoZisycDNON3lGRktMS0I3L0YKTlFsUHMyV2pyK25DUytxSHBSdnpQUjgzN01DUkZnbVlxRlNlaXE5NlcyeStwVTJBYVJkQTlqYWtPeWd0TGl5YQpSbHFDeWNVUjFRS0JnUUROWXBLVFpGWmJpUGdUbFk5NC80RXMyMnVyQUtxUEdhVEhubWVzdEdaMHlkYTF6NXh2CmRrM3ltWWFsNkI0dk5BeHBQcEQrRjJ1ME5JQk9jWXYvQlZBNHFuRTVTTXl3V0lMQmNxVFR6K1pRY2pvVDUrMlMKd1BNU2FkNXJCV2x0S3lZZnJrUzRRWm9DS2ZPbC83dXBrSkw4M2pJdzZucW9tWlZYQVBNeC9tTEFPUUtCZ1FDQQpWeXplVGNlRTVvVTVESWYzN3VHakZSdXdlcGljMDZBbFpNYVZrWXFyVHJscWZJNVlCU2x6MWJ4Y1dLUlphUGN0CkF3ZkNXMFF3QlBLSHJ5K2tUc29EV1p6ekxnZFVjU3NnbHI0SkpkWXJRcGpkQkE2M1pGMkpaY2hmUUZRQ2tjVjEKQnVNWCtVemdkMVBCOWxvSXRpRmZhYThtMGc1M0hMN1BwUHV3NG1YaHFRS0JnQmY5NGRrTXplUW44SDBrK2xXcQpJV3lJaGtqOHpNUmw2ODNzRFFOQUdSYngyTnR2RjYyL2dUK1ZJSXdmSzV5MmI4WXEwNFVEQy9rL1hkK0lBc3dVClFTRGdUVFpmYzZkUkVtRU8zc0M0a0xYa1N3Y1BQZmcvTC92T29YRDJiZWxmWUFtaHhSUnByQ0p4ZVowRVBvRUEKc25RblpMN1VsZCtSTmF3dmJNR05XTXJiCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K

View File

@@ -0,0 +1,67 @@
// 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/roundtripper"
"github.com/alibaba/higress/test/ingress/conformance/utils/suite"
)
func init() {
HigressConformanceTests = append(HigressConformanceTests, HttpRedirectAsHttps)
}
var HttpRedirectAsHttps = suite.ConformanceTest{
ShortName: "HttpRedirectAsHttps",
Description: "The Ingress in the higress-conformance-infra namespace Server-side HTTPS enforcement through redirect.",
Manifests: []string{"tests/httproute-redirct-as-https.yaml"},
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
testcases := []http.Assertion{
{
Meta: http.AssertionMeta{
TargetBackend: "infra-backend-v1",
TargetNamespace: "higress-conformance-infra",
},
Request: http.AssertionRequest{
ActualRequest: http.Request{
Host: "test.com",
Path: "/test",
UnfollowRedirect: true,
},
RedirectRequest: &roundtripper.RedirectRequest{
Scheme: "https",
Host: "test.com",
Path: "/test",
},
},
Response: http.AssertionResponse{
ExpectedResponse: http.Response{
StatusCode: 308,
},
},
},
}
t.Run("HTTPREDIRCTASHTTPS", func(t *testing.T) {
for _, testcase := range testcases {
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, suite.GatewayAddress, testcase)
}
})
},
}

View File

@@ -70,6 +70,8 @@ func TestHigressConformanceTests(t *testing.T) {
tests.HTTPRouteWhitelistSourceRange,
tests.HTTPRouteCanaryWeight,
tests.HTTPRouteMatchPath,
tests.HttpForceRedirectHttps,
tests.HttpRedirectAsHttps,
}
cSuite.Run(t, higressTests)