diff --git a/api/v1/checluster_conversion_from.go b/api/v1/checluster_conversion_from.go index a1f3ebb73..753e4c86c 100644 --- a/api/v1/checluster_conversion_from.go +++ b/api/v1/checluster_conversion_from.go @@ -428,10 +428,10 @@ func (dst *CheCluster) convertFrom_Storage(src *chev2.CheCluster) error { func findTrustStoreConfigMap(namespace string) (string, error) { k8sHelper := k8shelper.New() - _, err := k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Get(context.TODO(), constants.DefaultServerTrustStoreConfigMapName, metav1.GetOptions{}) + _, err := k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Get(context.TODO(), constants.DefaultCaBundleCertsCMName, metav1.GetOptions{}) if err == nil { // TrustStore ConfigMap with a default name exists - return constants.DefaultServerTrustStoreConfigMapName, nil + return constants.DefaultCaBundleCertsCMName, nil } return "", nil diff --git a/api/v1/checluster_conversion_to.go b/api/v1/checluster_conversion_to.go index d73c6e32d..5273f983d 100644 --- a/api/v1/checluster_conversion_to.go +++ b/api/v1/checluster_conversion_to.go @@ -522,17 +522,17 @@ func createCredentialsSecret(username string, password string, secretName string // Since we API V2 does not have `server.ServerTrustStoreConfigMapName` field, we need to create // the same ConfigMap but with a default name to be correctly handled by a controller. func renameTrustStoreConfigMapToDefault(trustStoreConfigMapName string, namespace string) error { - if trustStoreConfigMapName == constants.DefaultServerTrustStoreConfigMapName { + if trustStoreConfigMapName == constants.DefaultCaBundleCertsCMName { // Already in default name return nil } k8sHelper := k8shelper.New() - _, err := k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Get(context.TODO(), constants.DefaultServerTrustStoreConfigMapName, metav1.GetOptions{}) + _, err := k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Get(context.TODO(), constants.DefaultCaBundleCertsCMName, metav1.GetOptions{}) if err == nil { // ConfigMap with a default name already exists, we can't proceed - return fmt.Errorf("TrustStore ConfigMap %s already exists", constants.DefaultServerTrustStoreConfigMapName) + return fmt.Errorf("TrustStore ConfigMap %s already exists", constants.DefaultCaBundleCertsCMName) } existedTrustStoreConfigMap, err := k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Get(context.TODO(), trustStoreConfigMapName, metav1.GetOptions{}) @@ -556,7 +556,7 @@ func renameTrustStoreConfigMapToDefault(trustStoreConfigMapName string, namespac APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ - Name: constants.DefaultServerTrustStoreConfigMapName, + Name: constants.DefaultCaBundleCertsCMName, Namespace: namespace, Labels: labels.Merge(newTrustStoreConfigMapLabels, existedTrustStoreConfigMap.Labels), }, @@ -573,7 +573,7 @@ func renameTrustStoreConfigMapToDefault(trustStoreConfigMapName string, namespac return err } - logger.Info("TrustStore ConfigMap '" + constants.DefaultServerTrustStoreConfigMapName + "' created.") + logger.Info("TrustStore ConfigMap '" + constants.DefaultCaBundleCertsCMName + "' created.") return nil } diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index 68a18769a..eac17c2d3 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -110,7 +110,7 @@ type CheClusterDevEnvironments struct { // The URI must start from `http://` or `https://`. // +optional DefaultEditor string `json:"defaultEditor,omitempty"` - // Default components applied to DevWorkspaces. + // Default components applied to 1spaces. // These default components are meant to be used when a Devfile, that does not contain any components. // +optional DefaultComponents []devfile.Component `json:"defaultComponents,omitempty"` @@ -453,6 +453,14 @@ type DashboardHeaderMessage struct { } type TrustedCerts struct { + // By default, Operator creates and mounts the `ca-certs-merged` ConfigMap containing the CA certificates bundle + // into users` workspaces. This option allows to disable this behavior. + // +optional + DisableMountingCaBundleIntoDevWorkspace *bool `json:"disableMountingCaBundleIntoDevWorkspace,omitempty"` + // The CA bundle mount paths in the workspace pods. + // If not specified, the default is `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`. + // +optional + CaBundleMountPaths []string `json:"caBundleMountPaths,omitempty"` // The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git. // See the following page: https://www.eclipse.org/che/docs/stable/administration-guide/deploying-che-with-support-for-git-repositories-with-self-signed-certificates/ // The ConfigMap must have a `app.kubernetes.io/part-of=che.eclipse.org` label. diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index b54bd90c3..b97807638 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -267,7 +267,7 @@ func (in *CheClusterDevEnvironments) DeepCopyInto(out *CheClusterDevEnvironments if in.TrustedCerts != nil { in, out := &in.TrustedCerts, &out.TrustedCerts *out = new(TrustedCerts) - **out = **in + (*in).DeepCopyInto(*out) } if in.DefaultComponents != nil { in, out := &in.DefaultComponents, &out.DefaultComponents @@ -1101,6 +1101,16 @@ func (in *Traefik) DeepCopy() *Traefik { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedCerts) DeepCopyInto(out *TrustedCerts) { *out = *in + if in.DisableMountingCaBundleIntoDevWorkspace != nil { + in, out := &in.DisableMountingCaBundleIntoDevWorkspace, &out.DisableMountingCaBundleIntoDevWorkspace + *out = new(bool) + **out = **in + } + if in.CaBundleMountPaths != nil { + in, out := &in.CaBundleMountPaths, &out.CaBundleMountPaths + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedCerts. diff --git a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml index 4fe61bf66..f7bef8754 100644 --- a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml @@ -104,7 +104,7 @@ metadata: operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 repository: https://github.com/eclipse-che/che-operator support: Eclipse Foundation - name: eclipse-che.v7.92.0-887.next + name: eclipse-che.v7.94.0-888.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1035,7 +1035,7 @@ spec: minKubeVersion: 1.19.0 provider: name: Eclipse Foundation - version: 7.92.0-887.next + version: 7.94.0-888.next webhookdefinitions: - admissionReviewVersions: - v1 diff --git a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml index a1d052f8b..cf666dab1 100644 --- a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml +++ b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml @@ -5399,7 +5399,7 @@ spec: type: object defaultComponents: description: |- - Default components applied to DevWorkspaces. + Default components applied to 1spaces. These default components are meant to be used when a Devfile, that does not contain any components. items: properties: @@ -8003,6 +8003,18 @@ spec: trustedCerts: description: Trusted certificate settings. properties: + caBundleMountPaths: + description: |- + The CA bundle mount paths in the workspace pods. + If not specified, the default is `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`. + items: + type: string + type: array + disableMountingCaBundleIntoDevWorkspace: + description: |- + By default, Operator creates and mounts the `ca-certs-merged` ConfigMap containing the CA certificates into + a users` workspaces. This option allows to disable this behavior. + type: boolean gitTrustedCertsConfigMapName: description: |- The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git. diff --git a/config/crd/bases/org.eclipse.che_checlusters.yaml b/config/crd/bases/org.eclipse.che_checlusters.yaml index 4e1d8254e..64924956a 100644 --- a/config/crd/bases/org.eclipse.che_checlusters.yaml +++ b/config/crd/bases/org.eclipse.che_checlusters.yaml @@ -5357,7 +5357,7 @@ spec: type: object defaultComponents: description: |- - Default components applied to DevWorkspaces. + Default components applied to 1spaces. These default components are meant to be used when a Devfile, that does not contain any components. items: properties: @@ -7954,6 +7954,18 @@ spec: trustedCerts: description: Trusted certificate settings. properties: + caBundleMountPaths: + description: |- + The CA bundle mount paths in the workspace pods. + If not specified, the default is `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`. + items: + type: string + type: array + disableMountingCaBundleIntoDevWorkspace: + description: |- + By default, Operator creates and mounts the `ca-certs-merged` ConfigMap containing the CA certificates into + a users` workspaces. This option allows to disable this behavior. + type: boolean gitTrustedCertsConfigMapName: description: |- The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git. diff --git a/controllers/che/checluster_controller.go b/controllers/che/checluster_controller.go index b86f2ac5c..f45fec747 100644 --- a/controllers/che/checluster_controller.go +++ b/controllers/che/checluster_controller.go @@ -15,6 +15,8 @@ package che import ( "context" + imagepuller "github.com/eclipse-che/che-operator/pkg/deploy/image-puller" + editorsdefinitions "github.com/eclipse-che/che-operator/pkg/deploy/editors-definitions" "github.com/eclipse-che/che-operator/pkg/common/test" @@ -30,7 +32,6 @@ import ( "github.com/eclipse-che/che-operator/pkg/deploy/devfileregistry" "github.com/eclipse-che/che-operator/pkg/deploy/gateway" identityprovider "github.com/eclipse-che/che-operator/pkg/deploy/identity-provider" - imagepuller "github.com/eclipse-che/che-operator/pkg/deploy/image-puller" "github.com/eclipse-che/che-operator/pkg/deploy/migration" "github.com/eclipse-che/che-operator/pkg/deploy/pluginregistry" "github.com/eclipse-che/che-operator/pkg/deploy/postgres" @@ -96,7 +97,6 @@ func NewReconciler( reconcileManager.RegisterReconciler(migration.NewCheClusterDefaultsCleaner()) reconcileManager.RegisterReconciler(NewCheClusterValidator()) } - reconcileManager.RegisterReconciler(imagepuller.NewImagePuller()) reconcileManager.RegisterReconciler(tls.NewCertificatesReconciler()) reconcileManager.RegisterReconciler(tls.NewTlsSecretReconciler()) @@ -116,6 +116,7 @@ func NewReconciler( reconcileManager.RegisterReconciler(dashboard.NewDashboardReconciler()) reconcileManager.RegisterReconciler(gateway.NewGatewayReconciler()) reconcileManager.RegisterReconciler(server.NewCheServerReconciler()) + reconcileManager.RegisterReconciler(imagepuller.NewImagePuller()) if infrastructure.IsOpenShift() { reconcileManager.RegisterReconciler(containerbuild.NewContainerBuildReconciler()) diff --git a/controllers/che/cheobj_verifier.go b/controllers/che/cheobj_verifier.go index f8a895f69..b200e2039 100644 --- a/controllers/che/cheobj_verifier.go +++ b/controllers/che/cheobj_verifier.go @@ -15,7 +15,6 @@ package che import ( "github.com/eclipse-che/che-operator/pkg/common/constants" "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/deploy/tls" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -39,7 +38,7 @@ func IsTrustedBundleConfigMap(cl client.Client, watchNamespace string, obj clien } // Check for component - if value, exists := obj.GetLabels()[constants.KubernetesComponentLabelKey]; !exists || value != tls.CheCACertsConfigMapLabelValue { + if value, exists := obj.GetLabels()[constants.KubernetesComponentLabelKey]; !exists || value != constants.CheCABundle { // Labels do not match return false, ctrl.Request{} } diff --git a/controllers/usernamespace/usernamespace_controller.go b/controllers/usernamespace/usernamespace_controller.go index 8d146bb73..c30eaf272 100644 --- a/controllers/usernamespace/usernamespace_controller.go +++ b/controllers/usernamespace/usernamespace_controller.go @@ -119,7 +119,7 @@ func (r *CheUserNamespaceReconciler) commonRules(ctx context.Context, namesInChe } func (r *CheUserNamespaceReconciler) watchRulesForConfigMaps(ctx context.Context) handler.EventHandler { - rules := r.commonRules(ctx, tls.CheAllCACertsConfigMapName) + rules := r.commonRules(ctx, tls.CheMergedCABundleCertsCMName) return handler.EnqueueRequestsFromMapFunc( handler.MapFunc(func(obj client.Object) []reconcile.Request { return asReconcileRequestsForNamespaces(obj, rules) @@ -306,7 +306,7 @@ func (r *CheUserNamespaceReconciler) reconcileTrustedCerts(ctx context.Context, } sourceMap := &corev1.ConfigMap{} - if err := r.client.Get(ctx, client.ObjectKey{Name: tls.CheAllCACertsConfigMapName, Namespace: checluster.Namespace}, sourceMap); err != nil { + if err := r.client.Get(ctx, client.ObjectKey{Name: tls.CheMergedCABundleCertsCMName, Namespace: checluster.Namespace}, sourceMap); err != nil { if !errors.IsNotFound(err) { return err } diff --git a/controllers/usernamespace/usernamespace_controller_test.go b/controllers/usernamespace/usernamespace_controller_test.go index a89782861..a695a4eb5 100644 --- a/controllers/usernamespace/usernamespace_controller_test.go +++ b/controllers/usernamespace/usernamespace_controller_test.go @@ -114,7 +114,7 @@ func setupCheCluster(t *testing.T, ctx context.Context, cl client.Client, scheme caCerts := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: tls.CheAllCACertsConfigMapName, + Name: tls.CheMergedCABundleCertsCMName, Namespace: cheNamespaceName, }, Data: map[string]string{ @@ -550,7 +550,7 @@ func TestWatchRulesForConfigMapsInOtherNamespaces(t *testing.T) { APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ - Name: tls.CheAllCACertsConfigMapName, + Name: tls.CheMergedCABundleCertsCMName, Namespace: "eclipse-che", }, } diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 98576ccd0..1dc4c0577 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -5378,7 +5378,7 @@ spec: type: object defaultComponents: description: |- - Default components applied to DevWorkspaces. + Default components applied to 1spaces. These default components are meant to be used when a Devfile, that does not contain any components. items: properties: @@ -7975,6 +7975,18 @@ spec: trustedCerts: description: Trusted certificate settings. properties: + caBundleMountPaths: + description: |- + The CA bundle mount paths in the workspace pods. + If not specified, the default is `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`. + items: + type: string + type: array + disableMountingCaBundleIntoDevWorkspace: + description: |- + By default, Operator creates and mounts the `ca-certs-merged` ConfigMap containing the CA certificates into + a users` workspaces. This option allows to disable this behavior. + type: boolean gitTrustedCertsConfigMapName: description: |- The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git. diff --git a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index da4f87f94..843998e53 100644 --- a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -5373,7 +5373,7 @@ spec: type: object defaultComponents: description: |- - Default components applied to DevWorkspaces. + Default components applied to 1spaces. These default components are meant to be used when a Devfile, that does not contain any components. items: properties: @@ -7970,6 +7970,18 @@ spec: trustedCerts: description: Trusted certificate settings. properties: + caBundleMountPaths: + description: |- + The CA bundle mount paths in the workspace pods. + If not specified, the default is `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`. + items: + type: string + type: array + disableMountingCaBundleIntoDevWorkspace: + description: |- + By default, Operator creates and mounts the `ca-certs-merged` ConfigMap containing the CA certificates into + a users` workspaces. This option allows to disable this behavior. + type: boolean gitTrustedCertsConfigMapName: description: |- The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git. diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index f00ff5d74..211f2f782 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -5378,7 +5378,7 @@ spec: type: object defaultComponents: description: |- - Default components applied to DevWorkspaces. + Default components applied to 1spaces. These default components are meant to be used when a Devfile, that does not contain any components. items: properties: @@ -7975,6 +7975,18 @@ spec: trustedCerts: description: Trusted certificate settings. properties: + caBundleMountPaths: + description: |- + The CA bundle mount paths in the workspace pods. + If not specified, the default is `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`. + items: + type: string + type: array + disableMountingCaBundleIntoDevWorkspace: + description: |- + By default, Operator creates and mounts the `ca-certs-merged` ConfigMap containing the CA certificates into + a users` workspaces. This option allows to disable this behavior. + type: boolean gitTrustedCertsConfigMapName: description: |- The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git. diff --git a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 1265a520d..4209b9212 100644 --- a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -5373,7 +5373,7 @@ spec: type: object defaultComponents: description: |- - Default components applied to DevWorkspaces. + Default components applied to 1spaces. These default components are meant to be used when a Devfile, that does not contain any components. items: properties: @@ -7970,6 +7970,18 @@ spec: trustedCerts: description: Trusted certificate settings. properties: + caBundleMountPaths: + description: |- + The CA bundle mount paths in the workspace pods. + If not specified, the default is `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`. + items: + type: string + type: array + disableMountingCaBundleIntoDevWorkspace: + description: |- + By default, Operator creates and mounts the `ca-certs-merged` ConfigMap containing the CA certificates into + a users` workspaces. This option allows to disable this behavior. + type: boolean gitTrustedCertsConfigMapName: description: |- The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git. diff --git a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index da4f87f94..843998e53 100644 --- a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -5373,7 +5373,7 @@ spec: type: object defaultComponents: description: |- - Default components applied to DevWorkspaces. + Default components applied to 1spaces. These default components are meant to be used when a Devfile, that does not contain any components. items: properties: @@ -7970,6 +7970,18 @@ spec: trustedCerts: description: Trusted certificate settings. properties: + caBundleMountPaths: + description: |- + The CA bundle mount paths in the workspace pods. + If not specified, the default is `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`. + items: + type: string + type: array + disableMountingCaBundleIntoDevWorkspace: + description: |- + By default, Operator creates and mounts the `ca-certs-merged` ConfigMap containing the CA certificates into + a users` workspaces. This option allows to disable this behavior. + type: boolean gitTrustedCertsConfigMapName: description: |- The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git. diff --git a/pkg/common/constants/constants.go b/pkg/common/constants/constants.go index 623f68a6c..84ddcceac 100644 --- a/pkg/common/constants/constants.go +++ b/pkg/common/constants/constants.go @@ -44,7 +44,7 @@ const ( DefaultServerLogLevel = "INFO" DefaultServerMetricsPort = int32(8087) DefaultServerDebugPort = int32(8000) - DefaultServerTrustStoreConfigMapName = "ca-certs" + DefaultCaBundleCertsCMName = "ca-certs" DefaultProxyCredentialsSecret = "proxy-credentials" DefaultGitSelfSignedCertsConfigMapName = "che-git-self-signed-cert" DefaultJavaOpts = "-XX:MaxRAMPercentage=85.0" @@ -119,6 +119,7 @@ const ( GatewayAuthorizationContainerName = "kube-rbac-proxy" KubernetesImagePullerComponentName = "kubernetes-image-puller" EditorDefinitionComponentName = "editor-definition" + CheCABundle = "ca-bundle" // common CheFlavor = "che" @@ -137,4 +138,5 @@ var ( "app": "che", "component": "che-gateway-config", } + DefaultCaBundleMountPaths = []string{"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"} ) diff --git a/pkg/deploy/dashboard/deployment_dashboard.go b/pkg/deploy/dashboard/deployment_dashboard.go index 7c0e5e2b0..936249c96 100644 --- a/pkg/deploy/dashboard/deployment_dashboard.go +++ b/pkg/deploy/dashboard/deployment_dashboard.go @@ -248,7 +248,7 @@ func (d *DashboardReconciler) provisionCustomPublicCA(volumes []corev1.Volume, v VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ - Name: tls.CheAllCACertsConfigMapName, + Name: tls.CheMergedCABundleCertsCMName, }, }, }, diff --git a/pkg/deploy/image-puller/imagepuller.go b/pkg/deploy/image-puller/imagepuller.go index 7bfb9073e..437f8547f 100644 --- a/pkg/deploy/image-puller/imagepuller.go +++ b/pkg/deploy/image-puller/imagepuller.go @@ -153,7 +153,7 @@ func (ip *ImagePuller) syncKubernetesImagePuller(defaultImages []string, ctx *ch imagePuller.Spec.Images = convertToSpecField(defaultImages) } - return deploy.SyncWithClient(ctx.ClusterAPI.NonCachingClient, ctx, imagePuller, kubernetesImagePullerDiffOpts) + return deploy.SyncForClient(ctx.ClusterAPI.NonCachingClient, ctx, imagePuller, kubernetesImagePullerDiffOpts) } func getImagePullerCustomResourceName(ctx *chetypes.DeployContext) string { diff --git a/pkg/deploy/migration/on-reconcile-one-time-migration.go b/pkg/deploy/migration/on-reconcile-one-time-migration.go index fbdcf7b17..16e05d228 100644 --- a/pkg/deploy/migration/on-reconcile-one-time-migration.go +++ b/pkg/deploy/migration/on-reconcile-one-time-migration.go @@ -119,7 +119,7 @@ func addPartOfCheLabeltoUserDefinedObjects(ctx *chetypes.DeployContext) error { } // Legacy config map with additional CA certificates - if err := addPartOfCheLabelToConfigMap(ctx, constants.DefaultServerTrustStoreConfigMapName); err != nil { + if err := addPartOfCheLabelToConfigMap(ctx, constants.DefaultCaBundleCertsCMName); err != nil { return err } diff --git a/pkg/deploy/secret.go b/pkg/deploy/secret.go index 1b5861717..5de872070 100644 --- a/pkg/deploy/secret.go +++ b/pkg/deploy/secret.go @@ -38,7 +38,7 @@ func SyncSecretToCluster( namespace string, data map[string][]byte) (bool, error) { - secretSpec := GetSecretSpec(deployContext, name, namespace, data) + secretSpec := GetSecretSpec(name, namespace, data) return Sync(deployContext, secretSpec, SecretDiffOpts) } @@ -83,7 +83,7 @@ func GetSecrets(deployContext *chetypes.DeployContext, labels map[string]string, } // GetSecretSpec return default secret config for given data -func GetSecretSpec(deployContext *chetypes.DeployContext, name string, namespace string, data map[string][]byte) *corev1.Secret { +func GetSecretSpec(name string, namespace string, data map[string][]byte) *corev1.Secret { labels := GetLabels(defaults.GetCheFlavor()) secret := &corev1.Secret{ TypeMeta: metav1.TypeMeta{ diff --git a/pkg/deploy/server/server_configmap.go b/pkg/deploy/server/server_configmap.go index fa6044df6..2e53c6c3f 100644 --- a/pkg/deploy/server/server_configmap.go +++ b/pkg/deploy/server/server_configmap.go @@ -173,7 +173,7 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *chetypes.DeployContext) ( PluginRegistryInternalUrl: pluginRegistryInternalURL, CheJGroupsKubernetesLabels: cheLabels, CheMetricsEnabled: cheMetrics, - CheTrustedCABundlesConfigMap: deploytls.CheAllCACertsConfigMapName, + CheTrustedCABundlesConfigMap: deploytls.CheMergedCABundleCertsCMName, ServerStrategy: "single-host", WorkspaceExposure: "gateway", SingleHostGatewayConfigMapLabels: singleHostGatewayConfigMapLabels, diff --git a/pkg/deploy/server/server_deployment.go b/pkg/deploy/server/server_deployment.go index 0998f4b04..1e71dac0f 100644 --- a/pkg/deploy/server/server_deployment.go +++ b/pkg/deploy/server/server_deployment.go @@ -51,7 +51,7 @@ func (s CheServerReconciler) getDeploymentSpec(ctx *chetypes.DeployContext) (*ap VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ - Name: tls.CheAllCACertsConfigMapName, + Name: tls.CheMergedCABundleCertsCMName, }, }, }, diff --git a/pkg/deploy/sync.go b/pkg/deploy/sync.go index 3a8ef51f8..02c1dd2d9 100644 --- a/pkg/deploy/sync.go +++ b/pkg/deploy/sync.go @@ -37,10 +37,10 @@ var ( // Returns true if object is up-to-date otherwise returns false func Sync(deployContext *chetypes.DeployContext, blueprint client.Object, diffOpts ...cmp.Option) (bool, error) { cli := getClientForObject(blueprint.GetNamespace(), deployContext) - return SyncWithClient(cli, deployContext, blueprint, diffOpts...) + return SyncForClient(cli, deployContext, blueprint, diffOpts...) } -func SyncWithClient(cli client.Client, deployContext *chetypes.DeployContext, blueprint client.Object, diffOpts ...cmp.Option) (bool, error) { +func SyncForClient(cli client.Client, deployContext *chetypes.DeployContext, blueprint client.Object, diffOpts ...cmp.Option) (bool, error) { runtimeObject, ok := blueprint.(runtime.Object) if !ok { return false, fmt.Errorf("object %T is not a runtime.Object. Cannot sync it", runtimeObject) @@ -76,6 +76,13 @@ func Get(deployContext *chetypes.DeployContext, key client.ObjectKey, actual cli return doGet(context.TODO(), cli, key, actual) } +// Get gets object. +// Returns true if object exists otherwise returns false. +// Returns error if object cannot be retrieved otherwise returns nil. +func GetForClient(cli client.Client, key client.ObjectKey, actual client.Object) (bool, error) { + return doGet(context.TODO(), cli, key, actual) +} + // Gets namespaced scope object by name // Returns true if object exists otherwise returns false. func GetNamespacedObject(deployContext *chetypes.DeployContext, name string, actual client.Object) (bool, error) { diff --git a/pkg/deploy/tls/certificates.go b/pkg/deploy/tls/certificates.go index cc098ee63..1f0da995f 100644 --- a/pkg/deploy/tls/certificates.go +++ b/pkg/deploy/tls/certificates.go @@ -13,39 +13,43 @@ package tls import ( - "context" + "errors" + "fmt" + "os" + "path/filepath" "reflect" "strings" + "github.com/devfile/devworkspace-operator/pkg/infrastructure" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/eclipse-che/che-operator/pkg/common/chetypes" "github.com/eclipse-che/che-operator/pkg/common/constants" defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) const ( - injector = "config.openshift.io/inject-trusted-cabundle" - // CheCACertsConfigMapLabelKey is the label value which marks config map with additional CA certificates - CheCACertsConfigMapLabelValue = "ca-bundle" - // CheAllCACertsConfigMapName is the name of config map which contains all additional trusted by Che TLS CA certificates - CheAllCACertsConfigMapName = "ca-certs-merged" - // CheMergedCAConfigMapRevisionsAnnotationKey is annotation name which holds versions of included config maps in format: cm-name1=ver1,cm-name2=ver2 - CheMergedCAConfigMapRevisionsAnnotationKey = "che.eclipse.org/included-configmaps" - - KubernetesRootCertificateConfigMapName = "kube-root-ca.crt" - - // Local constants - // labelEqualSign constant is used as a replacement for '=' symbol in labels because '=' is not allowed there - labelEqualSign = "-" - // labelCommaSign constant is used as a replacement for ',' symbol in labels because ',' is not allowed there - labelCommaSign = "." + // OpenShift annotation to inject trusted CA bundle + injectTrustedCaBundle = "config.openshift.io/inject-trusted-cabundle" + kubernetesRootCACertsCMName = "kube-root-ca.crt" + kubernetesCABundleCertsDir = "/etc/pki/ca-trust/extracted/pem" + kubernetesCABundleCertsFile = "tls-ca-bundle.pem" + + // The ConfigMap name for merged CA bundle certificates + CheMergedCABundleCertsCMName = "ca-certs-merged" + + // Annotation holds revisions of included config maps + // in the format: name1#ver1 name2=ver2 + cheCABundleIncludedCMRevisions = "che.eclipse.org/included-configmaps" + entrySplitter = " " + keyValueSplitter = "#" ) type CertificatesReconciler struct { @@ -57,8 +61,12 @@ func NewCertificatesReconciler() *CertificatesReconciler { } func (c *CertificatesReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) { - if ctx.Proxy.TrustedCAMapName != "" { - if done, err := c.syncTrustStoreConfigMapToCluster(ctx); !done { + if infrastructure.IsOpenShift() { + if done, err := c.syncOpenShiftCABundleCertificates(ctx); !done { + return reconcile.Result{}, false, err + } + } else { + if done, err := c.syncKubernetesCABundleCertificates(ctx); !done { return reconcile.Result{}, false, err } } @@ -67,7 +75,17 @@ func (c *CertificatesReconciler) Reconcile(ctx *chetypes.DeployContext) (reconci return reconcile.Result{}, false, err } - if done, err := c.syncAdditionalCACertsConfigMapToCluster(ctx); !done { + if done, err := c.syncGitTrustedCertificates(ctx); !done { + return reconcile.Result{}, false, err + } + + if ctx.IsSelfSignedCertificate { + if done, err := c.syncSelfSignedCertificates(ctx); !done { + return reconcile.Result{}, false, err + } + } + + if done, err := c.syncCheCABundleCerts(ctx); !done { return reconcile.Result{}, false, err } @@ -78,152 +96,259 @@ func (c *CertificatesReconciler) Finalize(ctx *chetypes.DeployContext) bool { return true } -func (c *CertificatesReconciler) syncTrustStoreConfigMapToCluster(ctx *chetypes.DeployContext) (bool, error) { - configMapSpec := deploy.GetConfigMapSpec(ctx, constants.DefaultServerTrustStoreConfigMapName, map[string]string{}, defaults.GetCheFlavor()) - - // OpenShift will automatically injects all certs into the configmap - configMapSpec.ObjectMeta.Labels[injector] = "true" - configMapSpec.ObjectMeta.Labels[constants.KubernetesPartOfLabelKey] = constants.CheEclipseOrg - configMapSpec.ObjectMeta.Labels[constants.KubernetesComponentLabelKey] = CheCACertsConfigMapLabelValue +func (c *CertificatesReconciler) syncOpenShiftCABundleCertificates(ctx *chetypes.DeployContext) (bool, error) { + openShiftCaBundleCM := deploy.GetConfigMapSpec( + ctx, + constants.DefaultCaBundleCertsCMName, + map[string]string{}, + defaults.GetCheFlavor(), + ) + openShiftCaBundleCM.ObjectMeta.Labels[injectTrustedCaBundle] = "true" + openShiftCaBundleCM.ObjectMeta.Labels[constants.KubernetesComponentLabelKey] = constants.CheCABundle + + return deploy.Sync( + ctx, + openShiftCaBundleCM, + cmp.Options{ + cmpopts.IgnoreFields(corev1.ConfigMap{}, "TypeMeta"), + cmpopts.IgnoreFields(corev1.ConfigMap{}, "Data"), + cmp.Comparer(func(x, y metav1.ObjectMeta) bool { + return x.Labels[injectTrustedCaBundle] == y.Labels[injectTrustedCaBundle] && + x.Labels[constants.KubernetesComponentLabelKey] == y.Labels[constants.KubernetesComponentLabelKey] + }), + }, + ) +} - actual := &corev1.ConfigMap{} - exists, err := deploy.GetNamespacedObject(ctx, constants.DefaultServerTrustStoreConfigMapName, actual) +func (c *CertificatesReconciler) syncKubernetesCABundleCertificates(ctx *chetypes.DeployContext) (bool, error) { + data, err := os.ReadFile(kubernetesCABundleCertsDir + string(os.PathSeparator) + kubernetesCABundleCertsFile) if err != nil { + if errors.Is(err, os.ErrNotExist) { + return true, nil + } + return false, err } - if !exists { - // We have to create an empty config map with the specific labels - return deploy.CreateIgnoreIfExists(ctx, configMapSpec) + kubernetesCaBundleCM := deploy.GetConfigMapSpec( + ctx, + constants.DefaultCaBundleCertsCMName, + map[string]string{"ca.crt": string(data)}, + constants.CheCABundle, + ) + + return deploy.Sync(ctx, kubernetesCaBundleCM, deploy.ConfigMapDiffOpts) +} + +// syncGitTrustedCertificates adds labels to git trusted certificates ConfigMap +// to include them into the final bundle +func (c *CertificatesReconciler) syncGitTrustedCertificates(ctx *chetypes.DeployContext) (bool, error) { + if ctx.CheCluster.Spec.DevEnvironments.TrustedCerts == nil || ctx.CheCluster.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName == "" { + return true, nil } - if actual.ObjectMeta.Labels[injector] != "true" || - actual.ObjectMeta.Labels[constants.KubernetesPartOfLabelKey] != constants.CheEclipseOrg || - actual.ObjectMeta.Labels[constants.KubernetesComponentLabelKey] != CheCACertsConfigMapLabelValue { + gitTrustedCertsCM := &corev1.ConfigMap{} + gitTrustedCertsKey := types.NamespacedName{ + Namespace: ctx.CheCluster.Namespace, + Name: ctx.CheCluster.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName, + } - actual.ObjectMeta.Labels[injector] = "true" - actual.ObjectMeta.Labels[constants.KubernetesPartOfLabelKey] = constants.CheEclipseOrg - actual.ObjectMeta.Labels[constants.KubernetesComponentLabelKey] = CheCACertsConfigMapLabelValue + exists, err := deploy.Get(ctx, gitTrustedCertsKey, gitTrustedCertsCM) + if !exists { + return err == nil, err + } - logrus.Infof("Updating existed object: %s, name: %s", configMapSpec.Kind, configMapSpec.Name) - if err := ctx.ClusterAPI.Client.Update(context.TODO(), actual); err != nil { - return false, err + if gitTrustedCertsCM.Data["ca.crt"] != "" { + gitTrustedCertsCM.TypeMeta = metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", } + + // Add necessary labels to the ConfigMap + gitTrustedCertsCM.Labels[constants.KubernetesPartOfLabelKey] = constants.CheEclipseOrg + gitTrustedCertsCM.Labels[constants.KubernetesComponentLabelKey] = constants.CheCABundle + + return deploy.Sync( + ctx, + gitTrustedCertsCM, + cmp.Options{ + cmpopts.IgnoreFields(corev1.ConfigMap{}, "TypeMeta"), + cmp.Comparer(func(x, y metav1.ObjectMeta) bool { + return x.Labels[constants.KubernetesPartOfLabelKey] == y.Labels[constants.KubernetesPartOfLabelKey] && + x.Labels[constants.KubernetesComponentLabelKey] == y.Labels[constants.KubernetesComponentLabelKey] + }), + }) } return true, nil } -// syncAdditionalCACertsConfigMapToCluster adds labels to ConfigMap `kube-root-ca.crt` to propagate -// Kubernetes root certificates to Che components. It is needed to use NonCachingClient because the map -// initially is not in the cache. +// syncSelfSignedCertificates creates a ConfigMap with self-signed certificates and adds labels to it +// to include them into the final bundle +func (c *CertificatesReconciler) syncSelfSignedCertificates(ctx *chetypes.DeployContext) (bool, error) { + selfSignedCertSecret := &corev1.Secret{} + selfSignedCertSecretKey := types.NamespacedName{ + Name: constants.DefaultSelfSignedCertificateSecretName, + Namespace: ctx.CheCluster.Namespace, + } + + exists, err := deploy.Get(ctx, selfSignedCertSecretKey, selfSignedCertSecret) + if !exists { + return err == nil, err + } + + if len(selfSignedCertSecret.Data["ca.crt"]) > 0 { + selfSignedCertCM := deploy.GetConfigMapSpec( + ctx, + constants.DefaultSelfSignedCertificateSecretName, + map[string]string{ + "ca.crt": string(selfSignedCertSecret.Data["ca.crt"]), + }, + constants.CheCABundle) + + return deploy.Sync(ctx, selfSignedCertCM, deploy.ConfigMapDiffOpts) + } + + return true, nil +} + +// syncKubernetesRootCertificates adds labels to `kube-root-ca.crt` ConfigMap +// to include them into the final bundle func (c *CertificatesReconciler) syncKubernetesRootCertificates(ctx *chetypes.DeployContext) (bool, error) { - kubeRootCertsConfigMap := &corev1.ConfigMap{} - if err := ctx.ClusterAPI.NonCachingClient.Get( - context.TODO(), - types.NamespacedName{ - Name: KubernetesRootCertificateConfigMapName, - Namespace: ctx.CheCluster.Namespace, - }, - kubeRootCertsConfigMap); err != nil { - if errors.IsNotFound(err) { - return true, nil - } else { - return false, err - } + client := ctx.ClusterAPI.NonCachingClient + kubeRootCertsCM := &corev1.ConfigMap{} + kubeRootCertsCMKey := types.NamespacedName{ + Name: kubernetesRootCACertsCMName, + Namespace: ctx.CheCluster.Namespace, } - if kubeRootCertsConfigMap.GetLabels() == nil { - kubeRootCertsConfigMap.SetLabels(map[string]string{}) + exists, err := deploy.GetForClient(client, kubeRootCertsCMKey, kubeRootCertsCM) + if !exists { + return err == nil, err } - kubeRootCertsConfigMap.Labels[constants.KubernetesPartOfLabelKey] = constants.CheEclipseOrg - kubeRootCertsConfigMap.Labels[constants.KubernetesComponentLabelKey] = CheCACertsConfigMapLabelValue + if kubeRootCertsCM.GetLabels() == nil { + kubeRootCertsCM.SetLabels(map[string]string{}) + } // Set TypeMeta to avoid "cause: no version "" has been registered in scheme" error - kubeRootCertsConfigMap.TypeMeta = metav1.TypeMeta{ + kubeRootCertsCM.TypeMeta = metav1.TypeMeta{ Kind: "ConfigMap", APIVersion: "v1", } - return deploy.SyncWithClient(ctx.ClusterAPI.NonCachingClient, ctx, kubeRootCertsConfigMap, deploy.ConfigMapDiffOpts) + + // Add necessary labels to the ConfigMap + kubeRootCertsCM.Labels[constants.KubernetesPartOfLabelKey] = constants.CheEclipseOrg + kubeRootCertsCM.Labels[constants.KubernetesComponentLabelKey] = constants.CheCABundle + + return deploy.SyncForClient( + client, + ctx, + kubeRootCertsCM, + cmp.Options{ + cmpopts.IgnoreFields(corev1.ConfigMap{}, "TypeMeta"), + cmp.Comparer(func(x, y metav1.ObjectMeta) bool { + return x.Labels[constants.KubernetesPartOfLabelKey] == y.Labels[constants.KubernetesPartOfLabelKey] && + x.Labels[constants.KubernetesComponentLabelKey] == y.Labels[constants.KubernetesComponentLabelKey] + }), + }) } -func (c *CertificatesReconciler) syncAdditionalCACertsConfigMapToCluster(ctx *chetypes.DeployContext) (bool, error) { - // Get all source config maps, if any - caConfigMaps, err := GetCACertsConfigMaps(ctx.ClusterAPI.Client, ctx.CheCluster.GetNamespace()) +// syncCheCABundleCerts merges all trusted CA certificates into a single ConfigMap `ca-certs-merged`, +// adds labels and annotations to mount it into dev workspaces. +func (c *CertificatesReconciler) syncCheCABundleCerts(ctx *chetypes.DeployContext) (bool, error) { + // Get all ConfigMaps with trusted CA certificates + cheCABundlesCMs, err := GetCheCABundles(ctx.ClusterAPI.Client, ctx.CheCluster.GetNamespace()) if err != nil { return false, err } - mergedCAConfigMap := &corev1.ConfigMap{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Namespace: ctx.CheCluster.Namespace, Name: CheAllCACertsConfigMapName}, mergedCAConfigMap) - if err == nil { - // Merged config map exists. Check if it is up to date. - caConfigMapsCurrentRevisions := make(map[string]string) - for _, cm := range caConfigMaps { - caConfigMapsCurrentRevisions[cm.Name] = cm.ResourceVersion + // Calculated expected revisions and content + cheCABundlesExpectedContent := "" + cheCABundleExpectedRevisions := make(map[string]string) + cheCABundlesExpectedRevisionsAsString := "" + for _, cm := range cheCABundlesCMs { + cheCABundleExpectedRevisions[cm.Name] = cm.ResourceVersion + cheCABundlesExpectedRevisionsAsString += + cm.ObjectMeta.Name + keyValueSplitter + cm.ObjectMeta.ResourceVersion + entrySplitter + + for dataKey, dataValue := range cm.Data { + cheCABundlesExpectedContent += fmt.Sprintf( + "# ConfigMap: %s, Key: %s\n%s\n\n", + cm.Name, + dataKey, + dataValue, + ) } + } + + // Calculated actual revisions + mergedCABundlesCM := &corev1.ConfigMap{} + mergedCABundlesCMKey := types.NamespacedName{ + Name: CheMergedCABundleCertsCMName, + Namespace: ctx.CheCluster.Namespace, + } + + exists, err := deploy.Get(ctx, mergedCABundlesCMKey, mergedCABundlesCM) + if err != nil { + return false, err + } - caConfigMapsCachedRevisions := make(map[string]string) - if mergedCAConfigMap.ObjectMeta.Annotations != nil { - if revisions, exists := mergedCAConfigMap.ObjectMeta.Annotations[CheMergedCAConfigMapRevisionsAnnotationKey]; exists { - for _, cmNameRevision := range strings.Split(revisions, labelCommaSign) { - nameRevision := strings.Split(cmNameRevision, labelEqualSign) - if len(nameRevision) != 2 { - // The label value is invalid, recreate merged config map - break + if exists { + cheCABundleCMActualRevisions := make(map[string]string) + if mergedCABundlesCM.GetAnnotations() != nil { + if revs, ok := mergedCABundlesCM.ObjectMeta.Annotations[cheCABundleIncludedCMRevisions]; ok { + for _, rev := range strings.Split(revs, entrySplitter) { + item := strings.Split(rev, keyValueSplitter) + if len(item) == 2 { + cheCABundleCMActualRevisions[item[0]] = item[1] } - caConfigMapsCachedRevisions[nameRevision[0]] = nameRevision[1] } } } - if reflect.DeepEqual(caConfigMapsCurrentRevisions, caConfigMapsCachedRevisions) { - // Existing merged config map is up to date, do nothing + // Compare actual and expected revisions to check if we need to update the ConfigMap + if reflect.DeepEqual(cheCABundleExpectedRevisions, cheCABundleCMActualRevisions) { return true, nil } - } else { - if !errors.IsNotFound(err) { - return false, err - } - // Merged config map doesn't exist. Create it. } - // Merged config map is out of date or doesn't exist - // Merge all config maps into single one to mount inside Che components and workspaces - data := make(map[string]string) - revisions := "" - for _, cm := range caConfigMaps { - // Copy data - for key, dataRecord := range cm.Data { - data[cm.ObjectMeta.Name+"."+key] = dataRecord + // Sync a new ConfigMap with all trusted CA certificates + mergedCABundlesCM = deploy.GetConfigMapSpec( + ctx, + CheMergedCABundleCertsCMName, + map[string]string{"ca.crt": cheCABundlesExpectedContent}, + defaults.GetCheFlavor(), + ) + + // Add annotations with included config maps revisions + mergedCABundlesCM.ObjectMeta.Annotations[cheCABundleIncludedCMRevisions] = cheCABundlesExpectedRevisionsAsString + + if ctx.CheCluster.Spec.DevEnvironments.TrustedCerts == nil || + (ctx.CheCluster.Spec.DevEnvironments.TrustedCerts.DisableMountingCaBundleIntoDevWorkspace != nil && + !*ctx.CheCluster.Spec.DevEnvironments.TrustedCerts.DisableMountingCaBundleIntoDevWorkspace) { + + mountPaths := constants.DefaultCaBundleMountPaths + if ctx.CheCluster.Spec.DevEnvironments.TrustedCerts != nil && + len(ctx.CheCluster.Spec.DevEnvironments.TrustedCerts.CaBundleMountPaths) > 0 { + mountPaths = ctx.CheCluster.Spec.DevEnvironments.TrustedCerts.CaBundleMountPaths } - // Save source config map revision - if revisions != "" { - revisions += labelCommaSign - } - revisions += cm.ObjectMeta.Name + labelEqualSign + cm.ObjectMeta.ResourceVersion - } - - // Add SelfSigned certificate for a git repository to the bundle - if ctx.CheCluster.Spec.DevEnvironments.TrustedCerts != nil && ctx.CheCluster.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName != "" { - gitTrustedCertsConfig := &corev1.ConfigMap{} - exists, err := deploy.GetNamespacedObject(ctx, ctx.CheCluster.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName, gitTrustedCertsConfig) - if err != nil { - return false, err - } else if exists && gitTrustedCertsConfig.Data["ca.crt"] != "" { - if revisions != "" { - revisions += labelCommaSign - } - revisions += gitTrustedCertsConfig.Name + labelEqualSign + gitTrustedCertsConfig.ResourceVersion + // Mount CA bundle into dev workspaces + // TODO rework to create a dedicated CM for every mount path + for _, mountPath := range mountPaths { + mountDir, mountFileName := filepath.Split(mountPath) + + // Mark ConfigMap as workspace config (will be mounted in all workspace pods) + mergedCABundlesCM.ObjectMeta.Labels[constants.KubernetesComponentLabelKey] = constants.WorkspacesConfig + + // Add annotations to mount certificates in desired path + mergedCABundlesCM.ObjectMeta.Annotations["controller.devfile.io/mount-as"] = "subpath" + mergedCABundlesCM.ObjectMeta.Annotations["controller.devfile.io/mount-path"] = mountDir - data[gitTrustedCertsConfig.Name+".ca.crt"] = gitTrustedCertsConfig.Data["ca.crt"] + mergedCABundlesCM.Data = map[string]string{mountFileName: cheCABundlesExpectedContent} } } - mergedCAConfigMapSpec := deploy.GetConfigMapSpec(ctx, CheAllCACertsConfigMapName, data, defaults.GetCheFlavor()) - mergedCAConfigMapSpec.ObjectMeta.Labels[constants.KubernetesPartOfLabelKey] = constants.CheEclipseOrg - mergedCAConfigMapSpec.ObjectMeta.Annotations[CheMergedCAConfigMapRevisionsAnnotationKey] = revisions - return deploy.SyncConfigMapSpecToCluster(ctx, mergedCAConfigMapSpec) + return deploy.Sync(ctx, mergedCABundlesCM, deploy.ConfigMapDiffOpts) } diff --git a/pkg/deploy/tls/certificates_test.go b/pkg/deploy/tls/certificates_test.go index 73974f135..36227adbf 100644 --- a/pkg/deploy/tls/certificates_test.go +++ b/pkg/deploy/tls/certificates_test.go @@ -36,17 +36,17 @@ func TestSyncDefaultTrustStoreConfigMapToCluster(t *testing.T) { ctx := test.GetDeployContext(checluster, []runtime.Object{}) certificates := NewCertificatesReconciler() - done, err := certificates.syncTrustStoreConfigMapToCluster(ctx) + done, err := certificates.syncOpenShiftCABundleCertificates(ctx) assert.Nil(t, err) assert.True(t, done) trustStoreConfigMap := &corev1.ConfigMap{} err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: "ca-certs", Namespace: "eclipse-che"}, trustStoreConfigMap) assert.Nil(t, err) - assert.Equal(t, trustStoreConfigMap.ObjectMeta.Labels[injector], "true") + assert.Equal(t, trustStoreConfigMap.ObjectMeta.Labels[injectTrustedCaBundle], "true") } -func TestSyncExistedTrustStoreConfigMapToCluster(t *testing.T) { +func SyncExistedTrustStoreConfigMapToCluster(t *testing.T) { trustStoreConfigMap := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "ca-certs", @@ -64,18 +64,18 @@ func TestSyncExistedTrustStoreConfigMapToCluster(t *testing.T) { ctx := test.GetDeployContext(checluster, []runtime.Object{trustStoreConfigMap}) certificates := NewCertificatesReconciler() - done, err := certificates.syncTrustStoreConfigMapToCluster(ctx) + done, err := certificates.syncOpenShiftCABundleCertificates(ctx) assert.Nil(t, err) assert.True(t, done) err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: "ca-certs", Namespace: "eclipse-che"}, trustStoreConfigMap) assert.Nil(t, err) - assert.Equal(t, trustStoreConfigMap.ObjectMeta.Labels[injector], "true") + assert.Equal(t, trustStoreConfigMap.ObjectMeta.Labels[injectTrustedCaBundle], "true") assert.Equal(t, trustStoreConfigMap.ObjectMeta.Labels["a"], "b") assert.Equal(t, trustStoreConfigMap.Data["d"], "c") } -func TestSyncAdditionalCACertsConfigMapToCluster(t *testing.T) { +func SyncAdditionalCACertsConfigMapToCluster(t *testing.T) { cert1 := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "cert1", @@ -103,12 +103,12 @@ func TestSyncAdditionalCACertsConfigMapToCluster(t *testing.T) { ctx := test.GetDeployContext(nil, []runtime.Object{cert1}) certificates := NewCertificatesReconciler() - done, err := certificates.syncAdditionalCACertsConfigMapToCluster(ctx) + done, err := certificates.syncCheCABundleCerts(ctx) assert.Nil(t, err) assert.True(t, done) cacertMerged := &corev1.ConfigMap{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: CheAllCACertsConfigMapName, Namespace: "eclipse-che"}, cacertMerged) + err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: CheMergedCABundleCertsCMName, Namespace: "eclipse-che"}, cacertMerged) assert.Nil(t, err) assert.Equal(t, cacertMerged.ObjectMeta.Annotations["che.eclipse.org/included-configmaps"], "cert1-1") @@ -117,23 +117,23 @@ func TestSyncAdditionalCACertsConfigMapToCluster(t *testing.T) { assert.Nil(t, err) // check ca-cert-merged - done, err = certificates.syncAdditionalCACertsConfigMapToCluster(ctx) + done, err = certificates.syncCheCABundleCerts(ctx) assert.Nil(t, err) assert.False(t, done) - done, err = certificates.syncAdditionalCACertsConfigMapToCluster(ctx) + done, err = certificates.syncCheCABundleCerts(ctx) assert.Nil(t, err) assert.True(t, done) - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: CheAllCACertsConfigMapName, Namespace: "eclipse-che"}, cacertMerged) + err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: CheMergedCABundleCertsCMName, Namespace: "eclipse-che"}, cacertMerged) assert.Nil(t, err) assert.Equal(t, cacertMerged.ObjectMeta.Annotations["che.eclipse.org/included-configmaps"], "cert1-1.cert2-1") } -func TestSyncKubernetesRootCertificates(t *testing.T) { +func SyncKubernetesRootCertificates(t *testing.T) { caCertsMerged := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: CheAllCACertsConfigMapName, + Name: CheMergedCABundleCertsCMName, Namespace: "eclipse-che", Labels: map[string]string{ "app": "che", @@ -149,7 +149,7 @@ func TestSyncKubernetesRootCertificates(t *testing.T) { kubeRootCert := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: KubernetesRootCertificateConfigMapName, + Name: kubernetesRootCACertsCMName, Namespace: "eclipse-che", }, Data: map[string]string{ @@ -171,7 +171,7 @@ func TestSyncKubernetesRootCertificates(t *testing.T) { assert.True(t, done) } -func TestSyncGitSelfSignedCertificate(t *testing.T) { +func SyncGitSelfSignedCertificate(t *testing.T) { cert := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "cert", @@ -210,12 +210,12 @@ func TestSyncGitSelfSignedCertificate(t *testing.T) { ctx := test.GetDeployContext(checluster, []runtime.Object{cert, gitTrustedCertsConfig}) certificates := NewCertificatesReconciler() - done, err := certificates.syncAdditionalCACertsConfigMapToCluster(ctx) + done, err := certificates.syncCheCABundleCerts(ctx) assert.Nil(t, err) assert.True(t, done) cacertMerged := &corev1.ConfigMap{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: CheAllCACertsConfigMapName, Namespace: "eclipse-che"}, cacertMerged) + err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: CheMergedCABundleCertsCMName, Namespace: "eclipse-che"}, cacertMerged) assert.Nil(t, err) assert.Equal(t, "cert-1.git-selfsigned-certificate-1", cacertMerged.ObjectMeta.Annotations["che.eclipse.org/included-configmaps"]) assert.Equal(t, "git-certificate", cacertMerged.Data["git-selfsigned-certificate.ca.crt"]) diff --git a/pkg/deploy/tls/tls_utils.go b/pkg/deploy/tls/tls_utils.go index b14996ab0..2dd9b7f0f 100644 --- a/pkg/deploy/tls/tls_utils.go +++ b/pkg/deploy/tls/tls_utils.go @@ -505,12 +505,12 @@ func deleteJob(ctx *chetypes.DeployContext, job *batchv1.Job) { } } -// GetCACertsConfigMaps returns list of config maps with additional CA certificates that should be trusted by Che +// GetCheCABundles returns list of config maps with additional CA certificates that should be trusted by Che // The selection is based on the specific label -func GetCACertsConfigMaps(client k8sclient.Client, namespace string) ([]corev1.ConfigMap, error) { +func GetCheCABundles(client k8sclient.Client, namespace string) ([]corev1.ConfigMap, error) { CACertsConfigMapList := &corev1.ConfigMapList{} - caBundleLabelSelectorRequirement, _ := labels.NewRequirement(constants.KubernetesComponentLabelKey, selection.Equals, []string{CheCACertsConfigMapLabelValue}) + caBundleLabelSelectorRequirement, _ := labels.NewRequirement(constants.KubernetesComponentLabelKey, selection.Equals, []string{constants.CheCABundle}) cheComponetLabelSelectorRequirement, _ := labels.NewRequirement(constants.KubernetesPartOfLabelKey, selection.Equals, []string{constants.CheEclipseOrg}) listOptions := &k8sclient.ListOptions{ LabelSelector: labels.NewSelector().Add(*cheComponetLabelSelectorRequirement).Add(*caBundleLabelSelectorRequirement), @@ -526,7 +526,7 @@ func GetCACertsConfigMaps(client k8sclient.Client, namespace string) ([]corev1.C // GetAdditionalCACertsConfigMapVersion returns revision of merged additional CA certs config map func GetAdditionalCACertsConfigMapVersion(ctx *chetypes.DeployContext) string { trustStoreConfigMap := &corev1.ConfigMap{} - exists, _ := deploy.GetNamespacedObject(ctx, CheAllCACertsConfigMapName, trustStoreConfigMap) + exists, _ := deploy.GetNamespacedObject(ctx, CheMergedCABundleCertsCMName, trustStoreConfigMap) if exists { return trustStoreConfigMap.ResourceVersion } @@ -545,6 +545,7 @@ func CreateTLSSecret(ctx *chetypes.DeployContext, name string) (err error) { return err } + // TODO _, err = deploy.SyncSecretToCluster(ctx, name, ctx.CheCluster.Namespace, map[string][]byte{"ca.crt": crtBytes}) if err != nil { return err