From a58e8811a87ca3d4187d8fb1bf6a294066e5b6bd Mon Sep 17 00:00:00 2001 From: Abhishek Choudhary Date: Sun, 19 Jul 2026 14:24:03 +0545 Subject: [PATCH] fix: verify control-plane TLS certificate by default GatewayProxy's controlPlane.tlsVerify is a *bool with no default, so omitting it left the Go zero value false, which the executor inverts to tlsSkipVerify:true. A fresh install following the shipped https examples therefore skipped certificate verification on the channel carrying the AdminKey. Default tlsVerify to true via +kubebuilder:default=true and a secure default in the translator before honoring an explicit override, so only an explicit tlsVerify:false opts out. Regenerate CRD/docs and add a translator test locking in the default. Signed-off-by: Abhishek Choudhary --- api/v1alpha1/gatewayproxy_types.go | 3 + config/crd-nocel/apisix.apache.org_v2.yaml | 7 +- .../apisix.apache.org_gatewayproxies.yaml | 7 +- docs/en/latest/reference/api-reference.md | 2 +- internal/adc/translator/gatewayproxy.go | 3 + internal/adc/translator/gatewayproxy_test.go | 74 +++++++++++++++++++ 6 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 internal/adc/translator/gatewayproxy_test.go diff --git a/api/v1alpha1/gatewayproxy_types.go b/api/v1alpha1/gatewayproxy_types.go index 680fa8a9..9e7d8afe 100644 --- a/api/v1alpha1/gatewayproxy_types.go +++ b/api/v1alpha1/gatewayproxy_types.go @@ -133,7 +133,10 @@ type ControlPlaneProvider struct { Service *ProviderService `json:"service,omitempty"` // TlsVerify specifies whether to verify the TLS certificate of the control plane. + // Defaults to true. Setting it to false disables certificate verification and + // exposes the AdminKey to man-in-the-middle attacks over https endpoints. // +optional + // +kubebuilder:default=true TlsVerify *bool `json:"tlsVerify,omitempty"` // Auth specifies the authentication configuration. diff --git a/config/crd-nocel/apisix.apache.org_v2.yaml b/config/crd-nocel/apisix.apache.org_v2.yaml index 9e4cc186..12deb692 100644 --- a/config/crd-nocel/apisix.apache.org_v2.yaml +++ b/config/crd-nocel/apisix.apache.org_v2.yaml @@ -2295,8 +2295,11 @@ spec: - name type: object tlsVerify: - description: TlsVerify specifies whether to verify the TLS - certificate of the control plane. + default: true + description: |- + TlsVerify specifies whether to verify the TLS certificate of the control plane. + Defaults to true. Setting it to false disables certificate verification and + exposes the AdminKey to man-in-the-middle attacks over https endpoints. type: boolean required: - auth diff --git a/config/crd/bases/apisix.apache.org_gatewayproxies.yaml b/config/crd/bases/apisix.apache.org_gatewayproxies.yaml index 23a7ed50..ab10c758 100644 --- a/config/crd/bases/apisix.apache.org_gatewayproxies.yaml +++ b/config/crd/bases/apisix.apache.org_gatewayproxies.yaml @@ -147,8 +147,11 @@ spec: - name type: object tlsVerify: - description: TlsVerify specifies whether to verify the TLS - certificate of the control plane. + default: true + description: |- + TlsVerify specifies whether to verify the TLS certificate of the control plane. + Defaults to true. Setting it to false disables certificate verification and + exposes the AdminKey to man-in-the-middle attacks over https endpoints. type: boolean required: - auth diff --git a/docs/en/latest/reference/api-reference.md b/docs/en/latest/reference/api-reference.md index 5059f1d7..31f38468 100644 --- a/docs/en/latest/reference/api-reference.md +++ b/docs/en/latest/reference/api-reference.md @@ -312,7 +312,7 @@ ControlPlaneProvider defines configuration for control plane provider. | `mode` _string_ | Mode specifies the mode of control plane provider. Can be `apisix` or `apisix-standalone`. | | `endpoints` _string array_ | Endpoints specifies the list of control plane endpoints. | | `service` _[ProviderService](#providerservice)_ | | -| `tlsVerify` _boolean_ | TlsVerify specifies whether to verify the TLS certificate of the control plane. | +| `tlsVerify` _boolean_ | TlsVerify specifies whether to verify the TLS certificate of the control plane. Defaults to true. Setting it to false disables certificate verification and exposes the AdminKey to man-in-the-middle attacks over https endpoints. | | `auth` _[ControlPlaneAuth](#controlplaneauth)_ | Auth specifies the authentication configuration. | diff --git a/internal/adc/translator/gatewayproxy.go b/internal/adc/translator/gatewayproxy.go index 13ace18d..afecf8e5 100644 --- a/internal/adc/translator/gatewayproxy.go +++ b/internal/adc/translator/gatewayproxy.go @@ -52,6 +52,9 @@ func (t *Translator) TranslateGatewayProxyToConfig(tctx *provider.TranslateConte BackendType: cp.Mode, } + // Verify the control plane's TLS certificate by default; only an explicit + // tlsVerify:false opts out. + cfg.TlsVerify = true if cp.TlsVerify != nil { cfg.TlsVerify = *cp.TlsVerify } diff --git a/internal/adc/translator/gatewayproxy_test.go b/internal/adc/translator/gatewayproxy_test.go new file mode 100644 index 00000000..1d0ea323 --- /dev/null +++ b/internal/adc/translator/gatewayproxy_test.go @@ -0,0 +1,74 @@ +// 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" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/apisix-ingress-controller/api/v1alpha1" + "github.com/apache/apisix-ingress-controller/internal/provider" +) + +func TestTranslateGatewayProxyToConfig_TlsVerifyDefault(t *testing.T) { + newProxy := func(tlsVerify *bool) *v1alpha1.GatewayProxy { + return &v1alpha1.GatewayProxy{ + ObjectMeta: metav1.ObjectMeta{Name: "gp", Namespace: "default"}, + Spec: v1alpha1.GatewayProxySpec{ + Provider: &v1alpha1.GatewayProxyProvider{ + Type: v1alpha1.ProviderTypeControlPlane, + ControlPlane: &v1alpha1.ControlPlaneProvider{ + Endpoints: []string{"https://127.0.0.1:7443"}, + TlsVerify: tlsVerify, + Auth: v1alpha1.ControlPlaneAuth{ + Type: v1alpha1.AuthTypeAdminKey, + AdminKey: &v1alpha1.AdminKeyAuth{Value: "secret"}, + }, + }, + }, + }, + } + } + + tr := false + tt := true + cases := []struct { + name string + tlsVerify *bool + want bool + }{ + {"unset defaults to verify", nil, true}, + {"explicit false opts out", &tr, false}, + {"explicit true verifies", &tt, true}, + } + + translator := NewTranslator(logr.Discard()) + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + tctx := provider.NewDefaultTranslateContext(context.Background()) + cfg, err := translator.TranslateGatewayProxyToConfig(tctx, newProxy(c.tlsVerify), false) + require.NoError(t, err) + require.NotNil(t, cfg) + require.Equal(t, c.want, cfg.TlsVerify) + }) + } +}