From e3f1e5a0aebba9a2f2e04081c47e73116594fd42 Mon Sep 17 00:00:00 2001 From: dprotaso Date: Mon, 8 Jul 2024 11:43:43 -0400 Subject: [PATCH 1/2] add support for cluster local tls --- pkg/reconciler/contour/resources/httpproxy.go | 28 +- .../contour/resources/httpproxy_test.go | 255 ++++++++++++++++++ 2 files changed, 275 insertions(+), 8 deletions(-) diff --git a/pkg/reconciler/contour/resources/httpproxy.go b/pkg/reconciler/contour/resources/httpproxy.go index 20fcde5b2..5156809b1 100644 --- a/pkg/reconciler/contour/resources/httpproxy.go +++ b/pkg/reconciler/contour/resources/httpproxy.go @@ -97,19 +97,31 @@ func defaultRetryPolicy() *v1.RetryPolicy { } } +func tlsEntries(ing *v1alpha1.Ingress) map[string]v1alpha1.IngressTLS { + external := ing.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityExternalIP) + internal := ing.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityClusterLocal) + + entries := make(map[string]v1alpha1.IngressTLS, len(external)+len(internal)) + for _, tls := range external { + for _, host := range tls.Hosts { + entries[host] = tls + } + } + for _, tls := range internal { + for _, host := range tls.Hosts { + entries[host] = tls + } + } + return entries +} + func MakeHTTPProxies(ctx context.Context, ing *v1alpha1.Ingress, serviceToProtocol map[string]string) []*v1.HTTPProxy { cfg := config.FromContext(ctx) ing = ing.DeepCopy() ingress.InsertProbe(ing) - externalIngressTLS := ing.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityExternalIP) - hostToTLS := make(map[string]v1alpha1.IngressTLS, len(externalIngressTLS)) - for _, tls := range externalIngressTLS { - for _, host := range tls.Hosts { - hostToTLS[host] = tls - } - } + tlsEntries := tlsEntries(ing) var allowInsecure bool switch ing.Spec.HTTPOption { @@ -329,7 +341,7 @@ func MakeHTTPProxies(ctx context.Context, ing *v1alpha1.Ingress, serviceToProtoc // nolint:gosec // No strong cryptography needed. hostProxy.Labels[DomainHashKey] = fmt.Sprintf("%x", sha1.Sum([]byte(host))) - if tls, ok := hostToTLS[host]; ok { + if tls, ok := tlsEntries[host]; ok { // TODO(mattmoor): How do we deal with custom secret schemas? hostProxy.Spec.VirtualHost.TLS = &v1.TLS{ SecretName: fmt.Sprintf("%s/%s", tls.SecretNamespace, tls.SecretName), diff --git a/pkg/reconciler/contour/resources/httpproxy_test.go b/pkg/reconciler/contour/resources/httpproxy_test.go index f61e17209..3df169ba8 100644 --- a/pkg/reconciler/contour/resources/httpproxy_test.go +++ b/pkg/reconciler/contour/resources/httpproxy_test.go @@ -1929,6 +1929,261 @@ func TestMakeProxies(t *testing.T) { }}, }, }}, + }, { + name: "cluster local tls is enabled", + ing: &v1alpha1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "bar", + }, + Spec: v1alpha1.IngressSpec{ + HTTPOption: v1alpha1.HTTPOptionEnabled, + TLS: []v1alpha1.IngressTLS{{ + Hosts: []string{ + "foo.bar", + "foo.bar.svc", + "foo.bar.svc.cluster.local", + }, + SecretName: "some-secret", + SecretNamespace: "some-secret-namespace", + }}, + Rules: []v1alpha1.IngressRule{{ + Hosts: []string{network.GetServiceHostname("foo", "bar")}, + Visibility: v1alpha1.IngressVisibilityClusterLocal, + HTTP: &v1alpha1.HTTPIngressRuleValue{ + Paths: []v1alpha1.HTTPIngressPath{{ + Splits: []v1alpha1.IngressBackendSplit{{ + IngressBackend: v1alpha1.IngressBackend{ + ServiceName: "goo", + ServicePort: intstr.FromInt(123), + }, + Percent: 100, + }}, + }}, + }, + }}, + }, + }, + want: []*v1.HTTPProxy{{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "bar-" + privateClass + "-foo.bar", + Labels: map[string]string{ + DomainHashKey: "336d1b3d72e061b98b59d6c793f6a8da217a727a", + GenerationKey: "0", + ParentKey: "bar", + ClassKey: privateClass, + }, + Annotations: map[string]string{ + ClassKey: privateClass, + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "networking.internal.knative.dev/v1alpha1", + Kind: "Ingress", + Name: "bar", + Controller: ptr.Bool(true), + BlockOwnerDeletion: ptr.Bool(true), + }}, + }, + Spec: v1.HTTPProxySpec{ + VirtualHost: &v1.VirtualHost{ + Fqdn: "foo.bar", + TLS: &v1.TLS{ + SecretName: "some-secret-namespace/some-secret", + }, + }, + Routes: []v1.Route{{ + EnableWebsockets: true, + PermitInsecure: true, + TimeoutPolicy: &v1.TimeoutPolicy{ + Response: "infinity", + Idle: "infinity", + }, + RetryPolicy: defaultRetryPolicy(), + Conditions: []v1.MatchCondition{{ + Header: &v1.HeaderMatchCondition{ + Name: "K-Network-Hash", + Exact: "override", + }, + }}, + RequestHeadersPolicy: &v1.HeadersPolicy{ + Set: []v1.HeaderValue{{ + Name: "K-Network-Hash", + Value: "cff88c5187b8b06f96fdd65fc26493720cae752621d375f7d24ffcac71f6b907", + }}, + }, + Services: []v1.Service{{ + Name: "goo", + Protocol: &protocol, + Port: 123, + Weight: 100, + }}, + }, { + EnableWebsockets: true, + PermitInsecure: true, + TimeoutPolicy: &v1.TimeoutPolicy{ + Response: "infinity", + Idle: "infinity", + }, + RetryPolicy: defaultRetryPolicy(), + RequestHeadersPolicy: &v1.HeadersPolicy{ + Set: []v1.HeaderValue{}, + }, + Services: []v1.Service{{ + Name: "goo", + Protocol: &protocol, + Port: 123, + Weight: 100, + }}, + }}, + }, + }, { + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "bar-" + privateClass + "-foo.bar.svc", + Labels: map[string]string{ + DomainHashKey: "c537bbef14c1570803e5c51c6ca824524c758496", + GenerationKey: "0", + ParentKey: "bar", + ClassKey: privateClass, + }, + Annotations: map[string]string{ + ClassKey: privateClass, + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "networking.internal.knative.dev/v1alpha1", + Kind: "Ingress", + Name: "bar", + Controller: ptr.Bool(true), + BlockOwnerDeletion: ptr.Bool(true), + }}, + }, + Spec: v1.HTTPProxySpec{ + VirtualHost: &v1.VirtualHost{ + Fqdn: "foo.bar.svc", + TLS: &v1.TLS{ + SecretName: "some-secret-namespace/some-secret", + }, + }, + Routes: []v1.Route{{ + EnableWebsockets: true, + PermitInsecure: true, + TimeoutPolicy: &v1.TimeoutPolicy{ + Response: "infinity", + Idle: "infinity", + }, + RetryPolicy: defaultRetryPolicy(), + Conditions: []v1.MatchCondition{{ + Header: &v1.HeaderMatchCondition{ + Name: "K-Network-Hash", + Exact: "override", + }, + }}, + RequestHeadersPolicy: &v1.HeadersPolicy{ + Set: []v1.HeaderValue{{ + Name: "K-Network-Hash", + Value: "cff88c5187b8b06f96fdd65fc26493720cae752621d375f7d24ffcac71f6b907", + }}, + }, + Services: []v1.Service{{ + Name: "goo", + Protocol: &protocol, + Port: 123, + Weight: 100, + }}, + }, { + EnableWebsockets: true, + PermitInsecure: true, + TimeoutPolicy: &v1.TimeoutPolicy{ + Response: "infinity", + Idle: "infinity", + }, + RetryPolicy: defaultRetryPolicy(), + RequestHeadersPolicy: &v1.HeadersPolicy{ + Set: []v1.HeaderValue{}, + }, + Services: []v1.Service{{ + Name: "goo", + Protocol: &protocol, + Port: 123, + Weight: 100, + }}, + }}, + }, + }, { + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "bar-" + privateClass + "-foo.bar.svc.cluster.local", + Labels: map[string]string{ + DomainHashKey: "6f498a962729705e1c12fdef2c3371c00f5094e9", + GenerationKey: "0", + ParentKey: "bar", + ClassKey: privateClass, + }, + Annotations: map[string]string{ + ClassKey: privateClass, + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "networking.internal.knative.dev/v1alpha1", + Kind: "Ingress", + Name: "bar", + Controller: ptr.Bool(true), + BlockOwnerDeletion: ptr.Bool(true), + }}, + }, + Spec: v1.HTTPProxySpec{ + VirtualHost: &v1.VirtualHost{ + Fqdn: "foo.bar.svc.cluster.local", + TLS: &v1.TLS{ + SecretName: "some-secret-namespace/some-secret", + }, + }, + Routes: []v1.Route{{ + EnableWebsockets: true, + PermitInsecure: true, + TimeoutPolicy: &v1.TimeoutPolicy{ + Response: "infinity", + Idle: "infinity", + }, + RetryPolicy: defaultRetryPolicy(), + Conditions: []v1.MatchCondition{{ + Header: &v1.HeaderMatchCondition{ + Name: "K-Network-Hash", + Exact: "override", + }, + }}, + RequestHeadersPolicy: &v1.HeadersPolicy{ + Set: []v1.HeaderValue{{ + Name: "K-Network-Hash", + Value: "cff88c5187b8b06f96fdd65fc26493720cae752621d375f7d24ffcac71f6b907", + }}, + }, + Services: []v1.Service{{ + Name: "goo", + Protocol: &protocol, + Port: 123, + Weight: 100, + }}, + }, { + EnableWebsockets: true, + PermitInsecure: true, + TimeoutPolicy: &v1.TimeoutPolicy{ + Response: "infinity", + Idle: "infinity", + }, + RetryPolicy: defaultRetryPolicy(), + RequestHeadersPolicy: &v1.HeadersPolicy{ + Set: []v1.HeaderValue{}, + }, + Services: []v1.Service{{ + Name: "goo", + Protocol: &protocol, + Port: 123, + Weight: 100, + }}, + }}, + }, + }}, }} for _, test := range tests { From defb126b5b9474ba42ba9faef200212d173547dd Mon Sep 17 00:00:00 2001 From: dprotaso Date: Tue, 9 Jul 2024 11:00:07 -0400 Subject: [PATCH 2/2] refactor addHostEntries --- pkg/reconciler/contour/resources/httpproxy.go | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/reconciler/contour/resources/httpproxy.go b/pkg/reconciler/contour/resources/httpproxy.go index 5156809b1..8a45810ce 100644 --- a/pkg/reconciler/contour/resources/httpproxy.go +++ b/pkg/reconciler/contour/resources/httpproxy.go @@ -97,21 +97,21 @@ func defaultRetryPolicy() *v1.RetryPolicy { } } +func addHostEntries(entries map[string]v1alpha1.IngressTLS, list []v1alpha1.IngressTLS) { + for _, tls := range list { + for _, host := range tls.Hosts { + entries[host] = tls + } + } +} + func tlsEntries(ing *v1alpha1.Ingress) map[string]v1alpha1.IngressTLS { external := ing.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityExternalIP) internal := ing.GetIngressTLSForVisibility(v1alpha1.IngressVisibilityClusterLocal) entries := make(map[string]v1alpha1.IngressTLS, len(external)+len(internal)) - for _, tls := range external { - for _, host := range tls.Hosts { - entries[host] = tls - } - } - for _, tls := range internal { - for _, host := range tls.Hosts { - entries[host] = tls - } - } + addHostEntries(entries, external) + addHostEntries(entries, internal) return entries }