Skip to content

Commit b9ed6df

Browse files
TLS Passthrough support (#402)
* TLS Passthrough support This commit adds a tlsroute controller which is further used to configure tls passthrough in envoy. Signed-off-by: Shubham Chauhan <[email protected]> * Adding tlsroute experimental crd in testdata update gatewayclass/gateway/httproute experimental CRDs to use standard schemas Signed-off-by: Shubham Chauhan <[email protected]> * keep other testdata changes out of this PR Signed-off-by: Shubham Chauhan <[email protected]> * added testcases for tlsroutes, include serviceport in irInfraPortName Signed-off-by: Shubham Chauhan <[email protected]> * lintfix Signed-off-by: Shubham Chauhan <[email protected]> * tlroute kubernetes provider test Signed-off-by: Shubham Chauhan <[email protected]> * added xds tls config validate test for passthrough Signed-off-by: Shubham Chauhan <[email protected]> * types test tlsroute Signed-off-by: Shubham Chauhan <[email protected]> * test fixes Signed-off-by: Shubham Chauhan <[email protected]> * xds config tests for tls passthrough Signed-off-by: Shubham Chauhan <[email protected]> * increase test coverage Signed-off-by: Shubham Chauhan <[email protected]> * testfix Signed-off-by: Shubham Chauhan <[email protected]> * separate xds tls listener Signed-off-by: Shubham Chauhan <[email protected]> testfix Signed-off-by: Shubham Chauhan <[email protected]> * additional xds validate tests Signed-off-by: Shubham Chauhan <[email protected]> * tlsroute refgrant test Signed-off-by: Shubham Chauhan <[email protected]> * add rbac permissions for tlsroute Signed-off-by: Shubham Chauhan <[email protected]> * updates post rebase Signed-off-by: Shubham Chauhan <[email protected]> * add status updater, gateway watcher for tlsroute Signed-off-by: Shubham Chauhan <[email protected]> * add status update framework for tlsroute Signed-off-by: Shubham Chauhan <[email protected]> * lintfix, testfix, fix post rebase Signed-off-by: Shubham Chauhan <[email protected]> * yet another lintfix Signed-off-by: Shubham Chauhan <[email protected]> * refactor tlslistener/route -> tcplistener/route, xds updates Signed-off-by: Shubham Chauhan <[email protected]> * missed a file Signed-off-by: Shubham Chauhan <[email protected]> * lintfix Signed-off-by: Shubham Chauhan <[email protected]> * rebase, review comments Signed-off-by: Shubham Chauhan <[email protected]> * minor testfix Signed-off-by: Shubham Chauhan <[email protected]> * more Signed-off-by: Shubham Chauhan <[email protected]> * review comments, status deepcopy, check routes in ns Signed-off-by: Shubham Chauhan <[email protected]> * revert bad import, testfix, new test Signed-off-by: Shubham Chauhan <[email protected]> * rev sort Signed-off-by: Shubham Chauhan <[email protected]> Signed-off-by: Shubham Chauhan <[email protected]>
1 parent 872c7f5 commit b9ed6df

File tree

56 files changed

+3517
-258
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3517
-258
lines changed

internal/cmd/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ func setupRunners(cfg *config.Server) error {
153153
pResources.Namespaces.Close()
154154
pResources.GatewayStatuses.Close()
155155
pResources.HTTPRouteStatuses.Close()
156+
pResources.TLSRoutes.Close()
157+
pResources.TLSRouteStatuses.Close()
156158
xdsIR.Close()
157159
infraIR.Close()
158160
xds.Close()

internal/envoygateway/scheme.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ package envoygateway
33
import (
44
"k8s.io/apimachinery/pkg/runtime"
55
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
6-
gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1"
6+
gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1alpha2"
7+
gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1beta1"
78

89
"github.com/envoyproxy/gateway/api/config/v1alpha1"
910
)
@@ -28,6 +29,9 @@ func init() {
2829
if err := gwapiv1b1.AddToScheme(scheme); err != nil {
2930
panic(err)
3031
}
32+
if err := gwapiv1a2.AddToScheme(scheme); err != nil {
33+
panic(err)
34+
}
3135
}
3236

3337
// GetScheme returns a scheme with types supported by the Kubernetes provider.

internal/gatewayapi/contexts.go

Lines changed: 192 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
v1 "k8s.io/api/core/v1"
88
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
99
"k8s.io/apimachinery/pkg/labels"
10+
"sigs.k8s.io/controller-runtime/pkg/client"
11+
"sigs.k8s.io/gateway-api/apis/v1alpha2"
1012
"sigs.k8s.io/gateway-api/apis/v1beta1"
1113

1214
egv1alpha1 "github.com/envoyproxy/gateway/api/config/v1alpha1"
@@ -20,6 +22,10 @@ type GatewayContext struct {
2022
listeners []*ListenerContext
2123
}
2224

25+
// GetListenerContext returns the ListenerContext with listenerName.
26+
// If the listener exists in the Gateway Spec but NOT yet in the GatewayContext,
27+
// this creates a new ListenerContext for the listener and attaches it to the
28+
// GatewayContext.
2329
func (g *GatewayContext) GetListenerContext(listenerName v1beta1.SectionName) *ListenerContext {
2430
if g.listeners == nil {
2531
g.listeners = make([]*ListenerContext, 0)
@@ -169,6 +175,30 @@ func (l *ListenerContext) SetTLSSecret(tlsSecret *v1.Secret) {
169175
l.tlsSecret = tlsSecret
170176
}
171177

178+
// RouteContext represents a generic Route object (HTTPRoute, TLSRoute, etc.)
179+
// that can reference Gateway objects.
180+
type RouteContext interface {
181+
client.Object
182+
183+
// GetRouteType returns the Kind of the Route object, HTTPRoute,
184+
// TLSRoute, TCPRoute, UDPRoute etc.
185+
GetRouteType() string
186+
187+
// TODO: [v1alpha2-v1beta1] This should not be required once all Route
188+
// objects being implemented are of type v1beta1.
189+
// GetHostnames returns the hosts targeted by the Route object.
190+
GetHostnames() []string
191+
192+
// TODO: [v1alpha2-v1beta1] This should not be required once all Route
193+
// objects being implemented are of type v1beta1.
194+
// GetParentReferences returns the ParentReference of the Route object.
195+
GetParentReferences() []v1beta1.ParentReference
196+
197+
// GetRouteParentContext returns RouteParentContext by using the Route
198+
// objects' ParentReference.
199+
GetRouteParentContext(forParentRef v1beta1.ParentReference) *RouteParentContext
200+
}
201+
172202
// HTTPRouteContext wraps an HTTPRoute and provides helper methods for
173203
// accessing the route's parents.
174204
type HTTPRouteContext struct {
@@ -177,6 +207,22 @@ type HTTPRouteContext struct {
177207
parentRefs map[v1beta1.ParentReference]*RouteParentContext
178208
}
179209

210+
func (h *HTTPRouteContext) GetRouteType() string {
211+
return KindHTTPRoute
212+
}
213+
214+
func (h *HTTPRouteContext) GetHostnames() []string {
215+
hostnames := make([]string, len(h.Spec.Hostnames))
216+
for idx, s := range h.Spec.Hostnames {
217+
hostnames[idx] = string(s)
218+
}
219+
return hostnames
220+
}
221+
222+
func (h *HTTPRouteContext) GetParentReferences() []v1beta1.ParentReference {
223+
return h.Spec.ParentRefs
224+
}
225+
180226
func (h *HTTPRouteContext) GetRouteParentContext(forParentRef v1beta1.ParentReference) *RouteParentContext {
181227
if h.parentRefs == nil {
182228
h.parentRefs = make(map[v1beta1.ParentReference]*RouteParentContext)
@@ -217,20 +263,109 @@ func (h *HTTPRouteContext) GetRouteParentContext(forParentRef v1beta1.ParentRefe
217263
ctx := &RouteParentContext{
218264
ParentReference: parentRef,
219265

220-
route: h.HTTPRoute,
266+
httpRoute: h.HTTPRoute,
221267
routeParentStatusIdx: routeParentStatusIdx,
222268
}
223269
h.parentRefs[forParentRef] = ctx
224270
return ctx
225271
}
226272

273+
// TLSRouteContext wraps a TLSRoute and provides helper methods for
274+
// accessing the route's parents.
275+
type TLSRouteContext struct {
276+
*v1alpha2.TLSRoute
277+
278+
parentRefs map[v1beta1.ParentReference]*RouteParentContext
279+
}
280+
281+
func (t *TLSRouteContext) GetRouteType() string {
282+
return KindTLSRoute
283+
}
284+
285+
func (t *TLSRouteContext) GetHostnames() []string {
286+
hostnames := make([]string, len(t.Spec.Hostnames))
287+
for idx, s := range t.Spec.Hostnames {
288+
hostnames[idx] = string(s)
289+
}
290+
return hostnames
291+
}
292+
293+
func (t *TLSRouteContext) GetParentReferences() []v1beta1.ParentReference {
294+
parentReferences := make([]v1beta1.ParentReference, len(t.Spec.ParentRefs))
295+
for idx, p := range t.Spec.ParentRefs {
296+
parentReferences[idx] = UpgradeParentReference(p)
297+
}
298+
return parentReferences
299+
}
300+
301+
func (t *TLSRouteContext) GetRouteParentContext(forParentRef v1beta1.ParentReference) *RouteParentContext {
302+
if t.parentRefs == nil {
303+
t.parentRefs = make(map[v1beta1.ParentReference]*RouteParentContext)
304+
}
305+
306+
if ctx := t.parentRefs[forParentRef]; ctx != nil {
307+
return ctx
308+
}
309+
310+
var parentRef *v1beta1.ParentReference
311+
for i, p := range t.Spec.ParentRefs {
312+
p := UpgradeParentReference(p)
313+
if reflect.DeepEqual(p, forParentRef) {
314+
upgraded := UpgradeParentReference(t.Spec.ParentRefs[i])
315+
parentRef = &upgraded
316+
break
317+
}
318+
}
319+
if parentRef == nil {
320+
panic("parentRef not found")
321+
}
322+
323+
routeParentStatusIdx := -1
324+
for i := range t.Status.Parents {
325+
p := UpgradeParentReference(t.Status.Parents[i].ParentRef)
326+
defaultNamespace := v1beta1.Namespace(metav1.NamespaceDefault)
327+
if forParentRef.Namespace == nil {
328+
forParentRef.Namespace = &defaultNamespace
329+
}
330+
if p.Namespace == nil {
331+
p.Namespace = &defaultNamespace
332+
}
333+
if reflect.DeepEqual(p, forParentRef) {
334+
routeParentStatusIdx = i
335+
break
336+
}
337+
}
338+
if routeParentStatusIdx == -1 {
339+
rParentStatus := v1alpha2.RouteParentStatus{
340+
// TODO: get this value from the config
341+
ControllerName: v1alpha2.GatewayController(egv1alpha1.GatewayControllerName),
342+
ParentRef: DowngradeParentReference(forParentRef),
343+
}
344+
t.Status.Parents = append(t.Status.Parents, rParentStatus)
345+
routeParentStatusIdx = len(t.Status.Parents) - 1
346+
}
347+
348+
ctx := &RouteParentContext{
349+
ParentReference: parentRef,
350+
351+
tlsRoute: t.TLSRoute,
352+
routeParentStatusIdx: routeParentStatusIdx,
353+
}
354+
t.parentRefs[forParentRef] = ctx
355+
return ctx
356+
}
357+
227358
// RouteParentContext wraps a ParentReference and provides helper methods for
228359
// setting conditions and other status information on the associated
229-
// HTTPRoute, etc.
360+
// HTTPRoute, TLSRoute etc.
230361
type RouteParentContext struct {
231362
*v1beta1.ParentReference
232363

233-
route *v1beta1.HTTPRoute
364+
// TODO: [v1alpha2-v1beta1] This can probably be replaced with
365+
// a single field pointing to *v1beta1.RouteStatus.
366+
httpRoute *v1beta1.HTTPRoute
367+
tlsRoute *v1alpha2.TLSRoute
368+
234369
routeParentStatusIdx int
235370
listeners []*ListenerContext
236371
}
@@ -239,43 +374,77 @@ func (r *RouteParentContext) SetListeners(listeners ...*ListenerContext) {
239374
r.listeners = append(r.listeners, listeners...)
240375
}
241376

242-
func (r *RouteParentContext) SetCondition(conditionType v1beta1.RouteConditionType, status metav1.ConditionStatus, reason v1beta1.RouteConditionReason, message string) {
377+
func (r *RouteParentContext) SetCondition(route RouteContext, conditionType v1beta1.RouteConditionType, status metav1.ConditionStatus, reason v1beta1.RouteConditionReason, message string) {
243378
cond := metav1.Condition{
244379
Type: string(conditionType),
245380
Status: status,
246381
Reason: string(reason),
247382
Message: message,
248-
ObservedGeneration: r.route.Generation,
383+
ObservedGeneration: route.GetGeneration(),
249384
LastTransitionTime: metav1.NewTime(time.Now()),
250385
}
251386

252387
idx := -1
253-
for i, existing := range r.route.Status.Parents[r.routeParentStatusIdx].Conditions {
254-
if existing.Type == cond.Type {
255-
// return early if the condition is unchanged
256-
if existing.Status == cond.Status &&
257-
existing.Reason == cond.Reason &&
258-
existing.Message == cond.Message {
259-
return
388+
switch route.GetRouteType() {
389+
case KindHTTPRoute:
390+
for i, existing := range r.httpRoute.Status.Parents[r.routeParentStatusIdx].Conditions {
391+
if existing.Type == cond.Type {
392+
// return early if the condition is unchanged
393+
if existing.Status == cond.Status &&
394+
existing.Reason == cond.Reason &&
395+
existing.Message == cond.Message {
396+
return
397+
}
398+
idx = i
399+
break
260400
}
261-
idx = i
262-
break
263401
}
264-
}
265402

266-
if idx > -1 {
267-
r.route.Status.Parents[r.routeParentStatusIdx].Conditions[idx] = cond
268-
} else {
269-
r.route.Status.Parents[r.routeParentStatusIdx].Conditions = append(r.route.Status.Parents[r.routeParentStatusIdx].Conditions, cond)
403+
if idx > -1 {
404+
r.httpRoute.Status.Parents[r.routeParentStatusIdx].Conditions[idx] = cond
405+
} else {
406+
r.httpRoute.Status.Parents[r.routeParentStatusIdx].Conditions = append(r.httpRoute.Status.Parents[r.routeParentStatusIdx].Conditions, cond)
407+
}
408+
case KindTLSRoute:
409+
for i, existing := range r.tlsRoute.Status.Parents[r.routeParentStatusIdx].Conditions {
410+
if existing.Type == cond.Type {
411+
// return early if the condition is unchanged
412+
if existing.Status == cond.Status &&
413+
existing.Reason == cond.Reason &&
414+
existing.Message == cond.Message {
415+
return
416+
}
417+
idx = i
418+
break
419+
}
420+
}
421+
422+
if idx > -1 {
423+
r.tlsRoute.Status.Parents[r.routeParentStatusIdx].Conditions[idx] = cond
424+
} else {
425+
r.tlsRoute.Status.Parents[r.routeParentStatusIdx].Conditions = append(r.tlsRoute.Status.Parents[r.routeParentStatusIdx].Conditions, cond)
426+
}
270427
}
271428
}
272429

273-
func (r *RouteParentContext) ResetConditions() {
274-
r.route.Status.Parents[r.routeParentStatusIdx].Conditions = make([]metav1.Condition, 0)
430+
func (r *RouteParentContext) ResetConditions(route RouteContext) {
431+
switch route.GetRouteType() {
432+
case KindHTTPRoute:
433+
r.httpRoute.Status.Parents[r.routeParentStatusIdx].Conditions = make([]metav1.Condition, 0)
434+
case KindTLSRoute:
435+
r.tlsRoute.Status.Parents[r.routeParentStatusIdx].Conditions = make([]metav1.Condition, 0)
436+
}
275437
}
276438

277-
func (r *RouteParentContext) IsAccepted() bool {
278-
for _, cond := range r.route.Status.Parents[r.routeParentStatusIdx].Conditions {
439+
func (r *RouteParentContext) IsAccepted(route RouteContext) bool {
440+
var conditions []metav1.Condition
441+
switch route.GetRouteType() {
442+
case KindHTTPRoute:
443+
conditions = r.httpRoute.Status.Parents[r.routeParentStatusIdx].Conditions
444+
case KindTLSRoute:
445+
conditions = r.tlsRoute.Status.Parents[r.routeParentStatusIdx].Conditions
446+
}
447+
for _, cond := range conditions {
279448
if cond.Type == string(v1beta1.RouteConditionAccepted) && cond.Status == metav1.ConditionTrue {
280449
return true
281450
}

internal/gatewayapi/helpers.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ func FromNamespacesPtr(fromNamespaces v1beta1.FromNamespaces) *v1beta1.FromNames
2727
return &fromNamespaces
2828
}
2929

30+
func SectionNamePtr(name string) *v1beta1.SectionName {
31+
sectionName := v1beta1.SectionName(name)
32+
return &sectionName
33+
}
34+
3035
func StringPtr(val string) *string {
3136
return &val
3237
}
@@ -138,9 +143,9 @@ func HasReadyListener(listeners []*ListenerContext) bool {
138143
return false
139144
}
140145

141-
// ComputeHosts returns a list of the intersecting hostnames between the route
146+
// computeHosts returns a list of the intersecting hostnames between the route
142147
// and the listener.
143-
func ComputeHosts(routeHostnames []v1beta1.Hostname, listenerHostname *v1beta1.Hostname) []string {
148+
func computeHosts(routeHostnames []string, listenerHostname *v1beta1.Hostname) []string {
144149
var listenerHostnameVal string
145150
if listenerHostname != nil {
146151
listenerHostnameVal = string(*listenerHostname)
@@ -159,7 +164,7 @@ func ComputeHosts(routeHostnames []v1beta1.Hostname, listenerHostname *v1beta1.H
159164
var hostnames []string
160165

161166
for i := range routeHostnames {
162-
routeHostname := string(routeHostnames[i])
167+
routeHostname := routeHostnames[i]
163168

164169
// TODO ensure routeHostname is a valid hostname
165170

0 commit comments

Comments
 (0)