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 e913ccf5a26c783ca843f527240433c0c98043e9 Author: Antonin Stefanutti <anto...@stefanutti.fr> AuthorDate: Mon Mar 22 15:57:54 2021 +0100 feat(build): Add CA cert from user Secret into Maven build JVM trust store --- pkg/apis/camel/v1/common_types.go | 7 ++--- pkg/builder/project.go | 36 +++++++++++++++++++++++++- pkg/builder/quarkus.go | 4 +++ pkg/builder/types.go | 5 ++-- pkg/trait/quarkus_test.go | 2 +- pkg/util/kubernetes/core_client.go | 52 +++++++++++++++++++++++--------------- pkg/util/kubernetes/util.go | 2 -- pkg/util/maven/maven.go | 25 +++++++++++++++--- pkg/util/maven/maven_types.go | 11 ++++---- 9 files changed, 104 insertions(+), 40 deletions(-) diff --git a/pkg/apis/camel/v1/common_types.go b/pkg/apis/camel/v1/common_types.go index d772e77..ae0413b 100644 --- a/pkg/apis/camel/v1/common_types.go +++ b/pkg/apis/camel/v1/common_types.go @@ -83,9 +83,10 @@ type PlatformInjectable interface { // MavenSpec -- type MavenSpec struct { - LocalRepository string `json:"localRepository,omitempty"` - Settings ValueSource `json:"settings,omitempty"` - Timeout *metav1.Duration `json:"timeout,omitempty"` + LocalRepository string `json:"localRepository,omitempty"` + Settings ValueSource `json:"settings,omitempty"` + CaCert *corev1.SecretKeySelector `json:"caCert,omitempty"` + Timeout *metav1.Duration `json:"timeout,omitempty"` } // ValueSource -- diff --git a/pkg/builder/project.go b/pkg/builder/project.go index 1bd363f..27e20fe 100644 --- a/pkg/builder/project.go +++ b/pkg/builder/project.go @@ -18,19 +18,24 @@ limitations under the License. package builder import ( + "fmt" "os" + "os/exec" + "path" + "strings" + "github.com/apache/camel-k/pkg/util" "github.com/apache/camel-k/pkg/util/camel" "github.com/apache/camel-k/pkg/util/kubernetes" ) - func init() { registerSteps(Steps) } type steps struct { CleanUpBuildDir Step + GenerateJavaKeystore Step GenerateProjectSettings Step InjectDependencies Step SanitizeDependencies Step @@ -40,6 +45,7 @@ type steps struct { var Steps = steps{ CleanUpBuildDir: NewStep(ProjectGenerationPhase-1, cleanUpBuildDir), + GenerateJavaKeystore: NewStep(ProjectGenerationPhase, generateJavaKeystore), GenerateProjectSettings: NewStep(ProjectGenerationPhase+1, generateProjectSettings), InjectDependencies: NewStep(ProjectGenerationPhase+2, injectDependencies), SanitizeDependencies: NewStep(ProjectGenerationPhase+3, sanitizeDependencies), @@ -49,6 +55,7 @@ var Steps = steps{ var DefaultSteps = []Step{ Steps.CleanUpBuildDir, + Steps.GenerateJavaKeystore, Steps.GenerateProjectSettings, Steps.InjectDependencies, Steps.SanitizeDependencies, @@ -63,6 +70,33 @@ func cleanUpBuildDir(ctx *builderContext) error { return os.RemoveAll(ctx.Build.BuildDir) } +func generateJavaKeystore(ctx *builderContext) error { + if ctx.Build.Maven.CaCert == nil { + return nil + } + + certData, err := kubernetes.GetSecretRefData(ctx.C, ctx.Client, ctx.Namespace, ctx.Build.Maven.CaCert) + if err != nil { + return err + } + + certPath := ctx.Build.Maven.CaCert.Key + if err := util.WriteFileWithContent(ctx.Path, certPath, certData); err != nil { + return err + } + + keystore := "trust.jks" + ctx.Maven.TrustStorePath = path.Join(ctx.Path, keystore) + + args := strings.Fields(fmt.Sprintf("-importcert -alias maven -file %s -keystore %s", certPath, keystore)) + cmd := exec.CommandContext(ctx.C, "keytool", args...) + cmd.Dir = ctx.Path + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + + return cmd.Run() +} + func generateProjectSettings(ctx *builderContext) error { val, err := kubernetes.ResolveValueSource(ctx.C, ctx.Client, ctx.Namespace, &ctx.Build.Maven.Settings) if err != nil { diff --git a/pkg/builder/quarkus.go b/pkg/builder/quarkus.go index 23ef90a..028b919 100644 --- a/pkg/builder/quarkus.go +++ b/pkg/builder/quarkus.go @@ -147,6 +147,10 @@ func buildQuarkusRunner(ctx *builderContext) error { mc.LocalRepository = ctx.Build.Maven.LocalRepository mc.Timeout = ctx.Build.Maven.GetTimeout().Duration + if ctx.Maven.TrustStorePath != "" { + mc.ExtraMavenOpts = append(mc.ExtraMavenOpts, "-Djavax.net.ssl.trustStore="+path.Join(ctx.Path, ctx.Maven.TrustStorePath)) + } + err := BuildQuarkusRunnerCommon(mc) if err != nil { return err diff --git a/pkg/builder/types.go b/pkg/builder/types.go index 471ab88..776e8a0 100644 --- a/pkg/builder/types.go +++ b/pkg/builder/types.go @@ -88,7 +88,8 @@ type builderContext struct { SelectedArtifacts []v1.Artifact Resources []resource Maven struct { - Project maven.Project - SettingsData []byte + Project maven.Project + SettingsData []byte + TrustStorePath string } } diff --git a/pkg/trait/quarkus_test.go b/pkg/trait/quarkus_test.go index 9061f57..181ba78 100644 --- a/pkg/trait/quarkus_test.go +++ b/pkg/trait/quarkus_test.go @@ -62,7 +62,7 @@ func TestQuarkusTraitAddBuildStepsShouldSucceed(t *testing.T) { quarkusTrait.addBuildSteps(&steps) - assert.Len(t, steps, 9) + assert.Len(t, steps, len(builder.DefaultSteps)+len(builder.QuarkusSteps)) } func createNominalQuarkusTest() (*quarkusTrait, *Environment) { diff --git a/pkg/util/kubernetes/core_client.go b/pkg/util/kubernetes/core_client.go index 822b209..621a90f 100644 --- a/pkg/util/kubernetes/core_client.go +++ b/pkg/util/kubernetes/core_client.go @@ -23,15 +23,16 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - k8sclient "sigs.k8s.io/controller-runtime/pkg/client" + + ctrl "sigs.k8s.io/controller-runtime/pkg/client" v1 "github.com/apache/camel-k/pkg/apis/camel/v1" "github.com/apache/camel-k/pkg/client" ) // GetIntegrationPlatform -- -func GetIntegrationPlatform(context context.Context, client k8sclient.Reader, name string, namespace string) (*v1.IntegrationPlatform, error) { - key := k8sclient.ObjectKey{ +func GetIntegrationPlatform(context context.Context, client ctrl.Reader, name string, namespace string) (*v1.IntegrationPlatform, error) { + key := ctrl.ObjectKey{ Name: name, Namespace: namespace, } @@ -46,8 +47,8 @@ func GetIntegrationPlatform(context context.Context, client k8sclient.Reader, na } // GetIntegrationKit -- -func GetIntegrationKit(context context.Context, client k8sclient.Reader, name string, namespace string) (*v1.IntegrationKit, error) { - key := k8sclient.ObjectKey{ +func GetIntegrationKit(context context.Context, client ctrl.Reader, name string, namespace string) (*v1.IntegrationKit, error) { + key := ctrl.ObjectKey{ Name: name, Namespace: namespace, } @@ -62,8 +63,8 @@ func GetIntegrationKit(context context.Context, client k8sclient.Reader, name st } // GetIntegration -- -func GetIntegration(context context.Context, client k8sclient.Reader, name string, namespace string) (*v1.Integration, error) { - key := k8sclient.ObjectKey{ +func GetIntegration(context context.Context, client ctrl.Reader, name string, namespace string) (*v1.Integration, error) { + key := ctrl.ObjectKey{ Name: name, Namespace: namespace, } @@ -79,7 +80,7 @@ func GetIntegration(context context.Context, client k8sclient.Reader, name strin // GetBuild -- func GetBuild(context context.Context, client client.Client, name string, namespace string) (*v1.Build, error) { - key := k8sclient.ObjectKey{ + key := ctrl.ObjectKey{ Name: name, Namespace: namespace, } @@ -94,8 +95,8 @@ func GetBuild(context context.Context, client client.Client, name string, namesp } // GetConfigMap -- -func GetConfigMap(context context.Context, client k8sclient.Reader, name string, namespace string) (*corev1.ConfigMap, error) { - key := k8sclient.ObjectKey{ +func GetConfigMap(context context.Context, client ctrl.Reader, name string, namespace string) (*corev1.ConfigMap, error) { + key := ctrl.ObjectKey{ Name: name, Namespace: namespace, } @@ -119,8 +120,8 @@ func GetConfigMap(context context.Context, client k8sclient.Reader, name string, } // GetSecret -- -func GetSecret(context context.Context, client k8sclient.Reader, name string, namespace string) (*corev1.Secret, error) { - key := k8sclient.ObjectKey{ +func GetSecret(context context.Context, client ctrl.Reader, name string, namespace string) (*corev1.Secret, error) { + key := ctrl.ObjectKey{ Name: name, Namespace: namespace, } @@ -144,8 +145,8 @@ func GetSecret(context context.Context, client k8sclient.Reader, name string, na } // GetService -- -func GetService(context context.Context, client k8sclient.Reader, name string, namespace string) (*corev1.Service, error) { - key := k8sclient.ObjectKey{ +func GetService(context context.Context, client ctrl.Reader, name string, namespace string) (*corev1.Service, error) { + key := ctrl.ObjectKey{ Name: name, Namespace: namespace, } @@ -168,22 +169,31 @@ func GetService(context context.Context, client k8sclient.Reader, name string, n return &answer, nil } -// GetSecretRefValue returns the value of a secret in the supplied namespace -- -func GetSecretRefValue(ctx context.Context, client k8sclient.Reader, namespace string, selector *corev1.SecretKeySelector) (string, error) { - secret, err := GetSecret(ctx, client, selector.Name, namespace) +// GetSecretRefValue returns the value of a secret in the supplied namespace +func GetSecretRefValue(ctx context.Context, client ctrl.Reader, namespace string, selector *corev1.SecretKeySelector) (string, error) { + data, err := GetSecretRefData(ctx, client, namespace, selector) if err != nil { return "", err } + return string(data), nil +} + +// GetSecretRefData returns the value of a secret in the supplied namespace +func GetSecretRefData(ctx context.Context, client ctrl.Reader, namespace string, selector *corev1.SecretKeySelector) ([]byte, error) { + secret, err := GetSecret(ctx, client, selector.Name, namespace) + if err != nil { + return nil, err + } if data, ok := secret.Data[selector.Key]; ok { - return string(data), nil + return data, nil } - return "", fmt.Errorf("key %s not found in secret %s", selector.Key, selector.Name) + return nil, fmt.Errorf("key %s not found in secret %s", selector.Key, selector.Name) } // GetConfigMapRefValue returns the value of a configmap in the supplied namespace -func GetConfigMapRefValue(ctx context.Context, client k8sclient.Reader, namespace string, selector *corev1.ConfigMapKeySelector) (string, error) { +func GetConfigMapRefValue(ctx context.Context, client ctrl.Reader, namespace string, selector *corev1.ConfigMapKeySelector) (string, error) { cm, err := GetConfigMap(ctx, client, selector.Name, namespace) if err != nil { return "", err @@ -197,7 +207,7 @@ func GetConfigMapRefValue(ctx context.Context, client k8sclient.Reader, namespac } // ResolveValueSource -- -func ResolveValueSource(ctx context.Context, client k8sclient.Reader, namespace string, valueSource *v1.ValueSource) (string, error) { +func ResolveValueSource(ctx context.Context, client ctrl.Reader, namespace string, valueSource *v1.ValueSource) (string, error) { if valueSource.ConfigMapKeyRef != nil && valueSource.SecretKeyRef != nil { return "", fmt.Errorf("value source has bot config map and secret configured") } diff --git a/pkg/util/kubernetes/util.go b/pkg/util/kubernetes/util.go index 23d3401..232cf85 100644 --- a/pkg/util/kubernetes/util.go +++ b/pkg/util/kubernetes/util.go @@ -24,12 +24,10 @@ import ( "github.com/apache/camel-k/pkg/util" ) -// ToJSON -- func ToJSON(value runtime.Object) ([]byte, error) { return json.Marshal(value) } -// ToYAML -- func ToYAML(value runtime.Object) ([]byte, error) { data, err := ToJSON(value) if err != nil { diff --git a/pkg/util/maven/maven.go b/pkg/util/maven/maven.go index 067feca..f49658f 100644 --- a/pkg/util/maven/maven.go +++ b/pkg/util/maven/maven.go @@ -35,10 +35,8 @@ import ( "github.com/apache/camel-k/pkg/util/log" ) -// Log -- var Log = log.WithName("maven") -// GenerateProjectStructure -- func GenerateProjectStructure(context Context) error { if err := util.WriteFileWithBytesMarshallerContent(context.Path, "pom.xml", context.Project); err != nil { return err @@ -78,7 +76,6 @@ func GenerateProjectStructure(context Context) error { return nil } -// Run -- func Run(ctx Context) error { if err := GenerateProjectStructure(ctx); err != nil { return err @@ -127,7 +124,27 @@ func Run(ctx Context) error { cmd.Stdout = os.Stdout } - Log.WithValues("timeout", timeout.String()).Infof("executing: %s", strings.Join(cmd.Args, " ")) + mavenOpts, ok := os.LookupEnv("MAVEN_OPTS") + // FIXME: do not override duplicated Maven options + mavenOpts = strings.Join(append(strings.Fields(mavenOpts), ctx.ExtraMavenOpts...), " ") + + // Inherit the parent process environment + env := os.Environ() + if !ok { + env = append(env, mavenOpts) + } else { + for i, e := range env { + if strings.HasPrefix(e, "MAVEN_OPTS=") { + env[i] = mavenOpts + break + } + } + } + + cmd.Env = env + + Log.WithValues("timeout", timeout.String(), "env", env). + Infof("executing: %s", strings.Join(cmd.Args, " ")) return cmd.Run() } diff --git a/pkg/util/maven/maven_types.go b/pkg/util/maven/maven_types.go index 3b7dba5..3bac740 100644 --- a/pkg/util/maven/maven_types.go +++ b/pkg/util/maven/maven_types.go @@ -43,10 +43,10 @@ type RepositoryPolicy struct { // Mirror -- type Mirror struct { - ID string `xml:"id"` - Name string `xml:"name,omitempty"` - URL string `xml:"url"` - MirrorOf string `xml:"mirrorOf"` + ID string `xml:"id"` + Name string `xml:"name,omitempty"` + URL string `xml:"url"` + MirrorOf string `xml:"mirrorOf"` } // Build -- @@ -120,6 +120,7 @@ func NewContext(buildDir string, project Project) Context { type Context struct { Path string Project Project + ExtraMavenOpts []string SettingsContent []byte AdditionalArguments []string AdditionalEntries map[string]interface{} @@ -244,5 +245,3 @@ type PropertyActivation struct { Name string `xml:"name"` Value string `xml:"value"` } - -