Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds tls reconciler #155

Merged
merged 13 commits into from
Mar 22, 2024
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ require (
github.com/prometheus/common v0.44.0
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.25.0
gomodules.xyz/jsonpatch/v2 v2.4.0
k8s.io/api v0.28.1
k8s.io/apiextensions-apiserver v0.28.1
k8s.io/apimachinery v0.28.1
Expand Down Expand Up @@ -73,6 +72,7 @@ require (
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
Expand Down
4 changes: 4 additions & 0 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ func setupControllers(mgr ctrl.Manager, conf *config.Config, lgr logr.Logger, cl
if err := keyvault.NewPlaceholderPodController(mgr, conf, ingressManager); err != nil {
return fmt.Errorf("setting up placeholder pod controller: %w", err)
}
lgr.Info("setting up ingress tls reconciler")
if err := keyvault.NewIngressTlsReconciler(mgr, conf, ingressManager); err != nil {
return fmt.Errorf("setting up ingress tls reconciler: %w", err)
}
lgr.Info("setting up keyvault event mirror")
if err = keyvault.NewEventMirror(mgr, conf); err != nil {
return fmt.Errorf("setting up event mirror: %w", err)
Expand Down
6 changes: 6 additions & 0 deletions pkg/controller/keyvault/consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package keyvault

const (
tlsCertKvUriAnnotation = "kubernetes.azure.com/tls-cert-keyvault-uri"
tlsCertManagedAnnotation = "kubernetes.azure.com/tls-cert-keyvault-managed"
)
8 changes: 6 additions & 2 deletions pkg/controller/keyvault/ingress_secret_provider_class.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func (i *IngressSecretProviderClassReconciler) buildSPC(ing *netv1.Ingress, spc
return false, nil
}

certURI := ing.Annotations["kubernetes.azure.com/tls-cert-keyvault-uri"]
certURI := ing.Annotations[tlsCertKvUriAnnotation]
if certURI == "" {
return false, nil
}
Expand Down Expand Up @@ -185,7 +185,7 @@ func (i *IngressSecretProviderClassReconciler) buildSPC(ing *netv1.Ingress, spc
spc.Spec = secv1.SecretProviderClassSpec{
Provider: secv1.Provider("azure"),
SecretObjects: []*secv1.SecretObject{{
SecretName: fmt.Sprintf("keyvault-%s", ing.Name),
SecretName: certSecretName(ing.Name),
Type: "kubernetes.io/tls",
Data: []*secv1.SecretObjectData{
{
Expand Down Expand Up @@ -214,3 +214,7 @@ func (i *IngressSecretProviderClassReconciler) buildSPC(ing *netv1.Ingress, spc

return true, nil
}

func certSecretName(ingressName string) string {
return fmt.Sprintf("keyvault-%s", ingressName)
}
Original file line number Diff line number Diff line change
Expand Up @@ -469,4 +469,9 @@ func TestIngressSecretProviderClassReconcilerBuildSPCFailedIsManaging(t *testing
require.False(t, ok)
require.Error(t, err)
require.ErrorContains(t, err, "determining if ingress is managed")
}
}

OliverMKing marked this conversation as resolved.
Show resolved Hide resolved
func TestCertSecretName(t *testing.T) {
require.Equal(t, "keyvault-ingressname", certSecretName("ingressname"))
require.Equal(t, "keyvault-anotheringressname", certSecretName("anotheringressname"))
}
104 changes: 104 additions & 0 deletions pkg/controller/keyvault/ingress_tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package keyvault

import (
"context"
"errors"
"fmt"
"strings"

"github.com/Azure/aks-app-routing-operator/pkg/config"
"github.com/Azure/aks-app-routing-operator/pkg/controller/controllername"
"github.com/Azure/aks-app-routing-operator/pkg/controller/metrics"
"github.com/Azure/aks-app-routing-operator/pkg/util"
"github.com/go-logr/logr"
netv1 "k8s.io/api/networking/v1"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)

var ingressTlsControllerName = controllername.New("keyvault", "ingress", "tls")

// ingressTlsReconciler manages the TLS spec of an Ingress object using the Key Vault integration. Ingresses with
// the App Routing Key Vault annotation will have their TLS spec populated with the Key Vault secret name.
type ingressTlsReconciler struct {
client client.Client
events record.EventRecorder
ingressManager IngressManager
}

func NewIngressTlsReconciler(manager ctrl.Manager, conf *config.Config, ingressManager IngressManager) error {
metrics.InitControllerMetrics(ingressTlsControllerName)

if conf.DisableKeyvault {
return nil
}

return ingressTlsControllerName.AddToController(
ctrl.
NewControllerManagedBy(manager).
For(&netv1.Ingress{}), manager.GetLogger(),
).Complete(&ingressTlsReconciler{
client: manager.GetClient(),
events: manager.GetEventRecorderFor("aks-app-routing-operator"),
ingressManager: ingressManager,
})
}

func (i *ingressTlsReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) {
defer func() {
metrics.HandleControllerReconcileMetrics(ingressTlsControllerName, res, err)
}()

logger, err := logr.FromContext(ctx)
if err != nil {
return ctrl.Result{}, errors.New("getting logger from context")
}
logger = ingressTlsControllerName.AddToLogger(logger).WithValues("name", req.Name, "namespace", req.Namespace)

logger.Info("getting Ingress")
ing := &netv1.Ingress{}
if err = i.client.Get(ctx, req.NamespacedName, ing); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}

managed, err := i.ingressManager.IsManaging(ing)
if err != nil {
return ctrl.Result{}, fmt.Errorf("checking if ingress is managed: %w", err)
}

if !managed {
logger.Info("ingress is not managed by app routing")
return ctrl.Result{}, nil
}

if val, ok := ing.Annotations[tlsCertManagedAnnotation]; !ok || strings.ToLower(val) != "true" {
logger.Info("ingress does not have managed annotation")
return ctrl.Result{}, nil
}

if _, ok := ing.Annotations[tlsCertKvUriAnnotation]; !ok {
logger.Info("ingress does not have keyvault annotation")
i.events.Eventf(ing, "Warning", "KeyvaultUriAnnotationMissing", "Ingress has %[1]s annotation but is missing %[2]s annotation. %[2]s annotation is needed to manage Ingress TLS.", tlsCertManagedAnnotation, tlsCertKvUriAnnotation)
return ctrl.Result{}, nil
}

logger.Info("adding TLS spec to ingress")
OliverMKing marked this conversation as resolved.
Show resolved Hide resolved
ing.Spec.TLS = []netv1.IngressTLS{
{
SecretName: fmt.Sprintf("keyvault-%s", ing.Name),
Hosts: []string{},
},
}

for _, rule := range ing.Spec.Rules {
ing.Spec.TLS[0].Hosts = append(ing.Spec.TLS[0].Hosts, rule.Host)
}

if err := util.Upsert(ctx, i.client, ing); err != nil {
logger.Error(err, "error updating ingress")
return ctrl.Result{}, fmt.Errorf("updating ingress: %w", err)
}

return ctrl.Result{}, nil
}
Loading
Loading