This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 69e73491e9a2d8bca7ed55673eb48bd9d11afd92
Author: Antonin Stefanutti <anto...@stefanutti.fr>
AuthorDate: Mon Feb 24 16:21:32 2020 +0100

    feat(buildah): Auto-configure OpenShift internal registry certificate 
authority
---
 pkg/apis/camel/v1/integrationplatform_types.go |  1 +
 pkg/platform/defaults.go                       | 26 ++++++++
 pkg/trait/builder.go                           | 84 +++++++++++++++++++++++---
 3 files changed, 104 insertions(+), 7 deletions(-)

diff --git a/pkg/apis/camel/v1/integrationplatform_types.go 
b/pkg/apis/camel/v1/integrationplatform_types.go
index ff9afbb..ad00423 100644
--- a/pkg/apis/camel/v1/integrationplatform_types.go
+++ b/pkg/apis/camel/v1/integrationplatform_types.go
@@ -121,6 +121,7 @@ type IntegrationPlatformRegistrySpec struct {
        Insecure     bool   `json:"insecure,omitempty"`
        Address      string `json:"address,omitempty"`
        Secret       string `json:"secret,omitempty"`
+       CA           string `json:"ca,omitempty"`
        Organization string `json:"organization,omitempty"`
 }
 
diff --git a/pkg/platform/defaults.go b/pkg/platform/defaults.go
index caffed1..e04d3ef 100644
--- a/pkg/platform/defaults.go
+++ b/pkg/platform/defaults.go
@@ -90,6 +90,13 @@ func ConfigureDefaults(ctx context.Context, c client.Client, 
p *v1.IntegrationPl
                p.Status.Build.Registry.Address == "" {
                p.Status.Build.Registry.Address = 
"image-registry.openshift-image-registry.svc:5000"
 
+               // OpenShift automatically injects the service CA certificate 
into the service-ca.crt key on the ConfigMap
+               cm, err := createServiceCaBundleConfigMap(ctx, c, p)
+               if err != nil {
+                       return err
+               }
+               p.Status.Build.Registry.CA = cm.Name
+
                // Default to using the registry secret that's configured for 
the builder service account
                if p.Status.Build.Registry.Secret == "" {
                        sa := corev1.ServiceAccount{}
@@ -229,3 +236,22 @@ func createDefaultMavenSettingsConfigMap(ctx 
context.Context, client client.Clie
 
        return nil
 }
+
+func createServiceCaBundleConfigMap(ctx context.Context, client client.Client, 
p *v1.IntegrationPlatform) (*corev1.ConfigMap, error) {
+       cm := &corev1.ConfigMap{
+               ObjectMeta: metav1.ObjectMeta{
+                       Name:      "camel-k-builder-ca",
+                       Namespace: p.Namespace,
+                       Annotations: map[string]string{
+                               "service.beta.openshift.io/inject-cabundle": 
"true",
+                       },
+               },
+       }
+
+       err := client.Create(ctx, cm)
+       if err != nil && !k8serrors.IsAlreadyExists(err) {
+               return nil, err
+       }
+
+       return cm, nil
+}
diff --git a/pkg/trait/builder.go b/pkg/trait/builder.go
index 1a49ee6..72919c8 100644
--- a/pkg/trait/builder.go
+++ b/pkg/trait/builder.go
@@ -211,6 +211,8 @@ func (t *builderTrait) builderTask(e *Environment) 
*v1.BuilderTask {
 func (t *builderTrait) buildahTask(e *Environment) (*v1.ImageTask, error) {
        image := getImageName(e)
 
+       auth := []string{""}
+
        bud := []string{
                "buildah",
                "bud",
@@ -236,15 +238,22 @@ func (t *builderTrait) buildahTask(e *Environment) 
(*v1.ImageTask, error) {
                push = append(push[:2], append([]string{"--log-level=debug"}, 
push[2:]...)...)
        }
 
-       args := []string{
-               strings.Join(bud, " "),
-               strings.Join(push, " "),
-       }
-
        env := make([]corev1.EnvVar, 0)
        volumes := make([]corev1.Volume, 0)
        volumeMounts := make([]corev1.VolumeMount, 0)
 
+       if e.Platform.Status.Build.Registry.CA != "" {
+               config, err := getRegistryConfigMapFor(e, 
buildahRegistryConfigMaps)
+               if err != nil {
+                       return nil, err
+               }
+               mountRegistryConfigMap(e.Platform.Status.Build.Registry.CA, 
config, &volumes, &volumeMounts)
+               // This is easier to use the --cert-dir option, otherwise 
Buildah defaults to looking up certificates
+               //into a directory named after the registry address
+               bud = append(bud[:2], 
append([]string{"--cert-dir=/etc/containers/certs.d"}, bud[2:]...)...)
+               push = append(push[:2], 
append([]string{"--cert-dir=/etc/containers/certs.d"}, push[2:]...)...)
+       }
+
        if e.Platform.Status.Build.Registry.Secret != "" {
                secret, err := getRegistrySecretFor(e, buildahRegistrySecrets)
                if err != nil {
@@ -252,10 +261,9 @@ func (t *builderTrait) buildahTask(e *Environment) 
(*v1.ImageTask, error) {
                }
                if secret == plainDockerBuildahRegistrySecret {
                        // Handle old format and make it compatible with Buildah
-                       auth := []string{
+                       auth = []string{
                                "(echo '{ \"auths\": ' ; cat 
/buildah/.docker/config.json ; echo \"}\") > /tmp/.dockercfg",
                        }
-                       args = append([]string{strings.Join(auth, " ")}, 
args...)
                        env = append(env, corev1.EnvVar{
                                Name:  "REGISTRY_AUTH_FILE",
                                Value: "/tmp/.dockercfg",
@@ -269,6 +277,12 @@ func (t *builderTrait) buildahTask(e *Environment) 
(*v1.ImageTask, error) {
 
        env = append(env, proxySecretEnvVars(e)...)
 
+       args := []string{
+               strings.Join(auth, " "),
+               strings.Join(bud, " "),
+               strings.Join(push, " "),
+       }
+
        return &v1.ImageTask{
                ContainerTask: v1.ContainerTask{
                        BaseTask: v1.BaseTask{
@@ -384,6 +398,24 @@ var (
        }
 )
 
+type registryConfigMap struct {
+       fileName    string
+       mountPath   string
+       destination string
+}
+
+var (
+       serviceCABuildahRegistryConfigMap = registryConfigMap{
+               fileName:    "service-ca.crt",
+               mountPath:   "/etc/containers/certs.d",
+               destination: "service-ca.crt",
+       }
+
+       buildahRegistryConfigMaps = []registryConfigMap{
+               serviceCABuildahRegistryConfigMap,
+       }
+)
+
 func proxySecretEnvVars(e *Environment) []corev1.EnvVar {
        if e.Platform.Status.Build.HTTPProxySecret == "" {
                return []corev1.EnvVar{}
@@ -455,6 +487,44 @@ func mountRegistrySecret(name string, secret 
registrySecret, volumes *[]corev1.V
        }
 }
 
+func getRegistryConfigMapFor(e *Environment, registryConfigMaps 
[]registryConfigMap) (registryConfigMap, error) {
+       config := corev1.ConfigMap{}
+       err := e.Client.Get(e.C, client.ObjectKey{Namespace: 
e.Platform.Namespace, Name: e.Platform.Status.Build.Registry.CA}, &config)
+       if err != nil {
+               return registryConfigMap{}, err
+       }
+       for _, k := range registryConfigMaps {
+               if _, ok := config.Data[k.fileName]; ok {
+                       return k, nil
+               }
+       }
+       return registryConfigMap{}, errors.New("unsupported registry config 
map")
+}
+
+func mountRegistryConfigMap(name string, config registryConfigMap, volumes 
*[]corev1.Volume, volumeMounts *[]corev1.VolumeMount) {
+       *volumes = append(*volumes, corev1.Volume{
+               Name: "registry-config",
+               VolumeSource: corev1.VolumeSource{
+                       ConfigMap: &corev1.ConfigMapVolumeSource{
+                               LocalObjectReference: 
corev1.LocalObjectReference{
+                                       Name: name,
+                               },
+                               Items: []corev1.KeyToPath{
+                                       {
+                                               Key:  config.fileName,
+                                               Path: config.destination,
+                                       },
+                               },
+                       },
+               },
+       })
+
+       *volumeMounts = append(*volumeMounts, corev1.VolumeMount{
+               Name:      "registry-config",
+               MountPath: config.mountPath,
+       })
+}
+
 func getImageName(e *Environment) string {
        organization := e.Platform.Status.Build.Registry.Organization
        if organization == "" {

Reply via email to