Repository: knative/eventing (Go)

Issue:
Eventing TLS: support exposing https address in Broker controller
**Problem**

This issue is similar to https://github.com/knative/eventing/issues/6864 but for the Broker reconciler

As the [Eventing TLS feature track](https://docs.google.com/document/d/1H-x_oji8LqkCyd7tlsSyclmUe7FAmEJPgRxOU_0pkn8/edit) describes we should support TLS for Broker.

In particular, imc-controller should:
- when the feature flag (see #6836) is set to disabled
  - no behavior change 
- when the feature flag (see #6836) is set to permissive
  - expose both http and https endpoints in the new `status.addresses` (see https://github.com/knative/pkg/issues/2711) field
  - the existing `status.address` will continue to have the existing `http` endpoint
- when the feature flag (see #6836) is set to strict
  - expose only the `https` endpoints in both the new `status.addresses` and the existing `status.address`

The CA certs for the https address need to be read from a secret called `mt-broker-ingress-server-tls` and the key `ca.crt`

## Additional Info

- https://docs.google.com/document/d/1H-x_oji8LqkCyd7tlsSyclmUe7FAmEJPgRxOU_0pkn8/edit
- This issue is focusing only on the broker controller, for the data plane separate issues are used to track such changes (https://github.com/knative/eventing/issues/6876 and https://github.com/knative/eventing/issues/6877)

/good-first-issue



Discussion: @pierDipi: 
	This request has been marked as suitable for new contributors.

Please ensure the request meets the requirements listed [here](https://git.k8s.io/community/contributors/guide/help-wanted.md#good-first-issue).

If this request no longer meets these requirements, the label can be removed
by commenting with the `/remove-good-first-issue` command.


<details>

In response to [this](https://github.com/knative/eventing/issues/6918):

>**Problem**
>
>This issue is similar to https://github.com/knative/eventing/issues/6864 but for the Broker reconciler
>
>As the [Eventing TLS feature track](https://docs.google.com/document/d/1H-x_oji8LqkCyd7tlsSyclmUe7FAmEJPgRxOU_0pkn8/edit) describes we should support TLS for Broker.
>
>In particular, imc-controller should:
>- when the feature flag (see #6836) is set to disabled
>  - no behavior change 
>- when the feature flag (see #6836) is set to permissive
>  - expose both http and https endpoints in the new `status.addresses` (see https://github.com/knative/pkg/issues/2711) field
>  - the existing `status.address` will continue to have the existing `http` endpoint
>- when the feature flag (see #6836) is set to strict
>  - expose only the `https` endpoints in both the new `status.addresses` and the existing `status.address`
>
>The CA certs for the https address need to be read from a secret called `mt-broker-ingress-server-tls` and the key `ca.crt`
>
>## Additional Info
>
>- https://docs.google.com/document/d/1H-x_oji8LqkCyd7tlsSyclmUe7FAmEJPgRxOU_0pkn8/edit
>- This issue is focusing only on the broker controller, for the data plane separate issues are used to track such changes (https://github.com/knative/eventing/issues/6876 and https://github.com/knative/eventing/issues/6877)
>
>/good-first-issue
>


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>



Fix (patch):
diff --git a/pkg/apis/eventing/v1/broker_lifecycle.go b/pkg/apis/eventing/v1/broker_lifecycle.go
index 58ef725f759..e85f12ed80c 100644
--- a/pkg/apis/eventing/v1/broker_lifecycle.go
+++ b/pkg/apis/eventing/v1/broker_lifecycle.go
@@ -81,6 +81,7 @@ func (bs *BrokerStatus) SetAddress(url *apis.URL) {
 
 	if url != nil {
 		bs.GetConditionSet().Manage(bs).MarkTrue(BrokerConditionAddressable)
+		bs.AddressStatus.Address.Name = &url.Scheme
 	} else {
 		bs.GetConditionSet().Manage(bs).MarkFalse(BrokerConditionAddressable, "nil URL", "URL is nil")
 	}
diff --git a/pkg/eventingtls/eventingtls.go b/pkg/eventingtls/eventingtls.go
index 4e394952ab7..dcaeb50d945 100644
--- a/pkg/eventingtls/eventingtls.go
+++ b/pkg/eventingtls/eventingtls.go
@@ -43,6 +43,8 @@ const (
 	TLSCrt = "tls.crt"
 	// DefaultMinTLSVersion is the default minimum TLS version for servers and clients.
 	DefaultMinTLSVersion = tls.VersionTLS12
+	// SecretCACrt is the name of the CA Cert in the secret
+	SecretCACert = "ca.crt"
 )
 
 type ClientConfig struct {
diff --git a/pkg/reconciler/broker/broker.go b/pkg/reconciler/broker/broker.go
index 5baf4db26c6..951fbe4f003 100644
--- a/pkg/reconciler/broker/broker.go
+++ b/pkg/reconciler/broker/broker.go
@@ -31,6 +31,7 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/client-go/dynamic"
 	corev1listers "k8s.io/client-go/listers/core/v1"
+	"k8s.io/utils/pointer"
 	"knative.dev/pkg/kmeta"
 
 	"knative.dev/pkg/apis"
@@ -44,15 +45,22 @@ import (
 	duckv1 "knative.dev/eventing/pkg/apis/duck/v1"
 	"knative.dev/eventing/pkg/apis/eventing"
 	eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1"
+	"knative.dev/eventing/pkg/apis/feature"
 	messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1"
 	clientset "knative.dev/eventing/pkg/client/clientset/versioned"
 	brokerreconciler "knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1/broker"
 	messaginglisters "knative.dev/eventing/pkg/client/listers/messaging/v1"
 	ducklib "knative.dev/eventing/pkg/duck"
+	"knative.dev/eventing/pkg/eventingtls"
 	"knative.dev/eventing/pkg/reconciler/broker/resources"
 	"knative.dev/eventing/pkg/reconciler/names"
 )
 
+const (
+	brokerIngressTLSSecretName = "mt-broker-ingress-server-tls" //nolint:gosec // This is not a hardcoded credential
+	caCertsSecretKey           = eventingtls.SecretCACert
+)
+
 type Reconciler struct {
 	eventingClientSet clientset.Interface
 	dynamicClientSet  dynamic.Interface
@@ -61,6 +69,7 @@ type Reconciler struct {
 	endpointsLister    corev1listers.EndpointsLister
 	subscriptionLister messaginglisters.SubscriptionLister
 	configmapLister    corev1listers.ConfigMapLister
+	secretLister       corev1listers.SecretLister
 
 	channelableTracker ducklib.ListableTracker
 
@@ -183,11 +192,41 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, b *eventingv1.Broker) pk
 
 	// Route everything to shared ingress, just tack on the namespace/name as path
 	// so we can route there appropriately.
-	b.Status.SetAddress(&apis.URL{
-		Scheme: "http",
-		Host:   network.GetServiceHostname(names.BrokerIngressName, system.Namespace()),
-		Path:   fmt.Sprintf("/%s/%s", b.Namespace, b.Name),
-	})
+	transportEncryptionFlags := feature.FromContext(ctx)
+	if transportEncryptionFlags.IsPermissiveTransportEncryption() {
+		caCerts, err := r.getCaCerts()
+		if err != nil {
+			return err
+		}
+
+		httpAddress := r.httpAddress(b)
+		httpsAddress := r.httpsAddress(caCerts, b)
+		// Permissive mode:
+		// - status.address http address with path-based routing
+		// - status.addresses:
+		//   - https address with path-based routing
+		//   - http address with path-based routing
+		b.Status.Addresses = []pkgduckv1.Addressable{httpsAddress, httpAddress}
+		b.Status.Address = &httpAddress
+	} else if transportEncryptionFlags.IsStrictTransportEncryption() {
+		// Strict mode: (only https addresses)
+		// - status.address https address with path-based routing
+		// - status.addresses:
+		//   - https address with path-based routing
+		caCerts, err := r.getCaCerts()
+		if err != nil {
+			return err
+		}
+
+		httpsAddress := r.httpsAddress(caCerts, b)
+		b.Status.Addresses = []pkgduckv1.Addressable{httpsAddress}
+		b.Status.Address = &httpsAddress
+	} else {
+		httpAddress := r.httpAddress(b)
+		b.Status.Address = &httpAddress
+	}
+
+	b.GetConditionSet().Manage(b.GetStatus()).MarkTrue(eventingv1.BrokerConditionAddressable)
 
 	// So, at this point the Broker is ready and everything should be solid
 	// for the triggers to act upon.
@@ -361,3 +400,37 @@ func TriggerChannelLabels(brokerName string) map[string]string {
 		"eventing.knative.dev/brokerEverything": "true",
 	}
 }
+
+func (r *Reconciler) getCaCerts() (string, error) {
+	// Getting the secret called "mt-broker-ingress-server-tls" from system namespace
+	secret, err := r.secretLister.Secrets(system.Namespace()).Get(brokerIngressTLSSecretName)
+	if err != nil {
+		return "", fmt.Errorf("failed to get CA certs from %s/%s: %w", system.Namespace(), brokerIngressTLSSecretName, err)
+	}
+	caCerts, ok := secret.Data[caCertsSecretKey]
+	if !ok {
+		return "", fmt.Errorf("failed to get CA certs from %s/%s: missing %s key", system.Namespace(), brokerIngressTLSSecretName, caCertsSecretKey)
+	}
+	return string(caCerts), nil
+}
+
+func (r *Reconciler) httpAddress(b *eventingv1.Broker) pkgduckv1.Addressable {
+	// http address uses path-based routing
+	httpAddress := pkgduckv1.Addressable{
+		Name: pointer.String("http"),
+		URL:  apis.HTTP(network.GetServiceHostname(names.BrokerIngressName, system.Namespace())),
+	}
+	httpAddress.URL.Path = fmt.Sprintf("/%s/%s", b.Namespace, b.Name)
+	return httpAddress
+}
+
+func (r *Reconciler) httpsAddress(caCerts string, b *eventingv1.Broker) pkgduckv1.Addressable {
+	// https address uses path-based routing
+	httpsAddress := pkgduckv1.Addressable{
+		Name:    pointer.String("https"),
+		URL:     apis.HTTPS(fmt.Sprintf("%s.%s.svc.%s", names.BrokerIngressName, system.Namespace(), network.GetClusterDomainName())),
+		CACerts: pointer.String(caCerts),
+	}
+	httpsAddress.URL.Path = fmt.Sprintf("/%s/%s", b.Namespace, b.Name)
+	return httpsAddress
+}
diff --git a/pkg/reconciler/broker/controller.go b/pkg/reconciler/broker/controller.go
index e1a63b0a3cd..9dc80ead253 100644
--- a/pkg/reconciler/broker/controller.go
+++ b/pkg/reconciler/broker/controller.go
@@ -36,6 +36,7 @@ import (
 	"knative.dev/pkg/configmap"
 	"knative.dev/pkg/controller"
 	"knative.dev/pkg/injection/clients/dynamicclient"
+	secretinformer "knative.dev/pkg/injection/clients/namespacedkube/informers/core/v1/secret"
 	"knative.dev/pkg/logging"
 	pkgreconciler "knative.dev/pkg/reconciler"
 	"knative.dev/pkg/system"
@@ -64,6 +65,7 @@ func NewController(
 	subscriptionInformer := subscriptioninformer.Get(ctx)
 	endpointsInformer := endpointsinformer.Get(ctx)
 	configmapInformer := configmapinformer.Get(ctx)
+	secretInformer := secretinformer.Get(ctx)
 
 	var err error
 	if Tracer, err = tracing.SetupPublishingWithDynamicConfig(logger, cmw, "mt-broker-controller", tracingconfig.ConfigName); err != nil {
@@ -84,6 +86,7 @@ func NewController(
 		subscriptionLister: subscriptionInformer.Lister(),
 		brokerClass:        eventing.MTChannelBrokerClassValue,
 		configmapLister:    configmapInformer.Lister(),
+		secretLister:       secretInformer.Lister(),
 	}
 	impl := brokerreconciler.NewImpl(ctx, r, eventing.MTChannelBrokerClassValue)
 
@@ -118,6 +121,10 @@ func NewController(
 			pkgreconciler.NameFilterFunc(names.BrokerIngressName)),
 		Handler: controller.HandleAll(grCb),
 	})
+	secretInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
+		FilterFunc: controller.FilterWithName(brokerIngressTLSSecretName),
+		Handler:    controller.HandleAll(grCb),
+	})
 
 	return impl
 }
diff --git a/pkg/reconciler/inmemorychannel/controller/inmemorychannel.go b/pkg/reconciler/inmemorychannel/controller/inmemorychannel.go
index 9896b0a575d..745b6695e41 100644
--- a/pkg/reconciler/inmemorychannel/controller/inmemorychannel.go
+++ b/pkg/reconciler/inmemorychannel/controller/inmemorychannel.go
@@ -46,6 +46,7 @@ import (
 	"knative.dev/eventing/pkg/apis/feature"
 	v1 "knative.dev/eventing/pkg/apis/messaging/v1"
 	inmemorychannelreconciler "knative.dev/eventing/pkg/client/injection/reconciler/messaging/v1/inmemorychannel"
+	"knative.dev/eventing/pkg/eventingtls"
 	"knative.dev/eventing/pkg/reconciler/inmemorychannel/controller/config"
 	"knative.dev/eventing/pkg/reconciler/inmemorychannel/controller/resources"
 )
@@ -57,7 +58,7 @@ const (
 	dispatcherDeploymentCreated     = "DispatcherDeploymentCreated"
 	dispatcherServiceCreated        = "DispatcherServiceCreated"
 	dispatcherTLSSecretName         = "imc-dispatcher-tls"
-	caCertsSecretKey                = "ca.crt"
+	caCertsSecretKey                = eventingtls.SecretCACert
 )
 
 func newDeploymentWarn(err error) pkgreconciler.Event {