This is an automated email from the ASF dual-hosted git repository.
shreemaan-abhishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git
The following commit(s) were added to refs/heads/master by this push:
new e58f6e85 fix: reject invalid GatewayProxy plugin configuration (#2878)
e58f6e85 is described below
commit e58f6e853dfc4fe41dc22168a8c9dd6d25c82b38
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Fri Oct 9 14:40:32 2026 +0800
fix: reject invalid GatewayProxy plugin configuration (#2878)
---
internal/adc/translator/gateway.go | 30 ++++--
.../adc/translator/gatewayproxy_plugins_test.go | 103 +++++++++++++++++++++
internal/adc/translator/ingressclass.go | 8 +-
3 files changed, 129 insertions(+), 12 deletions(-)
diff --git a/internal/adc/translator/gateway.go
b/internal/adc/translator/gateway.go
index 68dcae81..1ab55a90 100644
--- a/internal/adc/translator/gateway.go
+++ b/internal/adc/translator/gateway.go
@@ -60,8 +60,12 @@ func (t *Translator) TranslateGateway(tctx
*provider.TranslateContext, obj *gate
globalRules := make(adctypes.GlobalRule)
pluginMetadata := make(adctypes.PluginMetadata)
// apply plugins from GatewayProxy to global rules
- t.fillPluginsFromGatewayProxy(globalRules, &gatewayProxy)
- t.fillPluginMetadataFromGatewayProxy(pluginMetadata, &gatewayProxy)
+ if err := t.fillPluginsFromGatewayProxy(globalRules, &gatewayProxy);
err != nil {
+ return nil, err
+ }
+ if err := t.fillPluginMetadataFromGatewayProxy(pluginMetadata,
&gatewayProxy); err != nil {
+ return nil, err
+ }
result.GlobalRules = globalRules
result.PluginMetadata = pluginMetadata
@@ -237,9 +241,9 @@ func (t *Translator) translateFrontendValidation(tctx
*provider.TranslateContext
}
// fillPluginsFromGatewayProxy fill plugins from GatewayProxy to given plugins
-func (t *Translator) fillPluginsFromGatewayProxy(plugins adctypes.GlobalRule,
gatewayProxy *v1alpha1.GatewayProxy) {
+func (t *Translator) fillPluginsFromGatewayProxy(plugins adctypes.GlobalRule,
gatewayProxy *v1alpha1.GatewayProxy) error {
if gatewayProxy == nil {
- return
+ return nil
}
for _, plugin := range gatewayProxy.Spec.Plugins {
@@ -252,26 +256,32 @@ func (t *Translator) fillPluginsFromGatewayProxy(plugins
adctypes.GlobalRule, ga
pluginConfig := map[string]any{}
if len(plugin.Config.Raw) > 0 {
if err := json.Unmarshal(plugin.Config.Raw,
&pluginConfig); err != nil {
- t.Log.Error(err, "gateway proxy plugin config
unmarshal failed", "plugin", pluginName)
- continue
+ return fmt.Errorf("failed to unmarshal config
of GatewayProxy plugin %q: %w", pluginName, err)
+ }
+ if pluginConfig == nil {
+ return fmt.Errorf("config of GatewayProxy
plugin %q must be a JSON object", pluginName)
}
}
plugins[pluginName] = pluginConfig
}
t.Log.V(1).Info("fill plugins for gateway proxy", "plugins", plugins)
+ return nil
}
-func (t *Translator) fillPluginMetadataFromGatewayProxy(pluginMetadata
adctypes.PluginMetadata, gatewayProxy *v1alpha1.GatewayProxy) {
+func (t *Translator) fillPluginMetadataFromGatewayProxy(pluginMetadata
adctypes.PluginMetadata, gatewayProxy *v1alpha1.GatewayProxy) error {
if gatewayProxy == nil {
- return
+ return nil
}
for pluginName, plugin := range gatewayProxy.Spec.PluginMetadata {
var pluginConfig map[string]any
if err := json.Unmarshal(plugin.Raw, &pluginConfig); err != nil
{
- t.Log.Error(err, "gateway proxy plugin_metadata
unmarshal failed", "plugin", pluginName)
- continue
+ return fmt.Errorf("failed to unmarshal GatewayProxy
plugin metadata for %q: %w", pluginName, err)
+ }
+ if pluginConfig == nil {
+ return fmt.Errorf("GatewayProxy plugin metadata for %q
must be a JSON object", pluginName)
}
t.Log.V(1).Info("fill plugin_metadata for gateway proxy",
"plugin", pluginName)
pluginMetadata[pluginName] = pluginConfig
}
+ return nil
}
diff --git a/internal/adc/translator/gatewayproxy_plugins_test.go
b/internal/adc/translator/gatewayproxy_plugins_test.go
new file mode 100644
index 00000000..a3275925
--- /dev/null
+++ b/internal/adc/translator/gatewayproxy_plugins_test.go
@@ -0,0 +1,103 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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 translator
+
+import (
+ "context"
+ "testing"
+
+ "github.com/go-logr/logr"
+ "github.com/stretchr/testify/require"
+ networkingv1 "k8s.io/api/networking/v1"
+ apiextensionsv1
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
+
+ "github.com/apache/apisix-ingress-controller/api/v1alpha1"
+ "github.com/apache/apisix-ingress-controller/internal/provider"
+ "github.com/apache/apisix-ingress-controller/internal/utils"
+)
+
+func TestGatewayProxyPluginRenderingErrors(t *testing.T) {
+ invalidConfigs := []struct {
+ name string
+ configure func(*v1alpha1.GatewayProxy)
+ errText string
+ }{
+ {
+ name: "plugin config",
+ configure: func(gatewayProxy *v1alpha1.GatewayProxy) {
+ gatewayProxy.Spec.Plugins =
[]v1alpha1.GatewayProxyPlugin{
+ {
+ Name: "response-rewrite",
+ Enabled: true,
+ Config:
apiextensionsv1.JSON{Raw: []byte(`["not-an-object"]`)},
+ },
+ }
+ },
+ errText: `failed to unmarshal config of GatewayProxy
plugin "response-rewrite"`,
+ },
+ {
+ name: "plugin metadata",
+ configure: func(gatewayProxy *v1alpha1.GatewayProxy) {
+ gatewayProxy.Spec.PluginMetadata =
map[string]apiextensionsv1.JSON{
+ "key-auth": {Raw:
[]byte(`["not-an-object"]`)},
+ }
+ },
+ errText: `failed to unmarshal GatewayProxy plugin
metadata for "key-auth"`,
+ },
+ }
+
+ callers := []struct {
+ name string
+ translate func(*Translator, v1alpha1.GatewayProxy)
(*TranslateResult, error)
+ }{
+ {
+ name: "Gateway",
+ translate: func(tr *Translator, gatewayProxy
v1alpha1.GatewayProxy) (*TranslateResult, error) {
+ tctx :=
provider.NewDefaultTranslateContext(context.Background())
+ gateway := &gatewayv1.Gateway{ObjectMeta:
metav1.ObjectMeta{Namespace: "default", Name: "gateway"}}
+
tctx.GatewayProxies[utils.NamespacedNameKind(gateway)] = gatewayProxy
+ return tr.TranslateGateway(tctx, gateway)
+ },
+ },
+ {
+ name: "IngressClass",
+ translate: func(tr *Translator, gatewayProxy
v1alpha1.GatewayProxy) (*TranslateResult, error) {
+ tctx :=
provider.NewDefaultTranslateContext(context.Background())
+ ingressClass :=
&networkingv1.IngressClass{ObjectMeta: metav1.ObjectMeta{Name: "apisix"}}
+
tctx.GatewayProxies[utils.NamespacedNameKind(ingressClass)] = gatewayProxy
+ return tr.TranslateIngressClass(tctx,
ingressClass)
+ },
+ },
+ }
+
+ for _, caller := range callers {
+ for _, invalidConfig := range invalidConfigs {
+ t.Run(caller.name+"/"+invalidConfig.name, func(t
*testing.T) {
+ tr := &Translator{Log: logr.Discard()}
+ gatewayProxy := v1alpha1.GatewayProxy{}
+ invalidConfig.configure(&gatewayProxy)
+
+ result, err := caller.translate(tr,
gatewayProxy)
+ require.ErrorContains(t, err,
invalidConfig.errText)
+ require.Nil(t, result)
+ })
+ }
+ }
+}
diff --git a/internal/adc/translator/ingressclass.go
b/internal/adc/translator/ingressclass.go
index 064bd77d..9052fc56 100644
--- a/internal/adc/translator/ingressclass.go
+++ b/internal/adc/translator/ingressclass.go
@@ -38,8 +38,12 @@ func (t *Translator) TranslateIngressClass(tctx
*provider.TranslateContext, obj
globalRules := make(adctypes.GlobalRule)
pluginMetadata := make(adctypes.PluginMetadata)
// apply plugins from GatewayProxy to global rules
- t.fillPluginsFromGatewayProxy(globalRules, &gatewayProxy)
- t.fillPluginMetadataFromGatewayProxy(pluginMetadata, &gatewayProxy)
+ if err := t.fillPluginsFromGatewayProxy(globalRules, &gatewayProxy);
err != nil {
+ return nil, err
+ }
+ if err := t.fillPluginMetadataFromGatewayProxy(pluginMetadata,
&gatewayProxy); err != nil {
+ return nil, err
+ }
result.GlobalRules = globalRules
result.PluginMetadata = pluginMetadata