Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ReToCode committed Nov 17, 2023
1 parent 2adc573 commit a216e45
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 56 deletions.
83 changes: 46 additions & 37 deletions pkg/generator/ingress_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,48 +80,24 @@ func NewIngressTranslator(
func (translator *IngressTranslator) translateIngress(ctx context.Context, ingress *v1alpha1.Ingress, extAuthzEnabled bool) (*translatedIngress, error) {
logger := logging.FromContext(ctx)

localSNIMatches := make([]*envoy.SNIMatch, 0, len(ingress.Spec.TLS))
externalSNIMatches := make([]*envoy.SNIMatch, 0, len(ingress.Spec.TLS))
for _, ingressTLS := range ingress.Spec.TLS {
if err := trackSecret(translator.tracker, ingressTLS.SecretNamespace, ingressTLS.SecretName, ingress); err != nil {
return nil, err
}
localIngressTLS := ingress.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityClusterLocal)
externalIngressTLS := ingress.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityExternalIP)

secret, err := translator.secretGetter(ingressTLS.SecretNamespace, ingressTLS.SecretName)
externalSNIMatches := make([]*envoy.SNIMatch, 0, len(externalIngressTLS))
for _, t := range externalIngressTLS {
sniMatch, err := translator.translateIngressTLS(t, ingress)
if err != nil {
return nil, fmt.Errorf("failed to fetch secret: %w", err)
return nil, fmt.Errorf("failed to translate ingressTLS: %w", err)
}

// Validate certificate here as these are defined by users.
// We should not send Gateway without validation.
_, err = tls.X509KeyPair(
secret.Data[certificates.CertName],
secret.Data[certificates.PrivateKeyName],
)
externalSNIMatches = append(externalSNIMatches, sniMatch)
}
localSNIMatches := make([]*envoy.SNIMatch, 0, len(localIngressTLS))
for _, t := range localIngressTLS {
sniMatch, err := translator.translateIngressTLS(t, ingress)
if err != nil {
return nil, fmt.Errorf("invalid secret is specified: %w", err)
}

secretRef := types.NamespacedName{
Namespace: ingressTLS.SecretNamespace,
Name: ingressTLS.SecretName,
}
sniMatch := &envoy.SNIMatch{
Hosts: ingressTLS.Hosts,
CertSource: secretRef,
CertificateChain: secret.Data[certificates.CertName],
PrivateKey: secret.Data[certificates.PrivateKeyName],
}

switch ingressTLS.Visibility {
// Also handle empty string as external for backwards compatibility
case "", v1alpha1.IngressVisibilityExternalIP:
externalSNIMatches = append(externalSNIMatches, sniMatch)
case v1alpha1.IngressVisibilityClusterLocal:
localSNIMatches = append(localSNIMatches, sniMatch)
default:
return nil, fmt.Errorf("invalid value: %s for ingress.spec.rule.tls.visibility", ingressTLS.Visibility)
return nil, fmt.Errorf("failed to translate ingressTLS: %w", err)
}
localSNIMatches = append(localSNIMatches, sniMatch)
}

localHosts := make([]*route.VirtualHost, 0, len(ingress.Spec.Rules))
Expand Down Expand Up @@ -315,6 +291,39 @@ func (translator *IngressTranslator) translateIngress(ctx context.Context, ingre
}, nil
}

func (translator *IngressTranslator) translateIngressTLS(ingressTLS v1alpha1.IngressTLS, ingress *v1alpha1.Ingress) (*envoy.SNIMatch, error) {
if err := trackSecret(translator.tracker, ingressTLS.SecretNamespace, ingressTLS.SecretName, ingress); err != nil {
return nil, err
}

secret, err := translator.secretGetter(ingressTLS.SecretNamespace, ingressTLS.SecretName)
if err != nil {
return nil, fmt.Errorf("failed to fetch secret: %w", err)
}

// Validate certificate here as these are defined by users.
// We should not send Gateway without validation.
_, err = tls.X509KeyPair(
secret.Data[certificates.CertName],
secret.Data[certificates.PrivateKeyName],
)
if err != nil {
return nil, fmt.Errorf("invalid secret is specified: %w", err)
}

secretRef := types.NamespacedName{
Namespace: ingressTLS.SecretNamespace,
Name: ingressTLS.SecretName,
}
sniMatch := &envoy.SNIMatch{
Hosts: ingressTLS.Hosts,
CertSource: secretRef,
CertificateChain: secret.Data[certificates.CertName],
PrivateKey: secret.Data[certificates.PrivateKeyName],
}
return sniMatch, nil
}

func (translator *IngressTranslator) createUpstreamTransportSocket(http2 bool, namespace string) (*envoycorev3.TransportSocket, error) {
caSecret, err := translator.secretGetter(pkgconfig.ServingNamespace(), netconfig.ServingRoutingCertName)
if err != nil {
Expand Down
15 changes: 4 additions & 11 deletions pkg/reconciler/ingress/lister.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,10 @@ func (l *gatewayPodTargetLister) ListProbeTargets(ctx context.Context, ing *v1al
func (l *gatewayPodTargetLister) getIngressUrls(ing *v1alpha1.Ingress, gatewayIps []string) ([]status.ProbeTarget, error) {
ips := sets.NewString(gatewayIps...)

localTLS := false
externalTLS := false
for _, t := range ing.Spec.TLS {
// Also include empty for reverse compatibility
if t.Visibility == "" || t.Visibility == v1alpha1.IngressVisibilityExternalIP {
externalTLS = true
}
if t.Visibility == v1alpha1.IngressVisibilityClusterLocal {
localTLS = true
}
}
localIngressTLS := ing.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityClusterLocal)
externalIngressTLS := ing.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityExternalIP)
localTLS := len(localIngressTLS) > 0
externalTLS := len(externalIngressTLS) > 0

targets := make([]status.ProbeTarget, 0, len(ing.Spec.Rules))
for _, rule := range ing.Spec.Rules {
Expand Down
3 changes: 0 additions & 3 deletions vendor/knative.dev/networking/config/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,6 @@ spec:
secretNamespace:
description: SecretNamespace is the namespace of the secret used to terminate SSL traffic. If not set the namespace should be assumed to be the same as the Ingress. If set the secret should have the same namespace as the Ingress otherwise the behaviour is undefined and not supported.
type: string
visibility:
description: Visibility signifies whether the tls hosts should be considered `ClusterLocal`. If it's not specified then it defaults to `ExternalIP`.
type: string
status:
description: 'Status is the current state of the Ingress. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'
type: object
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
Copyright 2023 The Knative Authors
Licensed 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 v1alpha1

import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)

// GetIngressTLSForVisibility returns a list of `Spec.TLS` where the `Hosts` field matches
// to `Spec.Rules.Hosts` and where the Rules have the defined ingress visibility.
// This method can be used in net-* implementations to select the correct `IngressTLS` entries
// for cluster-local and cluster-external gateways/listeners.
func (i *Ingress) GetIngressTLSForVisibility(visibility IngressVisibility) []IngressTLS {
ingressTLS := make([]IngressTLS, 0, len(i.Spec.TLS))

if i.Spec.TLS == nil || len(i.Spec.TLS) == 0 {
return ingressTLS
}

for _, r := range i.Spec.Rules {
if r.Visibility == visibility {
for _, t := range i.Spec.TLS {
// Check if hosts slices are equal ignoring the order
if cmp.Diff(r.Hosts, t.Hosts, cmpopts.SortSlices(func(a, b string) bool { return a < b })) == "" {
ingressTLS = append(ingressTLS, t)
}
}
}
}

return ingressTLS
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,6 @@ type IngressTLS struct {
//
// +optional
SecretNamespace string `json:"secretNamespace,omitempty"`

// Visibility signifies whether the tls hosts should be considered `ClusterLocal`.
// If it's not specified then it defaults to `ExternalIP`.
Visibility IngressVisibility `json:"visibility,omitempty"`
}

// IngressRule represents the rules mapping the paths under a specified host to
Expand Down
2 changes: 1 addition & 1 deletion vendor/knative.dev/networking/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ const (
type CertificateType string

const (
// CertificateSystemInternal defines a certificate used for `system-internal-tls`
// CertificateSystemInternal defines a certificate used for `system-internal-tls`.
CertificateSystemInternal CertificateType = "system-internal"

// CertificateClusterLocalDomain defines a certificate used for `cluster-local-domain-tls`.
Expand Down

0 comments on commit a216e45

Please sign in to comment.