This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 901c8bac0e4a26845313dcfc5e7841ed3ed16c19 Author: Andrea Cosentino <anco...@gmail.com> AuthorDate: Mon Feb 6 13:58:06 2023 +0100 feat(vault): Support Hashicorp Vault as secrets properties source Signed-off-by: Andrea Cosentino <anco...@gmail.com> --- addons/vault/hashicorp/hashicorp_vault.go | 94 ++++++++++++++++++++++++++ addons/vault/hashicorp/hashicorp_vault_test.go | 79 ++++++++++++++++++++++ 2 files changed, 173 insertions(+) diff --git a/addons/vault/hashicorp/hashicorp_vault.go b/addons/vault/hashicorp/hashicorp_vault.go new file mode 100644 index 000000000..0419a21a7 --- /dev/null +++ b/addons/vault/hashicorp/hashicorp_vault.go @@ -0,0 +1,94 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package hashicorp + +import ( + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + traitv1 "github.com/apache/camel-k/pkg/apis/camel/v1/trait" + "github.com/apache/camel-k/pkg/trait" + "github.com/apache/camel-k/pkg/util" + "k8s.io/utils/pointer" +) + +// The Hashicorp Vault trait can be used to use secrets from Hashicorp Vault +// +// The Hashicorp Vault trait is disabled by default. +// +// For more information about how to use secrets from Hashicorp vault take a look at the components docs: xref:components::hashicorp-vault-component.adoc[Hashicorp Vault component] +// +// A sample execution of this trait, would require +// the following trait options: +// -t hashicorp-vault.enabled=true -t hashicorp-vault.token="token" -t hashicorp-vault.port="port" -t hashicorp-vault.engine="engine" -t hashicorp-vault.port="port" -t hashicorp-vault.scheme="scheme" +// +// +camel-k:trait=aws-secrets-manager. +type Trait struct { + traitv1.Trait `property:",squash"` + // Enables automatic configuration of the trait. + Auto *bool `property:"auto" json:"auto,omitempty"` + // The Host to use + Host string `property:"host,omitempty"` + // The Port to use + Port string `property:"port,omitempty"` + // The Hashicorp engine to use + Engine string `property:"engine,omitempty"` + // The token to access Hashicorp Vault + Token string `property:"token,omitempty"` + // The scheme to access Hashicorp Vault + Scheme string `property:"scheme,omitempty"` +} + +type hashicorpVaultTrait struct { + trait.BaseTrait + Trait `property:",squash"` +} + +func NewHashicorpVaultTrait() trait.Trait { + return &hashicorpVaultTrait{ + BaseTrait: trait.NewBaseTrait("hashicorp-vault", trait.TraitOrderBeforeControllerCreation), + } +} + +func (t *hashicorpVaultTrait) Configure(environment *trait.Environment) (bool, error) { + if !pointer.BoolDeref(t.Enabled, false) { + return false, nil + } + + if !environment.IntegrationInPhase(v1.IntegrationPhaseInitialization) && !environment.IntegrationInRunningPhases() { + return false, nil + } + + return true, nil +} + +func (t *hashicorpVaultTrait) Apply(environment *trait.Environment) error { + if environment.IntegrationInPhase(v1.IntegrationPhaseInitialization) { + util.StringSliceUniqueAdd(&environment.Integration.Status.Capabilities, v1.CapabilityAwsSecretsManager) + // Add the Camel Quarkus AWS Secrets Manager + util.StringSliceUniqueAdd(&environment.Integration.Status.Dependencies, "mvn:org.apache.camel.quarkus:camel-quarkus-hashicorp-vault") + } + + if environment.IntegrationInRunningPhases() { + environment.ApplicationProperties["camel.vault.hashicorp.token"] = t.Token + environment.ApplicationProperties["camel.vault.hashicorp.host"] = t.Host + environment.ApplicationProperties["camel.vault.hashicorp.port"] = t.Port + environment.ApplicationProperties["camel.vault.hashicorp.engine"] = t.Engine + environment.ApplicationProperties["camel.vault.hashicorp.scheme"] = t.Scheme + } + + return nil +} diff --git a/addons/vault/hashicorp/hashicorp_vault_test.go b/addons/vault/hashicorp/hashicorp_vault_test.go new file mode 100644 index 000000000..53babdfaf --- /dev/null +++ b/addons/vault/hashicorp/hashicorp_vault_test.go @@ -0,0 +1,79 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package hashicorp + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" + + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/trait" + "github.com/apache/camel-k/pkg/util/camel" + + "github.com/stretchr/testify/assert" +) + +func TestHashicorpVaultTraitApply(t *testing.T) { + e := createEnvironment(t, camel.QuarkusCatalog) + hashicorp := NewHashicorpVaultTrait() + secrets, _ := hashicorp.(*hashicorpVaultTrait) + secrets.Enabled = pointer.Bool(true) + secrets.Engine = "test" + secrets.Token = "wwww.testx1234590" + secrets.Host = "localhost" + secrets.Port = "9091" + secrets.Scheme = "http" + ok, err := secrets.Configure(e) + assert.Nil(t, err) + assert.True(t, ok) + + err = secrets.Apply(e) + assert.Nil(t, err) + + assert.Empty(t, e.ApplicationProperties["quarkus.jaeger.enabled"]) + assert.Equal(t, "test", e.ApplicationProperties["camel.vault.hashicorp.engine"]) + assert.Equal(t, "wwww.testx1234590", e.ApplicationProperties["camel.vault.hashicorp.token"]) + assert.Equal(t, "localhost", e.ApplicationProperties["camel.vault.hashicorp.host"]) + assert.Equal(t, "9091", e.ApplicationProperties["camel.vault.hashicorp.port"]) + assert.Equal(t, "http", e.ApplicationProperties["camel.vault.hashicorp.scheme"]) +} + +func createEnvironment(t *testing.T, catalogGen func() (*camel.RuntimeCatalog, error)) *trait.Environment { + t.Helper() + + catalog, err := catalogGen() + assert.Nil(t, err) + + e := trait.Environment{ + CamelCatalog: catalog, + ApplicationProperties: make(map[string]string), + } + + it := v1.Integration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Status: v1.IntegrationStatus{ + Phase: v1.IntegrationPhaseDeploying, + }, + } + e.Integration = &it + return &e +}