Skip to content

fix: verify control-plane TLS certificate by default - #438

Open
shreemaan-abhishek wants to merge 5 commits into
masterfrom
fix/tlsverify-secure-default
Open

shreemaan-abhishek wants to merge 5 commits into
masterfrom
fix/tlsverify-secure-default

Conversation

@shreemaan-abhishek

@shreemaan-abhishek shreemaan-abhishek commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

What this PR does

GatewayProxy spec.provider.controlPlane.tlsVerify is a *bool with no default. When omitted (as the shipped example manifests do, while pointing at https:// Admin API endpoints), it decodes to nil, the translator leaves cfg.TlsVerify at the Go zero value false, and the executor inverts that into tlsSkipVerify: true. The result is that a default install skips certificate verification on the connection that carries the AdminKey and the full gateway config.

This makes verification the secure default:

  • +kubebuilder:default=true on the CRD field, so an omitted tlsVerify becomes true.
  • cfg.TlsVerify = true in the translator before honoring an explicit value, so behavior is correct even against an older CRD without the default. Only an explicit tlsVerify: false opts out.
  • Regenerated CRD manifests (bases + crd-nocel) and API reference docs; documented that setting it to false disables certificate verification.

Testing

Added a translator unit test asserting the default: unset -> verify, explicit false -> skip, explicit true -> verify.

go test ./internal/adc/translator/ -run TestTranslateGatewayProxyToConfig_TlsVerifyDefault

Synced with apache/apisix-ingress-controller#2811.

Summary by CodeRabbit

  • New Features

    • Added support for supplying PEM-encoded CA certificates for control-plane TLS verification.
    • Supports certificate bundles; invalid or malformed certificates are rejected.
    • Supplied certificates have no effect when verification is disabled.
  • Bug Fixes

    • TLS certificate verification now defaults to enabled when unspecified.
    • Explicitly setting verification to false continues to disable certificate checks.
  • Documentation

    • Updated API, CRD, and upgrade guidance with default behavior and security warnings.
  • Tests

    • Added coverage for CA certificates, validation, bundles, and verification settings.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Essentials

Run ID: a7dee0bc-d4f6-4990-b340-2df8d0d69f30

📥 Commits

Reviewing files that changed from the base of the PR and between f6e8103 and 688d837.

📒 Files selected for processing (7)
  • docs/en/latest/upgrade-guide.md
  • examples/httpbin/httproute.yaml
  • examples/httpbin/ingress.yaml
  • examples/httpbin/quickstart.yaml
  • examples/httpbin/tcproute.yaml
  • test/e2e/api7/route.go
  • test/e2e/scaffold/k8s.go

Included review availability: 1 review is currently available. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.


📝 Walkthrough

Walkthrough

tlsVerify now defaults to true. ControlPlaneProvider accepts an optional PEM CA certificate. Translation validates CA certificates and preserves explicit TLS verification settings.

Changes

Control-plane TLS configuration

Layer / File(s) Summary
TLS verification and CA certificate contract
api/v1alpha1/gatewayproxy_types.go, config/crd...
The API types and CRD schemas define the tlsVerify default, its security behavior, and the optional caCert PEM value.
CA certificate validation and TLS translation
internal/adc/translator/gatewayproxy.go
Translation validates certificate bundles, rejects invalid certificates, logs when verification is disabled, and passes backend ports directly.
TLS configuration test coverage
internal/adc/translator/gatewayproxy_test.go
Tests use a shared GatewayProxy fixture and cover CA certificates and unset, false, and true tlsVerify values.
TLS migration guidance and development configurations
docs/en/latest/..., examples/httpbin/*, test/e2e/...
Documentation describes the new default and CA configuration. Local development and end-to-end configurations disable verification for self-signed endpoints.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant GatewayProxy
  participant Translator
  participant CertificateValidator
  GatewayProxy->>Translator: Submit tlsVerify and caCert
  Translator->>CertificateValidator: Validate CA certificate bundle
  CertificateValidator-->>Translator: Return validation result
  Translator-->>GatewayProxy: Return translated configuration or error
Loading

Suggested reviewers: jarvis9443, alinsran

Merge Risk: ⚪ Minimal · up to 688d8

The secure TLS default, explicit development opt-outs, translator fallback, and migration guidance are consistent and ready for normal checks.

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
E2e Test Quality Review ⚠️ Warning Blocking E2E coverage is missing for the PR's main behavior. The new test in internal/adc/translator/gatewayproxy_test.go is a unit test for TlsVerify; no E2E test was added. The changed E2E fixtu… Add an E2E case that uses the existing HTTPS control-plane fixture, omits tlsVerify, supplies the private CA, and asserts that a route is programmed and serves successfully. Add or retain a separate explicit tlsVerify: false case with a…
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: enabling control-plane TLS certificate verification by default.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed No explicit security-check failure condition was introduced. (1) No new sensitive value is logged or returned; the changed translator log contains only the GatewayProxy identity, and the existing ADC …
Full details: E2e Test Quality Review

Explanation

Blocking E2E coverage is missing for the PR's main behavior. The new test in internal/adc/translator/gatewayproxy_test.go is a unit test for TlsVerify; no E2E test was added. The changed E2E fixtures set tlsVerify: false for self-signed API7 endpoints. The existing HTTPS control-plane E2E suite is unchanged from the base and explicitly sets tlsVerify: true, so it does not verify that an omitted field enables certificate verification through the full GatewayProxy → ADC → control-plane → route flow.

Resolution

Add an E2E case that uses the existing HTTPS control-plane fixture, omits tlsVerify, supplies the private CA, and asserts that a route is programmed and serves successfully. Add or retain a separate explicit tlsVerify: false case with a self-signed certificate. Keep assertions on both the successful route response and the expected failure when verification is enabled without the CA.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tlsverify-secure-default

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

conformance test report - apisix-standalone mode

apiVersion: gateway.networking.k8s.io/v1
date: "2026-09-14T07:50:59Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.6.0
implementation:
  contact:
  - https://github.com/apache/apisix-ingress-controller/issues
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    result: partial
    skippedTests:
    - HTTPRouteHTTPSListener
    - HTTPRouteInvalidBackendRefUnknownKind
    - HTTPRouteInvalidCrossNamespaceBackendRef
    - HTTPRouteInvalidNonExistentBackendRef
    - HTTPRouteListenerHostnameMatching
    - HTTPRouteMultipleGateways
    - HTTPRouteNoBackendRefs
    statistics:
      Failed: 0
      Passed: 30
      Skipped: 7
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 12
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - BackendTLSPolicy
    - BackendTLSPolicySANValidation
    - GatewayBackendClientCertificate
    - GatewayFrontendClientCertificateValidation
    - GatewayFrontendClientCertificateValidationInsecureFallback
    - GatewayHTTPListenerIsolation
    - GatewayHTTPSListenerDetectMisdirectedRequests
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRoute303RedirectStatusCode
    - HTTPRoute307RedirectStatusCode
    - HTTPRoute308RedirectStatusCode
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteCORS
    - HTTPRouteNamedRouteRule
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
    - HTTPRouteRetry
    - HTTPRouteRetryBackendTimeout
    - HTTPRouteRetryConnectionError
    - ListenerSet
  name: GATEWAY-HTTP
  summary: Core tests partially succeeded with 7 test skips. Extended tests partially
    succeeded with 1 test skips.
- core:
    result: partial
    skippedTests:
    - GRPCRouteListenerHostnameMatching
    statistics:
      Failed: 0
      Passed: 14
      Skipped: 1
  extended:
    result: success
    statistics:
      Failed: 0
      Passed: 1
      Skipped: 0
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    unsupportedFeatures:
    - GatewayBackendClientCertificate
    - GatewayFrontendClientCertificateValidation
    - GatewayFrontendClientCertificateValidationInsecureFallback
    - GatewayHTTPListenerIsolation
    - GatewayHTTPSListenerDetectMisdirectedRequests
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - ListenerSet
  name: GATEWAY-GRPC
  summary: Core tests partially succeeded with 1 test skips. Extended tests succeeded.
- core:
    result: partial
    skippedTests:
    - TLSRouteHostnameIntersection
    - TLSRouteInvalidBackendRefNonexistent
    - TLSRouteInvalidBackendRefUnknownKind
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 16
      Skipped: 4
  extended:
    result: partial
    skippedTests:
    - TLSRouteTerminateSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 3
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - TLSRouteModeTerminate
    unsupportedFeatures:
    - GatewayBackendClientCertificate
    - GatewayFrontendClientCertificateValidation
    - GatewayFrontendClientCertificateValidationInsecureFallback
    - GatewayHTTPListenerIsolation
    - GatewayHTTPSListenerDetectMisdirectedRequests
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - ListenerSet
    - TLSRouteModeMixed
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 4 test skips. Extended tests partially
    succeeded with 1 test skips.
succeededProvisionalTests:
- GatewayOptionalAddressValue

@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

conformance test report - apisix mode

apiVersion: gateway.networking.k8s.io/v1
date: "2026-09-14T07:51:18Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.6.0
implementation:
  contact:
  - https://github.com/apache/apisix-ingress-controller/issues
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    result: partial
    skippedTests:
    - HTTPRouteHTTPSListener
    - HTTPRouteInvalidBackendRefUnknownKind
    - HTTPRouteInvalidCrossNamespaceBackendRef
    - HTTPRouteInvalidNonExistentBackendRef
    - HTTPRouteListenerHostnameMatching
    - HTTPRouteMultipleGateways
    - HTTPRouteNoBackendRefs
    statistics:
      Failed: 0
      Passed: 30
      Skipped: 7
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 12
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - BackendTLSPolicy
    - BackendTLSPolicySANValidation
    - GatewayBackendClientCertificate
    - GatewayFrontendClientCertificateValidation
    - GatewayFrontendClientCertificateValidationInsecureFallback
    - GatewayHTTPListenerIsolation
    - GatewayHTTPSListenerDetectMisdirectedRequests
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRoute303RedirectStatusCode
    - HTTPRoute307RedirectStatusCode
    - HTTPRoute308RedirectStatusCode
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteCORS
    - HTTPRouteNamedRouteRule
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
    - HTTPRouteRetry
    - HTTPRouteRetryBackendTimeout
    - HTTPRouteRetryConnectionError
    - ListenerSet
  name: GATEWAY-HTTP
  summary: Core tests partially succeeded with 7 test skips. Extended tests partially
    succeeded with 1 test skips.
- core:
    result: partial
    skippedTests:
    - GRPCRouteListenerHostnameMatching
    statistics:
      Failed: 0
      Passed: 14
      Skipped: 1
  extended:
    result: success
    statistics:
      Failed: 0
      Passed: 1
      Skipped: 0
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    unsupportedFeatures:
    - GatewayBackendClientCertificate
    - GatewayFrontendClientCertificateValidation
    - GatewayFrontendClientCertificateValidationInsecureFallback
    - GatewayHTTPListenerIsolation
    - GatewayHTTPSListenerDetectMisdirectedRequests
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - ListenerSet
  name: GATEWAY-GRPC
  summary: Core tests partially succeeded with 1 test skips. Extended tests succeeded.
- core:
    result: partial
    skippedTests:
    - TLSRouteHostnameIntersection
    - TLSRouteInvalidBackendRefNonexistent
    - TLSRouteInvalidBackendRefUnknownKind
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 16
      Skipped: 4
  extended:
    result: partial
    skippedTests:
    - TLSRouteTerminateSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 3
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - TLSRouteModeTerminate
    unsupportedFeatures:
    - GatewayBackendClientCertificate
    - GatewayFrontendClientCertificateValidation
    - GatewayFrontendClientCertificateValidationInsecureFallback
    - GatewayHTTPListenerIsolation
    - GatewayHTTPSListenerDetectMisdirectedRequests
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - ListenerSet
    - TLSRouteModeMixed
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 4 test skips. Extended tests partially
    succeeded with 1 test skips.
succeededProvisionalTests:
- GatewayOptionalAddressValue

@shreemaan-abhishek shreemaan-abhishek self-assigned this Jul 20, 2026
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 <shreemaan.abhishek@gmail.com>
@shreemaan-abhishek
shreemaan-abhishek force-pushed the fix/tlsverify-secure-default branch from ae51fe0 to a58e881 Compare July 22, 2026 09:52
// 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This default breaks the live suites in this PR: the July 25 E2E rerun sends tlsSkipVerify:false to the HTTPS control plane and every sync returns self-signed certificate; the conformance and three E2E jobs fail for the same reason. This is not only test plumbing: ControlPlaneProvider and the ADC task expose no CA bundle, so private-CA deployments can only set tlsVerify:false. Please provide a trusted-CA path and an upgrade migration, then update the generated test and example GatewayProxy manifests before changing the default.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in the latest push:

  • Control-plane CA support has landed in feat: support a CA bundle for the control plane connection #447, the ADC-side support has landed in feat(server): support custom tls config per endpoint adc#552, and the controller now pins ADC 0.29.0.
  • All four self-signed local examples explicitly set tlsVerify: false and label it as development-only.
  • Both API7 E2E GatewayProxy templates that use the self-signed HTTPS dashboard endpoint now explicitly set tlsVerify: false.
  • The upgrade guide documents the effect of CRD defaulting on existing GatewayProxy objects and the migration paths through the system trust store, caCert, or a temporary development opt-out.
  • The branch is merged with current master; translator, scaffold, and API7 E2E packages compile successfully.

…e-default

Signed-off-by: Abhishek Choudhary <shreemaan.abhishek@gmail.com>

# Conflicts:
#	docs/en/latest/reference/api-reference.md
#	internal/adc/translator/gatewayproxy_test.go
Signed-off-by: Abhishek Choudhary <shreemaan.abhishek@gmail.com>
Signed-off-by: Abhishek Choudhary <shreemaan.abhishek@gmail.com>
Signed-off-by: Abhishek Choudhary <shreemaan.abhishek@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants