Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions internal/gatewayapi/testdata/sds-invalid.in.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ backendTLSPolicies:
- name: regular-ca-secret
kind: Secret
hostname: example.com
# Test case 4: Invalid SDS URL (should be rejected)
- apiVersion: gateway.networking.k8s.io/v1alpha2
kind: BackendTLSPolicy
metadata:
name: policy-invalid-sds-url
namespace: default
spec:
targetRefs:
- kind: Service
name: service-4
validation:
caCertificateRefs:
- name: sds-ref-invalid-url
kind: Secret
hostname: example.com
httpRoutes:
- apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
Expand Down Expand Up @@ -109,6 +124,13 @@ httpRoutes:
backendRefs:
- name: service-3
port: 8080
- matches:
- path:
type: Exact
value: "/service4"
backendRefs:
- name: service-4
port: 8080
services:
- apiVersion: v1
kind: Service
Expand Down Expand Up @@ -207,7 +229,8 @@ secrets:
namespace: default
type: gateway.envoyproxy.io/sds
data:
url: L3Zhci9ydW4vc2VjcmV0cy93b3JrbG9hZC1zcGlmZmUtdWRzL3NvY2tldA== # /var/run/secrets/workload-spiffe-uds/socket
# unix:///var/run/secrets/workload-spiffe-uds/socket
url: dW5peDovLy92YXIvcnVuL3NlY3JldHMvd29ya2xvYWQtc3BpZmZlLXVkcy9zb2NrZXQ=
secretName: Uk9PVENB # ROOTCA
- apiVersion: v1
kind: Secret
Expand All @@ -216,8 +239,19 @@ secrets:
namespace: default
type: gateway.envoyproxy.io/sds
data:
url: L3Zhci9ydW4vc2VjcmV0cy93b3JrbG9hZC1zcGlmZmUtdWRzL3NvY2tldA== # /var/run/secrets/workload-spiffe-uds/socket
# unix:///var/run/secrets/workload-spiffe-uds/socket
url: dW5peDovLy92YXIvcnVuL3NlY3JldHMvd29ya2xvYWQtc3BpZmZlLXVkcy9zb2NrZXQ=
secretName: Uk9PVENBMg== # ROOTCA2
# SDS reference secret with an invalid (scheme-less) URL
- apiVersion: v1
kind: Secret
metadata:
name: sds-ref-invalid-url
namespace: default
type: gateway.envoyproxy.io/sds
data:
url: L3Zhci9ydW4vc2VjcmV0cy93b3JrbG9hZC1zcGlmZmUtdWRzL3NvY2tldA== # /var/run/secrets/workload-spiffe-uds/socket
secretName: Uk9PVENBMw== # ROOTCA3
# Regular secret with CA certificate
- apiVersion: v1
kind: Secret
Expand Down
59 changes: 59 additions & 0 deletions internal/gatewayapi/testdata/sds-invalid.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,44 @@ backendTLSPolicies:
status: "False"
type: ResolvedRefs
controllerName: gateway.envoyproxy.io/gatewayclass-controller
- apiVersion: gateway.networking.k8s.io/v1alpha2
kind: BackendTLSPolicy
metadata:
name: policy-invalid-sds-url
namespace: default
spec:
targetRefs:
- group: ""
kind: Service
name: service-4
validation:
caCertificateRefs:
- group: ""
kind: Secret
name: sds-ref-invalid-url
hostname: example.com
status:
ancestors:
- ancestorRef:
name: gateway-1
namespace: envoy-gateway
sectionName: http
conditions:
- lastTransitionTime: null
message: 'Invalid SDS reference secret sds-ref-invalid-url: invalid URL in
SDS reference secret default/sds-ref-invalid-url: unsupported URL scheme:
.'
reason: NoValidCACertificate
status: "False"
type: Accepted
- lastTransitionTime: null
message: 'Invalid SDS reference secret sds-ref-invalid-url: invalid URL in
SDS reference secret default/sds-ref-invalid-url: unsupported URL scheme:
.'
reason: InvalidCACertificateRef
status: "False"
type: ResolvedRefs
controllerName: gateway.envoyproxy.io/gatewayclass-controller
backends:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
Expand Down Expand Up @@ -201,6 +239,13 @@ httpRoutes:
- path:
type: Exact
value: /service3
- backendRefs:
- name: service-4
port: 8080
matches:
- path:
type: Exact
value: /service4
status:
parents:
- conditions:
Expand All @@ -214,6 +259,7 @@ httpRoutes:
Failed to process route rule 0 backendRef 0: multiple SDS reference secrets are not supported.
Failed to process route rule 1 backendRef 0: cannot mix SDS reference secrets with other CA certificate types.
Failed to process route rule 2 backendRef 0: cannot mix SDS reference secrets with other CA certificate types.
Failed to process route rule 3 backendRef 0: invalid SDS reference secret sds-ref-invalid-url: invalid URL in SDS reference secret default/sds-ref-invalid-url: unsupported URL scheme: .
reason: InvalidBackendTLS
status: "False"
type: ResolvedRefs
Expand Down Expand Up @@ -322,6 +368,19 @@ xdsIR:
distinct: false
exact: /service3
name: ""
- directResponse:
statusCode: 500
hostname: '*'
isHTTP2: false
metadata:
kind: HTTPRoute
name: httproute-1
namespace: default
name: httproute/default/httproute-1/rule/3/match/0/*
pathMatch:
distinct: false
exact: /service4
name: ""
readyListener:
address: 0.0.0.0
ipFamily: IPv4
Expand Down
8 changes: 4 additions & 4 deletions internal/gatewayapi/testdata/sds.in.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ secrets:
namespace: envoy-gateway-system
type: gateway.envoyproxy.io/sds
data:
# /var/run/secrets/workload-spiffe-uds/socket
url: L3Zhci9ydW4vc2VjcmV0cy93b3JrbG9hZC1zcGlmZmUtdWRzL3NvY2tldA==
# unix:///var/run/secrets/workload-spiffe-uds/socket
url: dW5peDovLy92YXIvcnVuL3NlY3JldHMvd29ya2xvYWQtc3BpZmZlLXVkcy9zb2NrZXQ=

@zhaohuabing zhaohuabing May 27, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This would break upgrades from v1.8.0 to v1.9.0. Would it make sense to default to UDS for url without scheme?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

it's experimental, it should be fine.
I'm fine to add compatibility in v1.9, cc @envoyproxy/gateway-maintainers WDYT?

@zhaohuabing zhaohuabing May 28, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If this breaking change is acceptable, it's better to cp this into v1.8.1 to break early.

secretName: ZGVmYXVsdA== # base64 for "default"
- apiVersion: v1
kind: Secret
Expand All @@ -90,6 +90,6 @@ secrets:
namespace: default
type: gateway.envoyproxy.io/sds
data:
# /var/run/secrets/workload-spiffe-uds/socket
url: L3Zhci9ydW4vc2VjcmV0cy93b3JrbG9hZC1zcGlmZmUtdWRzL3NvY2tldA==
# unix:///var/run/secrets/workload-spiffe-uds/socket
url: dW5peDovLy92YXIvcnVuL3NlY3JldHMvd29ya2xvYWQtc3BpZmZlLXVkcy9zb2NrZXQ=
secretName: Uk9PVENB # base64 for "ROOTCA"
6 changes: 4 additions & 2 deletions internal/gatewayapi/testdata/sds.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,15 @@ xdsIR:
caCertificate:
name: policy-btls/default-ca
sds:
address: /var/run/secrets/workload-spiffe-uds/socket
scheme: unix
secretName: ROOTCA
url: /var/run/secrets/workload-spiffe-uds/socket
clientCertificates:
- name: ""
sds:
address: /var/run/secrets/workload-spiffe-uds/socket
scheme: unix
secretName: default
url: /var/run/secrets/workload-spiffe-uds/socket
maxVersion: "1.3"
minVersion: "1.2"
sni: example.com
Expand Down
22 changes: 19 additions & 3 deletions internal/ir/xds.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
httputils "github.com/envoyproxy/gateway/internal/utils/http"
netutil "github.com/envoyproxy/gateway/internal/utils/net"
)

const (
Expand Down Expand Up @@ -492,13 +493,23 @@ type TLSCertificate struct {
type SDSConfig struct {
// SecretName is an identifier for the SDS configuration.
SecretName string `json:"secretName" yaml:"secretName"`
// URL is the URL of the SDS server
URL string `json:"url" yaml:"url"`
// Scheme is the communication scheme to use when connecting to the SDS server (e.g., "http", "https", or "unix").
Scheme string `json:"scheme" yaml:"scheme"`
// Address is the host and port of the SDS server
Address string `json:"address" yaml:"address"`

// TODO: support additional SDS configuration options
// such as TLS settings for the SDS server, or authentication credentials if needed.
}

func (s *SDSConfig) GetURL() string {
if s.Scheme == "" {
return s.Address
}

return fmt.Sprintf("%s://%s", s.Scheme, s.Address)
}

func NewSDSConfig(s *corev1.Secret) (*SDSConfig, error) {
sdsSecretName, hasSecretName := s.Data["secretName"]
sdsURLBytes, hasURL := s.Data["url"]
Expand All @@ -509,10 +520,15 @@ func NewSDSConfig(s *corev1.Secret) (*SDSConfig, error) {
if !hasURL || len(sdsURLBytes) == 0 {
return nil, fmt.Errorf("no url found in SDS reference secret %s/%s", s.Namespace, s.Name)
}
scheme, hostAndPort, err := netutil.ParseURL(string(sdsURLBytes)) // validate the URL format
if err != nil {
return nil, fmt.Errorf("invalid URL in SDS reference secret %s/%s: %w", s.Namespace, s.Name, err)
}

return &SDSConfig{
SecretName: string(sdsSecretName),
URL: string(sdsURLBytes),
Scheme: scheme,
Address: hostAndPort,
}, nil
}

Expand Down
41 changes: 41 additions & 0 deletions internal/utils/net/url.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

package net

import (
"fmt"
"net/url"
)

// ParseURL return host and port if the URL is a valid HTTP, HTTPS or UDS,
// return the scheme and host:port if it's valid.
func ParseURL(urlStr string) (scheme, hostAndPort string, err error) {
u, err := url.Parse(urlStr)
if err != nil {
return "", "", fmt.Errorf("invalid URL: %w", err)
}

switch u.Scheme {
case "http", "https":
Comment thread
zirain marked this conversation as resolved.
// TODO: support http and https scheme
return "", "", fmt.Errorf("unsupported URL scheme: %s", u.Scheme)
case "unix":
// For Unix Domain Socket, return the path as host, empty port.
// unix:///absolute/path has empty host and path="/absolute/path".
// unix://./relative/path (SPIFFE workload API format) has host="." and path="/relative/path";
// combine them so the caller receives "./relative/path".
if u.Host != "" && u.Host != "." {
return "", "", fmt.Errorf("unix URL must not contain a host, use unix:///absolute/path")
}
if u.Path == "" && u.Host != "." {
return "", "", fmt.Errorf("unix URL must contain a path")
}

return u.Scheme, u.Host + u.Path, nil
default:
return "", "", fmt.Errorf("unsupported URL scheme: %s", u.Scheme)
}
}
Loading