Skip to content

Commit b4f63d3

Browse files
committed
Validate URI SANs
1 parent 190da92 commit b4f63d3

File tree

8 files changed

+564
-222
lines changed

8 files changed

+564
-222
lines changed

conformance/base/manifests.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,39 @@ spec:
9595
matchLabels:
9696
gateway-conformance: backend
9797
---
98+
apiVersion: gateway.networking.k8s.io/v1
99+
kind: Gateway
100+
metadata:
101+
name: gateway-backendtlspolicy
102+
namespace: gateway-conformance-infra
103+
spec:
104+
gatewayClassName: "{GATEWAY_CLASS_NAME}"
105+
listeners:
106+
- name: http
107+
port: 80
108+
protocol: HTTP
109+
hostname: "abc.example.com"
110+
allowedRoutes:
111+
namespaces:
112+
from: Same
113+
kinds:
114+
- kind: HTTPRoute
115+
- name: https
116+
port: 443
117+
protocol: HTTPS
118+
tls:
119+
mode: Terminate
120+
certificateRefs:
121+
- group: ""
122+
kind: Secret
123+
name: tls-checks-certificate
124+
hostname: "abc.example.com"
125+
allowedRoutes:
126+
namespaces:
127+
from: Same
128+
kinds:
129+
- kind: HTTPRoute
130+
---
98131
apiVersion: v1
99132
kind: Service
100133
metadata:
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package tests
18+
19+
import (
20+
"testing"
21+
22+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23+
"k8s.io/apimachinery/pkg/types"
24+
25+
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
26+
"sigs.k8s.io/gateway-api/apis/v1alpha2"
27+
h "sigs.k8s.io/gateway-api/conformance/utils/http"
28+
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
29+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
30+
"sigs.k8s.io/gateway-api/pkg/features"
31+
)
32+
33+
func init() {
34+
ConformanceTests = append(ConformanceTests, BackendTLSPolicySANValidation)
35+
}
36+
37+
var BackendTLSPolicySANValidation = suite.ConformanceTest{
38+
ShortName: "BackendTLSPolicySANValidation",
39+
Description: "BackendTLSPolicySANValidation extend BackendTLSPolicy with SubjectAltNames validation",
40+
Features: []features.FeatureName{
41+
features.SupportGateway,
42+
features.SupportHTTPRoute,
43+
features.SupportBackendTLSPolicy,
44+
features.SupportBackendTLSPolicySANValidation,
45+
},
46+
Manifests: []string{"tests/backendtlspolicy-san.yaml"},
47+
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
48+
ns := "gateway-conformance-infra"
49+
routeNN := types.NamespacedName{Name: "route-backendtlspolicy-san-test", Namespace: ns}
50+
gwNN := types.NamespacedName{Name: "gateway-backendtlspolicy", Namespace: ns}
51+
52+
kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns})
53+
gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN)
54+
kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN)
55+
56+
policyCond := metav1.Condition{
57+
Type: string(v1alpha2.PolicyConditionAccepted),
58+
Status: metav1.ConditionTrue,
59+
Reason: string(v1alpha2.PolicyReasonAccepted),
60+
}
61+
62+
serverStr := "abc.example.com"
63+
64+
// Verify that the request sent to Service with valid BackendTLSPolicy containing dns SAN should succeed.
65+
t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing dns SAN should succeed", func(t *testing.T) {
66+
policyNN := types.NamespacedName{Name: "backendtlspolicy-san-dns", Namespace: ns}
67+
kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond)
68+
69+
h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr,
70+
h.ExpectedResponse{
71+
Namespace: ns,
72+
Request: h.Request{
73+
Host: serverStr,
74+
Path: "/backendTLSSanDns",
75+
SNI: serverStr,
76+
},
77+
Response: h.Response{StatusCode: 200},
78+
})
79+
})
80+
81+
// Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched dns SAN should fail.
82+
t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched dns SAN should return an HTTP error", func(t *testing.T) {
83+
policyNN := types.NamespacedName{Name: "backendtlspolicy-san-dns-mismatch", Namespace: ns}
84+
kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond)
85+
86+
h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr,
87+
h.ExpectedResponse{
88+
Namespace: ns,
89+
Request: h.Request{
90+
Host: serverStr,
91+
Path: "/backendTLSSanDnsMismatch",
92+
SNI: serverStr,
93+
},
94+
})
95+
})
96+
97+
// Verify that the request sent to Service with valid BackendTLSPolicy containing uri SAN should succeed.
98+
t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing uri SAN should succeed", func(t *testing.T) {
99+
policyNN := types.NamespacedName{Name: "backendtlspolicy-san-uri", Namespace: ns}
100+
kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond)
101+
102+
h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr,
103+
h.ExpectedResponse{
104+
Namespace: ns,
105+
Request: h.Request{
106+
Host: serverStr,
107+
Path: "/backendTLSSanUri",
108+
SNI: serverStr,
109+
},
110+
Response: h.Response{StatusCode: 200},
111+
})
112+
})
113+
114+
// Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched uri SAN should fail.
115+
t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched uri SAN should return an HTTP error", func(t *testing.T) {
116+
policyNN := types.NamespacedName{Name: "backendtlspolicy-san-uri-mismatch", Namespace: ns}
117+
kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond)
118+
119+
h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr,
120+
h.ExpectedResponse{
121+
Namespace: ns,
122+
Request: h.Request{
123+
Host: serverStr,
124+
Path: "/backendTLSSanUriMismatch",
125+
SNI: serverStr,
126+
},
127+
})
128+
})
129+
130+
// Verify that the request sent to Service with valid BackendTLSPolicy containing multi SANs should succeed.
131+
t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing multi SAN should succeed", func(t *testing.T) {
132+
policyNN := types.NamespacedName{Name: "backendtlspolicy-multiple-sans", Namespace: ns}
133+
kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond)
134+
135+
h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr,
136+
h.ExpectedResponse{
137+
Namespace: ns,
138+
Request: h.Request{
139+
Host: serverStr,
140+
Path: "/backendTLSMultiSans",
141+
SNI: serverStr,
142+
},
143+
Response: h.Response{StatusCode: 200},
144+
})
145+
})
146+
147+
// Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched multi SAN should fail.
148+
t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched multi SAN should return an HTTP error", func(t *testing.T) {
149+
policyNN := types.NamespacedName{Name: "backendtlspolicy-multiple-mismatch-sans", Namespace: ns}
150+
kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond)
151+
152+
h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr,
153+
h.ExpectedResponse{
154+
Namespace: ns,
155+
Request: h.Request{
156+
Host: serverStr,
157+
Path: "/backendTLSMultiMismatchSans",
158+
SNI: serverStr,
159+
},
160+
})
161+
})
162+
},
163+
}

0 commit comments

Comments
 (0)