mirror of
https://github.com/alibaba/higress.git
synced 2026-06-08 04:07:31 +08:00
feature: support secret reference for Redis password in MCP Server (#3006)
Co-authored-by: 澄潭 <zty98751@alibaba-inc.com>
This commit is contained in:
@@ -96,6 +96,17 @@ Ingress Config 包含 6 个控制器,各自负责不同的功能:
|
|||||||
- Http2Rpc Controller:监听 Http2Rpc 资源,实现 HTTP 协议到 RPC 协议的转换。用户可以通过配置协议转换,将 RPC 服务以 HTTP 接口的形式暴露,从而使用 HTTP 请求调用 RPC 接口。
|
- Http2Rpc Controller:监听 Http2Rpc 资源,实现 HTTP 协议到 RPC 协议的转换。用户可以通过配置协议转换,将 RPC 服务以 HTTP 接口的形式暴露,从而使用 HTTP 请求调用 RPC 接口。
|
||||||
- WasmPlugin Controller:监听 WasmPlugin 资源,将 Higress WasmPlugin 转化为 Istio WasmPlugin。Higress WasmPlugin 在 Istio WasmPlugin 的基础上进行了扩展,支持全局、路由、域名、服务级别的配置。
|
- WasmPlugin Controller:监听 WasmPlugin 资源,将 Higress WasmPlugin 转化为 Istio WasmPlugin。Higress WasmPlugin 在 Istio WasmPlugin 的基础上进行了扩展,支持全局、路由、域名、服务级别的配置。
|
||||||
- ConfigmapMgr:监听 Higress 的全局配置 `higress-config` ConfigMap,可以根据 tracing、gzip 等配置构造 EnvoyFilter。
|
- ConfigmapMgr:监听 Higress 的全局配置 `higress-config` ConfigMap,可以根据 tracing、gzip 等配置构造 EnvoyFilter。
|
||||||
|
`mcpServer.redis` 支持通过 Secret 引用保存敏感信息,密码字段可以使用 `passwordSecret` 指向 `higress-system` 命名空间下的 Kubernetes Secret,避免在 ConfigMap 中保存明文密码,例如:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
higress: |-
|
||||||
|
mcpServer:
|
||||||
|
redis:
|
||||||
|
address: "redis:6379"
|
||||||
|
passwordSecret:
|
||||||
|
name: redis-credentials
|
||||||
|
key: password
|
||||||
|
```
|
||||||
|
|
||||||
#### 2.2.2 Cert Server
|
#### 2.2.2 Cert Server
|
||||||
|
|
||||||
@@ -140,4 +151,4 @@ Envoy 核心架构如下图:
|
|||||||
- [1] [Istio Pilot 组件介绍](https://www.zhaohuabing.com/post/2019-10-21-pilot-discovery-code-analysis/)
|
- [1] [Istio Pilot 组件介绍](https://www.zhaohuabing.com/post/2019-10-21-pilot-discovery-code-analysis/)
|
||||||
- [2] [Istio 服务注册插件机制代码解析](https://www.zhaohuabing.com/post/2019-02-18-pilot-service-registry-code-analysis/)
|
- [2] [Istio 服务注册插件机制代码解析](https://www.zhaohuabing.com/post/2019-02-18-pilot-service-registry-code-analysis/)
|
||||||
- [3] [Istio Pilot代码深度解析](https://www.zhaohuabing.com/post/2019-10-21-pilot-discovery-code-analysis/)
|
- [3] [Istio Pilot代码深度解析](https://www.zhaohuabing.com/post/2019-10-21-pilot-discovery-code-analysis/)
|
||||||
- [4] [Envoy 官方文档](https://www.envoyproxy.io/docs/envoy/latest/intro/intro)
|
- [4] [Envoy 官方文档](https://www.envoyproxy.io/docs/envoy/latest/intro/intro)
|
||||||
|
|||||||
@@ -39,10 +39,22 @@ type RedisConfig struct {
|
|||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
// The password for Redis authentication
|
// The password for Redis authentication
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
|
// Reference to a secret containing the password
|
||||||
|
PasswordSecret *SecretKeyReference `json:"passwordSecret,omitempty"`
|
||||||
// The database index to use
|
// The database index to use
|
||||||
DB int `json:"db,omitempty"`
|
DB int `json:"db,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SecretKeyReference defines a reference to a key within a Kubernetes secret
|
||||||
|
type SecretKeyReference struct {
|
||||||
|
// The namespace of the secret. Defaults to the higress system namespace.
|
||||||
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
// The name of the secret
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
// The key within the secret data
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// MCPRatelimitConfig defines the configuration for rate limit
|
// MCPRatelimitConfig defines the configuration for rate limit
|
||||||
type MCPRatelimitConfig struct {
|
type MCPRatelimitConfig struct {
|
||||||
// The limit of the rate limit
|
// The limit of the rate limit
|
||||||
@@ -119,6 +131,15 @@ func validMcpServer(m *McpServer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.Redis != nil && m.Redis.PasswordSecret != nil {
|
||||||
|
if m.Redis.PasswordSecret.Name == "" {
|
||||||
|
return errors.New("redis passwordSecret.name cannot be empty")
|
||||||
|
}
|
||||||
|
if m.Redis.PasswordSecret.Key == "" {
|
||||||
|
return errors.New("redis passwordSecret.key cannot be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if m.EnableUserLevelServer && m.Redis == nil {
|
if m.EnableUserLevelServer && m.Redis == nil {
|
||||||
return errors.New("redis config cannot be empty when user level server is enabled")
|
return errors.New("redis config cannot be empty when user level server is enabled")
|
||||||
}
|
}
|
||||||
@@ -184,6 +205,13 @@ func deepCopyMcpServer(mcp *McpServer) (*McpServer, error) {
|
|||||||
Password: mcp.Redis.Password,
|
Password: mcp.Redis.Password,
|
||||||
DB: mcp.Redis.DB,
|
DB: mcp.Redis.DB,
|
||||||
}
|
}
|
||||||
|
if mcp.Redis.PasswordSecret != nil {
|
||||||
|
newMcp.Redis.PasswordSecret = &SecretKeyReference{
|
||||||
|
Namespace: mcp.Redis.PasswordSecret.Namespace,
|
||||||
|
Name: mcp.Redis.PasswordSecret.Name,
|
||||||
|
Key: mcp.Redis.PasswordSecret.Key,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if mcp.Ratelimit != nil {
|
if mcp.Ratelimit != nil {
|
||||||
newMcp.Ratelimit = &MCPRatelimitConfig{
|
newMcp.Ratelimit = &MCPRatelimitConfig{
|
||||||
@@ -504,12 +532,24 @@ func (m *McpServerController) constructMcpSessionStruct(mcp *McpServer) string {
|
|||||||
// Build redis configuration
|
// Build redis configuration
|
||||||
redisConfig := "null"
|
redisConfig := "null"
|
||||||
if mcp.Redis != nil {
|
if mcp.Redis != nil {
|
||||||
|
passwordValue := mcp.Redis.Password
|
||||||
|
if mcp.Redis.PasswordSecret != nil && mcp.Redis.PasswordSecret.Name != "" && mcp.Redis.PasswordSecret.Key != "" {
|
||||||
|
ns := mcp.Redis.PasswordSecret.Namespace
|
||||||
|
if ns == "" {
|
||||||
|
ns = m.Namespace
|
||||||
|
}
|
||||||
|
if ns != "" {
|
||||||
|
passwordValue = fmt.Sprintf("${secret.%s/%s.%s}", ns, mcp.Redis.PasswordSecret.Name, mcp.Redis.PasswordSecret.Key)
|
||||||
|
} else {
|
||||||
|
passwordValue = fmt.Sprintf("${secret.%s.%s}", mcp.Redis.PasswordSecret.Name, mcp.Redis.PasswordSecret.Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
redisConfig = fmt.Sprintf(`{
|
redisConfig = fmt.Sprintf(`{
|
||||||
"address": "%s",
|
"address": "%s",
|
||||||
"username": "%s",
|
"username": "%s",
|
||||||
"password": "%s",
|
"password": "%s",
|
||||||
"db": %d
|
"db": %d
|
||||||
}`, mcp.Redis.Address, mcp.Redis.Username, mcp.Redis.Password, mcp.Redis.DB)
|
}`, mcp.Redis.Address, mcp.Redis.Username, passwordValue, mcp.Redis.DB)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build rate limit configuration
|
// Build rate limit configuration
|
||||||
|
|||||||
@@ -120,6 +120,30 @@ func Test_validMcpServer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantErr: errors.New("redis config cannot be empty when user level server is enabled"),
|
wantErr: errors.New("redis config cannot be empty when user level server is enabled"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "redis config with password secret missing name",
|
||||||
|
mcp: &McpServer{
|
||||||
|
Enable: true,
|
||||||
|
Redis: &RedisConfig{
|
||||||
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Key: "password",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: errors.New("redis passwordSecret.name cannot be empty"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "redis config with password secret missing key",
|
||||||
|
mcp: &McpServer{
|
||||||
|
Enable: true,
|
||||||
|
Redis: &RedisConfig{
|
||||||
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Name: "redis-credentials",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: errors.New("redis passwordSecret.key cannot be empty"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "valid config with redis",
|
name: "valid config with redis",
|
||||||
mcp: &McpServer{
|
mcp: &McpServer{
|
||||||
@@ -152,6 +176,20 @@ func Test_validMcpServer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "valid config with redis password secret",
|
||||||
|
mcp: &McpServer{
|
||||||
|
Enable: true,
|
||||||
|
Redis: &RedisConfig{
|
||||||
|
Address: "localhost:6379",
|
||||||
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Name: "redis-credentials",
|
||||||
|
Key: "password",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -265,7 +303,11 @@ func Test_deepCopyMcpServer(t *testing.T) {
|
|||||||
Address: "localhost:6379",
|
Address: "localhost:6379",
|
||||||
Username: "default",
|
Username: "default",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
DB: 0,
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Name: "redis-credentials",
|
||||||
|
Key: "password",
|
||||||
|
},
|
||||||
|
DB: 0,
|
||||||
},
|
},
|
||||||
MatchList: []*MatchRule{},
|
MatchList: []*MatchRule{},
|
||||||
Servers: []*SSEServer{},
|
Servers: []*SSEServer{},
|
||||||
@@ -276,7 +318,11 @@ func Test_deepCopyMcpServer(t *testing.T) {
|
|||||||
Address: "localhost:6379",
|
Address: "localhost:6379",
|
||||||
Username: "default",
|
Username: "default",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
DB: 0,
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Name: "redis-credentials",
|
||||||
|
Key: "password",
|
||||||
|
},
|
||||||
|
DB: 0,
|
||||||
},
|
},
|
||||||
MatchList: []*MatchRule{},
|
MatchList: []*MatchRule{},
|
||||||
Servers: []*SSEServer{},
|
Servers: []*SSEServer{},
|
||||||
@@ -291,7 +337,12 @@ func Test_deepCopyMcpServer(t *testing.T) {
|
|||||||
Address: "localhost:6379",
|
Address: "localhost:6379",
|
||||||
Username: "default",
|
Username: "default",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
DB: 0,
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Name: "redis-credentials",
|
||||||
|
Namespace: "custom-ns",
|
||||||
|
Key: "password",
|
||||||
|
},
|
||||||
|
DB: 0,
|
||||||
},
|
},
|
||||||
SSEPathSuffix: "/sse",
|
SSEPathSuffix: "/sse",
|
||||||
MatchList: []*MatchRule{
|
MatchList: []*MatchRule{
|
||||||
@@ -318,7 +369,12 @@ func Test_deepCopyMcpServer(t *testing.T) {
|
|||||||
Address: "localhost:6379",
|
Address: "localhost:6379",
|
||||||
Username: "default",
|
Username: "default",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
DB: 0,
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Name: "redis-credentials",
|
||||||
|
Namespace: "custom-ns",
|
||||||
|
Key: "password",
|
||||||
|
},
|
||||||
|
DB: 0,
|
||||||
},
|
},
|
||||||
SSEPathSuffix: "/sse",
|
SSEPathSuffix: "/sse",
|
||||||
MatchList: []*MatchRule{
|
MatchList: []*MatchRule{
|
||||||
@@ -706,6 +762,80 @@ func TestMcpServerController_constructMcpSessionStruct(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "config with password secret",
|
||||||
|
mcp: &McpServer{
|
||||||
|
Enable: true,
|
||||||
|
Redis: &RedisConfig{
|
||||||
|
Address: "localhost:6379",
|
||||||
|
Password: "ignored",
|
||||||
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Name: "redis-credentials",
|
||||||
|
Key: "password",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MatchList: []*MatchRule{},
|
||||||
|
Servers: []*SSEServer{},
|
||||||
|
},
|
||||||
|
wantJSON: `{
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
|
||||||
|
"library_id": "mcp-session",
|
||||||
|
"library_path": "/var/lib/istio/envoy/golang-filter.so",
|
||||||
|
"plugin_name": "mcp-session",
|
||||||
|
"plugin_config": {
|
||||||
|
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
|
||||||
|
"value": {
|
||||||
|
"redis": {
|
||||||
|
"address": "localhost:6379",
|
||||||
|
"username": "",
|
||||||
|
"password": "${secret.test-namespace/redis-credentials.password}",
|
||||||
|
"db": 0
|
||||||
|
},
|
||||||
|
"rate_limit": null,
|
||||||
|
"sse_path_suffix": "",
|
||||||
|
"match_list": [],
|
||||||
|
"enable_user_level_server": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "config with password secret and namespace",
|
||||||
|
mcp: &McpServer{
|
||||||
|
Enable: true,
|
||||||
|
Redis: &RedisConfig{
|
||||||
|
Address: "localhost:6379",
|
||||||
|
PasswordSecret: &SecretKeyReference{
|
||||||
|
Namespace: "other-ns",
|
||||||
|
Name: "redis-credentials",
|
||||||
|
Key: "password",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MatchList: []*MatchRule{},
|
||||||
|
Servers: []*SSEServer{},
|
||||||
|
},
|
||||||
|
wantJSON: `{
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
|
||||||
|
"library_id": "mcp-session",
|
||||||
|
"library_path": "/var/lib/istio/envoy/golang-filter.so",
|
||||||
|
"plugin_name": "mcp-session",
|
||||||
|
"plugin_config": {
|
||||||
|
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
|
||||||
|
"value": {
|
||||||
|
"redis": {
|
||||||
|
"address": "localhost:6379",
|
||||||
|
"username": "",
|
||||||
|
"password": "${secret.other-ns/redis-credentials.password}",
|
||||||
|
"db": 0
|
||||||
|
},
|
||||||
|
"rate_limit": null,
|
||||||
|
"sse_path_suffix": "",
|
||||||
|
"match_list": [],
|
||||||
|
"enable_user_level_server": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ data:
|
|||||||
redis:
|
redis:
|
||||||
address: redis-stack-server.higress-system.svc.cluster.local:6379 # Redis服务地址
|
address: redis-stack-server.higress-system.svc.cluster.local:6379 # Redis服务地址
|
||||||
username: "" # Redis用户名(可选)
|
username: "" # Redis用户名(可选)
|
||||||
password: "" # Redis密码(可选)
|
password: "" # Redis密码(可选,明文方式)
|
||||||
|
passwordSecret: # 从 Secret 引用密码(推荐,优先级高于 password)
|
||||||
|
name: redis-credentials # Secret 名称
|
||||||
|
key: password # Secret 中的 key
|
||||||
|
namespace: higress-system # Secret 所在命名空间(可选,默认为 higress-system)
|
||||||
db: 0 # Redis数据库(可选)
|
db: 0 # Redis数据库(可选)
|
||||||
match_list: # MCP Server 会话保持路由规则(当匹配下面路径时,将被识别为一个 MCP 会话,通过 SSE 等机制进行会话保持)
|
match_list: # MCP Server 会话保持路由规则(当匹配下面路径时,将被识别为一个 MCP 会话,通过 SSE 等机制进行会话保持)
|
||||||
- match_rule_domain: "*"
|
- match_rule_domain: "*"
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ data:
|
|||||||
redis:
|
redis:
|
||||||
address: redis-stack-server.higress-system.svc.cluster.local:6379 # Redis service address
|
address: redis-stack-server.higress-system.svc.cluster.local:6379 # Redis service address
|
||||||
username: "" # Redis username (optional)
|
username: "" # Redis username (optional)
|
||||||
password: "" # Redis password (optional)
|
password: "" # Redis password (optional, plaintext)
|
||||||
|
passwordSecret: # Reference password from Secret (recommended, higher priority than password)
|
||||||
|
name: redis-credentials # Secret name
|
||||||
|
key: password # Key in Secret
|
||||||
|
namespace: higress-system # Secret namespace (optional, defaults to higress-system)
|
||||||
db: 0 # Redis database (optional)
|
db: 0 # Redis database (optional)
|
||||||
match_list: # MCP Server session persistence routing rules (when matching the following paths, it will be recognized as an MCP session and maintained through SSE)
|
match_list: # MCP Server session persistence routing rules (when matching the following paths, it will be recognized as an MCP session and maintained through SSE)
|
||||||
- match_rule_domain: "*"
|
- match_rule_domain: "*"
|
||||||
|
|||||||
87
test/e2e/conformance/tests/configmap-mcp-redis-secret.go
Normal file
87
test/e2e/conformance/tests/configmap-mcp-redis-secret.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// Copyright (c) 2025 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/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/alibaba/higress/v2/pkg/ingress/kube/configmap"
|
||||||
|
"github.com/alibaba/higress/v2/test/e2e/conformance/utils/envoy"
|
||||||
|
"github.com/alibaba/higress/v2/test/e2e/conformance/utils/kubernetes"
|
||||||
|
"github.com/alibaba/higress/v2/test/e2e/conformance/utils/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Register(ConfigMapMcpRedisSecret)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ConfigMapMcpRedisSecret = suite.ConformanceTest{
|
||||||
|
ShortName: "ConfigMapMcpRedisSecret",
|
||||||
|
Description: "Envoy MCP session filter should resolve Redis password from Kubernetes secret and react to updates",
|
||||||
|
Manifests: []string{"tests/configmap-mcp-redis-secret.yaml"},
|
||||||
|
Features: []suite.SupportedFeature{suite.EnvoyConfigConformanceFeature},
|
||||||
|
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
|
||||||
|
const (
|
||||||
|
configMapNamespace = "higress-system"
|
||||||
|
configMapName = "higress-config"
|
||||||
|
configMapKey = "higress"
|
||||||
|
secretNamespace = "higress-system"
|
||||||
|
secretName = "redis-credentials"
|
||||||
|
secretKey = "password"
|
||||||
|
|
||||||
|
initialSecretValue = "InitialSecretFromSecret123"
|
||||||
|
updatedSecretValue = "UpdatedSecretFromSecret456"
|
||||||
|
)
|
||||||
|
|
||||||
|
higressCfg := &configmap.HigressConfig{
|
||||||
|
McpServer: &configmap.McpServer{
|
||||||
|
Enable: true,
|
||||||
|
SSEPathSuffix: "/sse",
|
||||||
|
Redis: &configmap.RedisConfig{
|
||||||
|
Address: "redis:6379",
|
||||||
|
PasswordSecret: &configmap.SecretKeyReference{
|
||||||
|
Name: secretName,
|
||||||
|
Key: secretKey,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := kubernetes.ApplyConfigmapDataWithYaml(t, suite.Client, configMapNamespace, configMapName, configMapKey, higressCfg)
|
||||||
|
require.NoErrorf(t, err, "failed to update %s/%s", configMapNamespace, configMapName)
|
||||||
|
|
||||||
|
assertRedisPassword := func(password string) {
|
||||||
|
envoy.AssertEnvoyConfig(t, suite.TimeoutConfig, envoy.Assertion{
|
||||||
|
Path: `configs.#(@type=="type.googleapis.com/envoy.admin.v3.EcdsConfigDump").` +
|
||||||
|
`ecds_filters.#(ecds_filter.name=="golang-filter-mcp-session").` +
|
||||||
|
`ecds_filter.typed_config.plugin_config.value.redis`,
|
||||||
|
CheckType: envoy.CheckTypeMatch,
|
||||||
|
TargetNamespace: configMapNamespace,
|
||||||
|
ExpectEnvoyConfig: map[string]interface{}{
|
||||||
|
"password": password,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
assertRedisPassword(initialSecretValue)
|
||||||
|
|
||||||
|
err = kubernetes.ApplySecret(t, suite.Client, secretNamespace, secretName, secretKey, updatedSecretValue)
|
||||||
|
require.NoErrorf(t, err, "failed to update %s/%s secret", secretNamespace, secretName)
|
||||||
|
|
||||||
|
assertRedisPassword(updatedSecretValue)
|
||||||
|
},
|
||||||
|
}
|
||||||
41
test/e2e/conformance/tests/configmap-mcp-redis-secret.yaml
Normal file
41
test/e2e/conformance/tests/configmap-mcp-redis-secret.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Copyright (c) 2025 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: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: redis-credentials
|
||||||
|
namespace: higress-system
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
password: InitialSecretFromSecret123
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: higress-conformance-infra-configmap-mcp-redis-secret-test
|
||||||
|
namespace: higress-conformance-infra
|
||||||
|
spec:
|
||||||
|
ingressClassName: higress
|
||||||
|
rules:
|
||||||
|
- host: "mcp-redis-secret.example.com"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: "/mcp"
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: infra-backend-v3
|
||||||
|
port:
|
||||||
|
number: 8080
|
||||||
Reference in New Issue
Block a user