diff --git a/cmd/main.go b/cmd/main.go index 9ea0348e..80d3fec6 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -30,6 +30,7 @@ import ( corev1 "k8s.io/api/core/v1" k8spoliciesv1 "k8s.io/api/policy/v1" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" @@ -79,6 +80,7 @@ func main() { var enableOtelSidecar bool var openTelemetryClientCertificateSecret string var openTelemetryCertificateSecret string + var clientCAConfigMapName string flag.StringVar(&metricsAddr, "metrics-bind-address", ":8088", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") @@ -105,6 +107,7 @@ func main() { "always-accept-admission-reviews-on-deployments-namespace", false, "Always accept admission reviews targeting the deployments-namespace.") + flag.StringVar(&clientCAConfigMapName, "client-ca-configmap-name", "", "The name of the ConfigMap containing the client CA certificate. If provided, mTLS will be enabled.") opts := zap.Options{} opts.BindFlags(flag.CommandLine) @@ -134,7 +137,7 @@ func main() { }() } - mgr, err := setupManager(deploymentsNamespace, metricsAddr, probeAddr, enableLeaderElection) + mgr, err := setupManager(deploymentsNamespace, metricsAddr, probeAddr, enableLeaderElection, clientCAConfigMapName != "") if err != nil { setupLog.Error(err, "unable to start manager") retcode = 1 @@ -153,7 +156,14 @@ func main() { OtelCertificateSecret: openTelemetryCertificateSecret, OtelClientCertificateSecret: openTelemetryClientCertificateSecret, } - if err = setupReconcilers(mgr, deploymentsNamespace, webhookServiceName, alwaysAcceptAdmissionReviewsOnDeploymentsNamespace, featureGateAdmissionWebhookMatchConditions, otelConfiguration); err != nil { + if err = setupReconcilers(mgr, + deploymentsNamespace, + webhookServiceName, + alwaysAcceptAdmissionReviewsOnDeploymentsNamespace, + featureGateAdmissionWebhookMatchConditions, + otelConfiguration, + clientCAConfigMapName, + ); err != nil { setupLog.Error(err, "unable to create controllers") retcode = 1 return @@ -181,10 +191,16 @@ func main() { } } -func setupManager(deploymentsNamespace string, metricsAddr string, probeAddr string, enableLeaderElection bool) (ctrl.Manager, error) { +func setupManager(deploymentsNamespace string, metricsAddr string, probeAddr string, enableLeaderElection bool, enableMutualTLS bool) (ctrl.Manager, error) { namespaceSelector := cache.ByObject{ Field: fields.ParseSelectorOrDie("metadata.namespace=" + deploymentsNamespace), } + + clientCAName := "" + if enableMutualTLS { + clientCAName = constants.ClientCACert + } + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, Metrics: metricsserver.Options{ @@ -227,6 +243,9 @@ func setupManager(deploymentsNamespace string, metricsAddr string, probeAddr str &appsv1.Deployment{}: namespaceSelector, }, }, + WebhookServer: webhook.NewServer(webhook.Options{ + ClientCAName: clientCAName, + }), }) return mgr, err } @@ -241,7 +260,14 @@ func setupProbes(mgr ctrl.Manager) error { return nil } -func setupReconcilers(mgr ctrl.Manager, deploymentsNamespace, webhookServiceName string, alwaysAcceptAdmissionReviewsOnDeploymentsNamespace, featureGateAdmissionWebhookMatchConditions bool, otelConfiguration controller.TelemetryConfiguration) error { +func setupReconcilers(mgr ctrl.Manager, + deploymentsNamespace, + webhookServiceName string, + alwaysAcceptAdmissionReviewsOnDeploymentsNamespace, + featureGateAdmissionWebhookMatchConditions bool, + otelConfiguration controller.TelemetryConfiguration, + clientCAConfigMapName string, +) error { if err := (&controller.PolicyServerReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), @@ -249,6 +275,7 @@ func setupReconcilers(mgr ctrl.Manager, deploymentsNamespace, webhookServiceName DeploymentsNamespace: deploymentsNamespace, AlwaysAcceptAdmissionReviewsInDeploymentsNamespace: alwaysAcceptAdmissionReviewsOnDeploymentsNamespace, TelemetryConfiguration: otelConfiguration, + ClientCAConfigMapName: clientCAConfigMapName, }).SetupWithManager(mgr); err != nil { return errors.Join(errors.New("unable to create PolicyServer controller"), err) } diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 7583fdc9..788d960d 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -14,6 +14,7 @@ const ( PolicyServerPort = 8443 PolicyServerMetricsPortEnvVar = "KUBEWARDEN_POLICY_SERVER_SERVICES_METRICS_PORT" PolicyServerMetricsPort = 8080 + PolicyServerReadinessProbePort = 8081 PolicyServerReadinessProbe = "/readiness" PolicyServerLogFmtEnvVar = "KUBEWARDEN_LOG_FMT" @@ -72,6 +73,9 @@ const ( CARootPrivateKey = "ca.key" OldCARootCert = "old-ca.crt" + // Client CA ConfigMap. + ClientCACert = "client-ca.crt" + // Certs. CertExpirationYears = 10 CACertExpiration = 10 * 365 * 24 * time.Hour diff --git a/internal/controller/admissionpolicy_controller_test.go b/internal/controller/admissionpolicy_controller_test.go index c7ff52fe..c0c6d33e 100644 --- a/internal/controller/admissionpolicy_controller_test.go +++ b/internal/controller/admissionpolicy_controller_test.go @@ -1,5 +1,3 @@ -//go:build testing - /* Copyright 2022. diff --git a/internal/controller/admissionpolicygroup_controller_test.go b/internal/controller/admissionpolicygroup_controller_test.go index ab868b19..69d2224c 100644 --- a/internal/controller/admissionpolicygroup_controller_test.go +++ b/internal/controller/admissionpolicygroup_controller_test.go @@ -1,5 +1,3 @@ -//go:build testing - /* Copyright 2022. diff --git a/internal/controller/clusteradmissionpolicy_controller_test.go b/internal/controller/clusteradmissionpolicy_controller_test.go index 9fd79c60..7263ca2d 100644 --- a/internal/controller/clusteradmissionpolicy_controller_test.go +++ b/internal/controller/clusteradmissionpolicy_controller_test.go @@ -1,5 +1,3 @@ -//go:build testing - /* Copyright 2022. diff --git a/internal/controller/clusteradmissionpolicygroup_controller_test.go b/internal/controller/clusteradmissionpolicygroup_controller_test.go index 7a8f8a60..b14d01e0 100644 --- a/internal/controller/clusteradmissionpolicygroup_controller_test.go +++ b/internal/controller/clusteradmissionpolicygroup_controller_test.go @@ -1,5 +1,3 @@ -//go:build testing - /* Copyright 2022. diff --git a/internal/controller/policyserver_controller.go b/internal/controller/policyserver_controller.go index 28be158f..33198f18 100644 --- a/internal/controller/policyserver_controller.go +++ b/internal/controller/policyserver_controller.go @@ -61,6 +61,7 @@ type PolicyServerReconciler struct { Scheme *runtime.Scheme DeploymentsNamespace string AlwaysAcceptAdmissionReviewsInDeploymentsNamespace bool + ClientCAConfigMapName string } // TelemetryConfiguration is a struct that contains the configuration for the @@ -261,6 +262,7 @@ func (r *PolicyServerReconciler) enqueueAdmissionPolicyGroup(_ context.Context, }, } } + func (r *PolicyServerReconciler) enqueueClusterAdmissionPolicy(_ context.Context, object client.Object) []reconcile.Request { // The watch will trigger twice per object change; once with the old // object, and once the new object. We need to be mindful when doing diff --git a/internal/controller/policyserver_controller_deployment.go b/internal/controller/policyserver_controller_deployment.go index 0c39c92c..ca0ca5ca 100644 --- a/internal/controller/policyserver_controller_deployment.go +++ b/internal/controller/policyserver_controller_deployment.go @@ -11,6 +11,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -27,6 +28,10 @@ const ( policiesVolumeName = "policies" sourcesVolumeName = "sources" verificationConfigVolumeName = "verification" + kubewardenCAVolumeName = "kubewarden-ca-cert" + kubewardenCAVolumePath = "/ca" + clientCAVolumeName = "client-ca-cert" + clientCAVolumePath = "/client-ca" secretsContainerPath = "/pki" imagePullSecretVolumeName = "imagepullsecret" dockerConfigJSONPolicyServerPath = "/home/kubewarden/.docker" @@ -52,7 +57,7 @@ func (r *PolicyServerReconciler) reconcilePolicyServerDeployment(ctx context.Con }, } _, err = controllerutil.CreateOrPatch(ctx, r.Client, policyServerDeployment, func() error { - return r.updatePolicyServerDeployment(policyServer, policyServerDeployment, configMapVersion) + return r.updatePolicyServerDeployment(ctx, policyServer, policyServerDeployment, configMapVersion) }) if err != nil { return fmt.Errorf("error reconciling policy-server deployment: %w", err) @@ -77,52 +82,7 @@ func configureVerificationConfig(policyServer *policiesv1.PolicyServer, admissio } } -func configureImagePullSecret(policyServer *policiesv1.PolicyServer, admissionContainer *corev1.Container) { - if policyServer.Spec.ImagePullSecret != "" { - admissionContainer.VolumeMounts = append(admissionContainer.VolumeMounts, - corev1.VolumeMount{ - Name: imagePullSecretVolumeName, - ReadOnly: true, - MountPath: dockerConfigJSONPolicyServerPath, - }) - admissionContainer.Env = append(admissionContainer.Env, - corev1.EnvVar{ - Name: "KUBEWARDEN_DOCKER_CONFIG_JSON_PATH", - Value: dockerConfigJSONPolicyServerPath, - }) - } -} - -func configuresInsecureSources(policyServer *policiesv1.PolicyServer, admissionContainer *corev1.Container) { - if len(policyServer.Spec.InsecureSources) > 0 || len(policyServer.Spec.SourceAuthorities) > 0 { - admissionContainer.VolumeMounts = append(admissionContainer.VolumeMounts, - corev1.VolumeMount{ - Name: sourcesVolumeName, - ReadOnly: true, - MountPath: constants.PolicyServerSourcesConfigContainerPath, - }) - admissionContainer.Env = append(admissionContainer.Env, - corev1.EnvVar{ - Name: "KUBEWARDEN_SOURCES_PATH", - Value: filepath.Join(constants.PolicyServerSourcesConfigContainerPath, sourcesFilename), - }) - } -} - -func configureLabelsAndAnnotations(policyServerDeployment *appsv1.Deployment, policyServer *policiesv1.PolicyServer, configMapVersion string) { - if policyServerDeployment.ObjectMeta.Annotations == nil { - policyServerDeployment.ObjectMeta.Annotations = make(map[string]string) - } - policyServerDeployment.ObjectMeta.Annotations[constants.PolicyServerDeploymentConfigVersionAnnotation] = configMapVersion - - if policyServerDeployment.Labels == nil { - policyServerDeployment.Labels = make(map[string]string) - } - policyServerDeployment.Labels[constants.AppLabelKey] = policyServer.AppLabel() - policyServerDeployment.Labels[constants.PolicyServerLabelKey] = policyServer.Name -} - -func (r *PolicyServerReconciler) updatePolicyServerDeployment(policyServer *policiesv1.PolicyServer, policyServerDeployment *appsv1.Deployment, configMapVersion string) error { +func (r *PolicyServerReconciler) updatePolicyServerDeployment(ctx context.Context, policyServer *policiesv1.PolicyServer, policyServerDeployment *appsv1.Deployment, configMapVersion string) error { admissionContainer := getPolicyServerContainer(policyServer) if r.AlwaysAcceptAdmissionReviewsInDeploymentsNamespace { @@ -153,70 +113,19 @@ func (r *PolicyServerReconciler) updatePolicyServerDeployment(policyServer *poli configureLabelsAndAnnotations(policyServerDeployment, policyServer, configMapVersion) - policyServerDeployment.Spec = appsv1.DeploymentSpec{ - Replicas: &policyServer.Spec.Replicas, - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - constants.AppLabelKey: policyServer.AppLabel(), - }, - }, - Strategy: appsv1.DeploymentStrategy{ - Type: appsv1.RollingUpdateDeploymentStrategyType, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - constants.AppLabelKey: policyServer.AppLabel(), - constants.PolicyServerDeploymentPodSpecConfigVersionLabel: configMapVersion, - constants.PolicyServerLabelKey: policyServer.Name, - }, - Annotations: templateAnnotations, - }, - Spec: corev1.PodSpec{ - SecurityContext: podSecurityContext, - Containers: []corev1.Container{admissionContainer}, - ServiceAccountName: policyServer.Spec.ServiceAccountName, - Tolerations: policyServer.Spec.Tolerations, - Affinity: &policyServer.Spec.Affinity, - Volumes: []corev1.Volume{ - { - Name: policyStoreVolume, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: certsVolumeName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: policyServer.NameWithPrefix(), - }, - }, - }, - { - Name: policiesVolumeName, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: policyServer.NameWithPrefix(), - }, - Items: []corev1.KeyToPath{ - { - Key: constants.PolicyServerConfigPoliciesEntry, - Path: policiesFilename, - }, - }, - }, - }, - }, - }, - }, - }, - } - + policyServerDeployment.Spec = buildPolicyServerDeploymentSpec( + policyServer, + admissionContainer, + configMapVersion, + templateAnnotations, + podSecurityContext, + ) r.adaptDeploymentForMetricsAndTracingConfiguration(policyServerDeployment, templateAnnotations) r.adaptDeploymentSettingsForPolicyServer(policyServerDeployment, policyServer) + if err := r.configureMutualTLS(ctx, policyServerDeployment); err != nil { + return fmt.Errorf("failed to configure mutual TLS: %w", err) + } if err := controllerutil.SetOwnerReference(policyServer, policyServerDeployment, r.Client.Scheme()); err != nil { return errors.Join(errors.New("failed to set policy server deployment owner reference"), err) } @@ -345,6 +254,200 @@ func (r *PolicyServerReconciler) adaptDeploymentSettingsForPolicyServer(policySe } } +func configureImagePullSecret(policyServer *policiesv1.PolicyServer, admissionContainer *corev1.Container) { + if policyServer.Spec.ImagePullSecret != "" { + admissionContainer.VolumeMounts = append(admissionContainer.VolumeMounts, + corev1.VolumeMount{ + Name: imagePullSecretVolumeName, + ReadOnly: true, + MountPath: dockerConfigJSONPolicyServerPath, + }) + admissionContainer.Env = append(admissionContainer.Env, + corev1.EnvVar{ + Name: "KUBEWARDEN_DOCKER_CONFIG_JSON_PATH", + Value: dockerConfigJSONPolicyServerPath, + }) + } +} + +func configuresInsecureSources(policyServer *policiesv1.PolicyServer, admissionContainer *corev1.Container) { + if len(policyServer.Spec.InsecureSources) > 0 || len(policyServer.Spec.SourceAuthorities) > 0 { + admissionContainer.VolumeMounts = append(admissionContainer.VolumeMounts, + corev1.VolumeMount{ + Name: sourcesVolumeName, + ReadOnly: true, + MountPath: constants.PolicyServerSourcesConfigContainerPath, + }) + admissionContainer.Env = append(admissionContainer.Env, + corev1.EnvVar{ + Name: "KUBEWARDEN_SOURCES_PATH", + Value: filepath.Join(constants.PolicyServerSourcesConfigContainerPath, sourcesFilename), + }) + } +} + +func configureLabelsAndAnnotations(policyServerDeployment *appsv1.Deployment, policyServer *policiesv1.PolicyServer, configMapVersion string) { + if policyServerDeployment.ObjectMeta.Annotations == nil { + policyServerDeployment.ObjectMeta.Annotations = make(map[string]string) + } + policyServerDeployment.ObjectMeta.Annotations[constants.PolicyServerDeploymentConfigVersionAnnotation] = configMapVersion + + if policyServerDeployment.Labels == nil { + policyServerDeployment.Labels = make(map[string]string) + } + policyServerDeployment.Labels[constants.AppLabelKey] = policyServer.AppLabel() + policyServerDeployment.Labels[constants.PolicyServerLabelKey] = policyServer.Name +} + +func (r *PolicyServerReconciler) configureMutualTLS(ctx context.Context, policyServerDeployment *appsv1.Deployment) error { + policyServerDeployment.Spec.Template.Spec.Volumes = append( + policyServerDeployment.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: kubewardenCAVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: constants.CARootSecretName, + Items: []corev1.KeyToPath{ + { + Key: constants.CARootCert, + Path: constants.CARootCert, + }, + }, + }, + }, + }, + ) + + admissionContainer := &policyServerDeployment.Spec.Template.Spec.Containers[0] + + admissionContainer.VolumeMounts = append( + admissionContainer.VolumeMounts, + corev1.VolumeMount{ + Name: kubewardenCAVolumeName, + MountPath: kubewardenCAVolumePath, + ReadOnly: true, + }, + ) + + if r.ClientCAConfigMapName != "" { + if err := r.Client.Get(ctx, types.NamespacedName{Name: r.ClientCAConfigMapName, Namespace: r.DeploymentsNamespace}, &corev1.ConfigMap{}); err != nil { + return fmt.Errorf("failed to fetch client CA config map: %w", err) + } + + policyServerDeployment.Spec.Template.Spec.Volumes = append( + policyServerDeployment.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: clientCAVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: r.ClientCAConfigMapName, + }, + Items: []corev1.KeyToPath{ + { + Key: constants.ClientCACert, + Path: constants.ClientCACert, + }, + }, + }, + }, + }, + ) + + admissionContainer.VolumeMounts = append( + admissionContainer.VolumeMounts, + corev1.VolumeMount{ + Name: clientCAVolumeName, + MountPath: clientCAVolumePath, + ReadOnly: true, + }, + ) + + // kubewardenCAPath := filepath.Join(kubewardenCAVolumePath, constants.CARootCert) + // clientCAPath := filepath.Join(clientCAVolumePath, constants.ClientCACert) + // admissionContainer.Env = append(admissionContainer.Env, corev1.EnvVar{ + // Name: "KUBEWARDEN_CLIENT_CA_FILE", + // Value: fmt.Sprintf("%s,%s", kubewardenCAPath, clientCAPath), + // }) + // return nil + } + + admissionContainer.Env = append(admissionContainer.Env, corev1.EnvVar{ + Name: "KUBEWARDEN_CLIENT_CA_FILE", + Value: filepath.Join(kubewardenCAVolumePath, constants.CARootCert), + }) + return nil +} + +func buildPolicyServerDeploymentSpec( + policyServer *policiesv1.PolicyServer, + admissionContainer corev1.Container, + configMapVersion string, + templateAnnotations map[string]string, + podSecurityContext *corev1.PodSecurityContext, +) appsv1.DeploymentSpec { + return appsv1.DeploymentSpec{ + Replicas: &policyServer.Spec.Replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.AppLabelKey: policyServer.AppLabel(), + }, + }, + Strategy: appsv1.DeploymentStrategy{ + Type: appsv1.RollingUpdateDeploymentStrategyType, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + constants.AppLabelKey: policyServer.AppLabel(), + constants.PolicyServerDeploymentPodSpecConfigVersionLabel: configMapVersion, + constants.PolicyServerLabelKey: policyServer.Name, + }, + Annotations: templateAnnotations, + }, + Spec: corev1.PodSpec{ + SecurityContext: podSecurityContext, + Containers: []corev1.Container{admissionContainer}, + ServiceAccountName: policyServer.Spec.ServiceAccountName, + Tolerations: policyServer.Spec.Tolerations, + Affinity: &policyServer.Spec.Affinity, + Volumes: []corev1.Volume{ + { + Name: policyStoreVolume, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + { + Name: certsVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: policyServer.NameWithPrefix(), + }, + }, + }, + { + Name: policiesVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: policyServer.NameWithPrefix(), + }, + Items: []corev1.KeyToPath{ + { + Key: constants.PolicyServerConfigPoliciesEntry, + Path: policiesFilename, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + func setOtelCertificateMounts(policyServerDeployment *appsv1.Deployment, otelCertificateSecret, otelClientCertificateSecret string) { admissionContainer := &policyServerDeployment.Spec.Template.Spec.Containers[0] defaultCertificateMountMode := int32(defaultOtelCertificateMountMode) @@ -488,6 +591,10 @@ func getPolicyServerContainer(policyServer *policiesv1.PolicyServer) corev1.Cont Name: "KUBEWARDEN_PORT", Value: strconv.Itoa(constants.PolicyServerPort), }, + { + Name: "KUBEWARDEN_READINESS_PROBE_PORT", + Value: strconv.Itoa(constants.PolicyServerReadinessProbePort), + }, { Name: "KUBEWARDEN_POLICIES_DOWNLOAD_DIR", Value: policyStoreVolumePath, @@ -505,8 +612,8 @@ func getPolicyServerContainer(policyServer *policiesv1.PolicyServer) corev1.Cont ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ Path: constants.PolicyServerReadinessProbe, - Port: intstr.FromInt(constants.PolicyServerPort), - Scheme: corev1.URISchemeHTTPS, + Port: intstr.FromInt(constants.PolicyServerReadinessProbePort), + Scheme: corev1.URISchemeHTTP, }, }, }, diff --git a/internal/controller/policyserver_controller_test.go b/internal/controller/policyserver_controller_test.go index 3f152b0e..3e1ba78a 100644 --- a/internal/controller/policyserver_controller_test.go +++ b/internal/controller/policyserver_controller_test.go @@ -1,5 +1,3 @@ -//go:build testing - /* copyright 2022. @@ -660,6 +658,62 @@ var _ = Describe("PolicyServer controller", func() { }).Should(Succeed()) }) + // It("should enable mTLS in the policy server deployment", func() { + // policyServer := policiesv1.NewPolicyServerFactory().WithName(policyServerName).Build() + // createPolicyServerAndWaitForItsService(ctx, policyServer) + + // deployment, err := getTestPolicyServerDeployment(ctx, policyServerName) + // Expect(err).ToNot(HaveOccurred()) + + // container := deployment.Spec.Template.Spec.Containers[0] + + // kubewardenCAPath := filepath.Join(kubewardenCAVolumePath, constants.CARootCert) + // clientCAPath := filepath.Join(clientCAVolumePath, constants.ClientCACert) + // By("specifing the client ca certificate") + // Expect(container.Env).To(ContainElement(MatchFields(IgnoreExtras, Fields{ + // "Name": Equal("KUBEWARDEN_CLIENT_CA_FILE"), + // "Value": Equal(fmt.Sprintf("%s,%s", kubewardenCAPath, clientCAPath)), + // }))) + + // By("mounting the kubewarden CA Secret") + // Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(MatchFields(IgnoreExtras, Fields{ + // "Name": Equal(kubewardenCAVolumeName), + // "VolumeSource": MatchFields(IgnoreExtras, Fields{ + // "Secret": PointTo(MatchFields(IgnoreExtras, Fields{ + // "SecretName": Equal(constants.CARootSecretName), + // "Items": ConsistOf(MatchFields(IgnoreExtras, Fields{ + // "Key": Equal(constants.CARootCert), + // "Path": Equal(constants.CARootCert), + // })), + // })), + // }), + // }))) + // Expect(container.VolumeMounts).To(ContainElement(MatchFields(IgnoreExtras, Fields{ + // "Name": Equal(kubewardenCAVolumeName), + // "MountPath": Equal(kubewardenCAVolumePath), + // }))) + + // By("mounting the client CA ConfigMap") + // Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(MatchFields(IgnoreExtras, Fields{ + // "Name": Equal(clientCAVolumeName), + // "VolumeSource": MatchFields(IgnoreExtras, Fields{ + // "ConfigMap": PointTo(MatchFields(IgnoreExtras, Fields{ + // "LocalObjectReference": MatchFields(IgnoreExtras, Fields{ + // "Name": Equal(clientCAConfigMapName), + // }), + // "Items": ConsistOf(MatchFields(IgnoreExtras, Fields{ + // "Key": Equal(constants.ClientCACert), + // "Path": Equal(constants.ClientCACert), + // })), + // })), + // }), + // }))) + // Expect(container.VolumeMounts).To(ContainElement(MatchFields(IgnoreExtras, Fields{ + // "Name": Equal(clientCAVolumeName), + // "MountPath": Equal(clientCAVolumePath), + // }))) + // }) + It("should set the configMap version as a deployment annotation", func() { policyServer := policiesv1.NewPolicyServerFactory().WithName(policyServerName).Build() createPolicyServerAndWaitForItsService(ctx, policyServer) diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 1c9af23e..c30da231 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -148,9 +148,10 @@ var _ = SynchronizedBeforeSuite(func() []byte { Expect(err).ToNot(HaveOccurred()) err = (&PolicyServerReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - DeploymentsNamespace: deploymentsNamespace, + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + DeploymentsNamespace: deploymentsNamespace, + ClientCAConfigMapName: clientCAConfigMapName, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) @@ -178,6 +179,20 @@ var _ = SynchronizedBeforeSuite(func() []byte { }) Expect(err).NotTo(HaveOccurred()) + // Create the client CA config map + clientCACertBytes, _, err := certs.GenerateCA(time.Now(), time.Now().Add(constants.CACertExpiration)) + Expect(err).NotTo(HaveOccurred()) + err = k8sClient.Create(ctx, &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: clientCAConfigMapName, + Namespace: deploymentsNamespace, + }, + Data: map[string]string{ + constants.ClientCACert: string(clientCACertBytes), + }, + }) + Expect(err).NotTo(HaveOccurred()) + go func() { defer GinkgoRecover() err = k8sManager.Start(ctx) diff --git a/internal/controller/utils_test.go b/internal/controller/utils_test.go index c6d9743b..0edc6c28 100644 --- a/internal/controller/utils_test.go +++ b/internal/controller/utils_test.go @@ -1,5 +1,3 @@ -//go:build testing - /* Copyright 2022. @@ -44,6 +42,7 @@ import ( const ( integrationTestsFinalizer = "integration-tests-safety-net-finalizer" defaultKubewardenRepository = "ghcr.io/kubewarden/policy-server" + clientCAConfigMapName = "client-ca" ) func getTestAdmissionPolicy(ctx context.Context, namespace, name string) (*policiesv1.AdmissionPolicy, error) {