diff --git a/cmd/main.go b/cmd/main.go index c533e242..7cec0d6e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -26,6 +26,7 @@ import ( // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" + routev1 "github.com/openshift/api/route/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -53,6 +54,7 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(confidentialcontainersorgv1alpha1.AddToScheme(scheme)) + utilruntime.Must(routev1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index d92f43a2..06124daa 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -73,6 +73,19 @@ rules: verbs: - get - list +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: - "" resources: - configmaps diff --git a/internal/controller/common.go b/internal/controller/common.go index ed516eba..3d46473d 100644 --- a/internal/controller/common.go +++ b/internal/controller/common.go @@ -39,6 +39,9 @@ const ( // KBS service name KbsServiceName = "kbs-service" + // KBS route name + KbsRouteName = "kbs-route" + // Root path for KBS file system rootPath = "/opt" diff --git a/internal/controller/trusteeconfig_controller.go b/internal/controller/trusteeconfig_controller.go index 0ec7956b..d677f1b3 100644 --- a/internal/controller/trusteeconfig_controller.go +++ b/internal/controller/trusteeconfig_controller.go @@ -25,11 +25,13 @@ import ( "time" "github.com/go-logr/logr" + routev1 "github.com/openshift/api/route/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/handler" @@ -54,6 +56,7 @@ type TrusteeConfigReconciler struct { //+kubebuilder:rbac:groups=confidentialcontainers.org,resources=kbsconfigs/status,verbs=get;update;patch //+kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=route.openshift.io,resources=routes,verbs=get;list;watch;create;update;patch;delete // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -365,6 +368,20 @@ func (r *TrusteeConfigReconciler) buildKbsConfigSpec(ctx context.Context) confid return spec } spec = r.configureHttps(spec) + + // Create passthrough route since https is enabled + err = r.createOrUpdateKbsRoute(ctx, routev1.TLSTerminationPassthrough) + if err != nil { + r.log.Error(err, "Error creating Trustee passthrough route") + return spec + } + } else { + // Http, create an edge route + err := r.createOrUpdateKbsRoute(ctx, routev1.TLSTerminationEdge) + if err != nil { + r.log.Error(err, "Error creating Trustee edge route") + return spec + } } // Configure attestation token verification if specified @@ -1315,3 +1332,66 @@ func (r *TrusteeConfigReconciler) createOrUpdateAttestationPolicyConfigMap(ctx c r.log.Info("Attestation policy config map already exists, preserving existing content", "ConfigMap.Namespace", r.namespace, "ConfigMap.Name", configMapName) return nil } + +// createOrUpdateKbsRoute creates a route for the KBS service if it doesn't already exist +// If the route already exists, this function does nothing +func (r *TrusteeConfigReconciler) createOrUpdateKbsRoute(ctx context.Context, termination routev1.TLSTerminationType) error { + routeName := KbsRouteName + serviceName := KbsServiceName + portName := "kbs-port" + + // Check if the route already exists + found := &routev1.Route{} + err := r.Get(ctx, client.ObjectKey{ + Namespace: r.namespace, + Name: routeName, + }, found) + + if err != nil && k8serrors.IsNotFound(err) { + // Create the route + terminationType := "passthrough" + if termination == routev1.TLSTerminationEdge { + terminationType = "edge" + } + r.log.Info("Creating KBS route", "Route.Namespace", r.namespace, "Route.Name", routeName, "Termination", terminationType) + + route := &routev1.Route{ + ObjectMeta: metav1.ObjectMeta{ + Name: routeName, + Namespace: r.namespace, + }, + Spec: routev1.RouteSpec{ + To: routev1.RouteTargetReference{ + Kind: "Service", + Name: serviceName, + }, + Port: &routev1.RoutePort{ + TargetPort: intstr.FromString(portName), + }, + TLS: &routev1.TLSConfig{ + Termination: termination, + }, + }, + } + + // Set TrusteeConfig as the owner + err = ctrl.SetControllerReference(r.trusteeConfig, route, r.Scheme) + if err != nil { + r.log.Info("Error setting controller reference for route", "err", err) + // Continue anyway, route can still be created + } + + err = r.Create(ctx, route) + if err != nil { + return err + } + r.log.Info("Successfully created KBS route", "Route.Namespace", r.namespace, "Route.Name", routeName, "Termination", terminationType) + return nil + } else if err != nil { + return err + } + + // Route already exists, do nothing + r.log.Info("KBS route already exists, skipping creation", "Route.Namespace", r.namespace, "Route.Name", routeName) + return nil +}