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
The following commit(s) were added to refs/heads/main by this push:
new f5c86b79d Kamelet - Inject secret in Vaults - Hashicorp Vault (#4799)
f5c86b79d is described below
commit f5c86b79d320ea719b645545d4923c1c9e43c6f5
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Oct 5 17:04:29 2023 +0200
Kamelet - Inject secret in Vaults - Hashicorp Vault (#4799)
Signed-off-by: Andrea Cosentino <[email protected]>
---
addons/vault/hashicorp/hashicorp_vault.go | 20 +++++-
addons/vault/hashicorp/hashicorp_vault_test.go | 84 +++++++++++++++++++++++++-
docs/modules/traits/pages/hashicorp-vault.adoc | 4 +-
resources/traits.yaml | 6 +-
4 files changed, 108 insertions(+), 6 deletions(-)
diff --git a/addons/vault/hashicorp/hashicorp_vault.go
b/addons/vault/hashicorp/hashicorp_vault.go
index e3eefed8e..058b18cc9 100644
--- a/addons/vault/hashicorp/hashicorp_vault.go
+++ b/addons/vault/hashicorp/hashicorp_vault.go
@@ -18,10 +18,13 @@ limitations under the License.
package hashicorp
import (
+ "regexp"
+
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
"github.com/apache/camel-k/v2/pkg/trait"
"github.com/apache/camel-k/v2/pkg/util"
+ "github.com/apache/camel-k/v2/pkg/util/kubernetes"
"k8s.io/utils/pointer"
)
@@ -46,7 +49,9 @@ type Trait struct {
Port string `property:"port" json:"port,omitempty"`
// The Hashicorp engine to use
Engine string `property:"engine" json:"engine,omitempty"`
- // The token to access Hashicorp Vault
+ // The token to access Hashicorp Vault. This could be a plain text or a
configmap/secret
+ // The content of the hashicorp vault token is expected to be a text
containing a valid Hashicorp Vault Token.
+ // Syntax: [configmap|secret]:name[/key], where name represents the
resource name, key optionally represents the resource key to be filtered
(default key value = hashicorp-vault-token).
Token string `property:"token" json:"token,omitempty"`
// The scheme to access Hashicorp Vault
Scheme string `property:"scheme" json:"scheme,omitempty"`
@@ -76,6 +81,7 @@ func (t *hashicorpVaultTrait) Configure(environment
*trait.Environment) (bool, e
}
func (t *hashicorpVaultTrait) Apply(environment *trait.Environment) error {
+ rex :=
regexp.MustCompile(`^(configmap|secret):([a-zA-Z0-9][a-zA-Z0-9-]*)(/([a-zA-Z0-9].*))?$`)
if environment.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
util.StringSliceUniqueAdd(&environment.Integration.Status.Capabilities,
v1.CapabilityHashicorpVault)
// Deprecated
@@ -84,7 +90,17 @@ func (t *hashicorpVaultTrait) Apply(environment
*trait.Environment) error {
}
if environment.IntegrationInRunningPhases() {
-
environment.ApplicationProperties["camel.vault.hashicorp.token"] = t.Token
+ hits := rex.FindAllStringSubmatch(t.Token, -1)
+ if len(hits) >= 1 {
+ var res, _ = v1.DecodeValueSource(t.Token,
"hashicorp-vault-token", "The Hashicorp Vault Token provided is not valid")
+ if secretValue, err :=
kubernetes.ResolveValueSource(environment.Ctx, environment.Client,
environment.Platform.Namespace, &res); err != nil {
+ return err
+ } else if secretValue != "" {
+
environment.ApplicationProperties["camel.vault.hashicorp.token"] =
string([]byte(secretValue))
+ }
+ } else {
+
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
diff --git a/addons/vault/hashicorp/hashicorp_vault_test.go
b/addons/vault/hashicorp/hashicorp_vault_test.go
index 7333dffe1..86cb70229 100644
--- a/addons/vault/hashicorp/hashicorp_vault_test.go
+++ b/addons/vault/hashicorp/hashicorp_vault_test.go
@@ -20,6 +20,9 @@ package hashicorp
import (
"testing"
+ "github.com/apache/camel-k/v2/pkg/util/test"
+ corev1 "k8s.io/api/core/v1"
+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"
@@ -28,6 +31,7 @@ import (
"github.com/apache/camel-k/v2/pkg/util/camel"
"github.com/stretchr/testify/assert"
+ "k8s.io/apimachinery/pkg/runtime"
)
func TestHashicorpVaultTraitApply(t *testing.T) {
@@ -55,25 +59,101 @@ func TestHashicorpVaultTraitApply(t *testing.T) {
assert.Equal(t, "http",
e.ApplicationProperties["camel.vault.hashicorp.scheme"])
}
-func createEnvironment(t *testing.T, catalogGen func() (*camel.RuntimeCatalog,
error)) *trait.Environment {
+func TestHashicorpVaultTraitWithSecretApply(t *testing.T) {
+ e := createEnvironment(t, camel.QuarkusCatalog, &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "my-secret1",
+ },
+ Data: map[string][]byte{
+ "hashicorp-vault-token":
[]byte("my-hashicorp-vault-token"),
+ },
+ })
+ hashicorp := NewHashicorpVaultTrait()
+ secrets, _ := hashicorp.(*hashicorpVaultTrait)
+ secrets.Enabled = pointer.Bool(true)
+ secrets.Engine = "test"
+ secrets.Token = "secret:my-secret1/hashicorp-vault-token"
+ 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, "my-hashicorp-vault-token",
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 TestHashicorpVaultTraitWithConfigMapApply(t *testing.T) {
+ e := createEnvironment(t, camel.QuarkusCatalog, &corev1.ConfigMap{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "my-configmap1",
+ },
+ Data: map[string]string{
+ "hashicorp-vault-token": "my-hashicorp-vault-token",
+ },
+ })
+ hashicorp := NewHashicorpVaultTrait()
+ secrets, _ := hashicorp.(*hashicorpVaultTrait)
+ secrets.Enabled = pointer.Bool(true)
+ secrets.Engine = "test"
+ secrets.Token = "configmap:my-configmap1/hashicorp-vault-token"
+ 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, "my-hashicorp-vault-token",
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), objects ...runtime.Object) *trait.Environment {
t.Helper()
catalog, err := catalogGen()
+ client, _ := test.NewFakeClient(objects...)
assert.Nil(t, err)
e := trait.Environment{
CamelCatalog: catalog,
ApplicationProperties: make(map[string]string),
+ Client: client,
}
it := v1.Integration{
ObjectMeta: metav1.ObjectMeta{
- Name: "test",
+ Namespace: "test",
+ Name: "test",
},
Status: v1.IntegrationStatus{
Phase: v1.IntegrationPhaseDeploying,
},
}
+ platform := v1.IntegrationPlatform{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "test",
+ },
+ }
e.Integration = &it
+ e.Platform = &platform
return &e
}
diff --git a/docs/modules/traits/pages/hashicorp-vault.adoc
b/docs/modules/traits/pages/hashicorp-vault.adoc
index ea64b34e8..10c0cb89d 100644
--- a/docs/modules/traits/pages/hashicorp-vault.adoc
+++ b/docs/modules/traits/pages/hashicorp-vault.adoc
@@ -51,7 +51,9 @@ The following configuration options are available:
| hashicorp-vault.token
| string
-| The token to access Hashicorp Vault
+| The token to access Hashicorp Vault. This could be a plain text or a
configmap/secret
+The content of the hashicorp vault token is expected to be a text containing a
valid Hashicorp Vault Token.
+Syntax: [configmap\|secret]:name[/key], where name represents the resource
name, key optionally represents the resource key to be filtered (default key
value = hashicorp-vault-token).
| hashicorp-vault.scheme
| string
diff --git a/resources/traits.yaml b/resources/traits.yaml
index 5fdd4f75e..7484e147e 100755
--- a/resources/traits.yaml
+++ b/resources/traits.yaml
@@ -650,7 +650,11 @@ traits:
description: The Hashicorp engine to use
- name: token
type: string
- description: The token to access Hashicorp Vault
+ description: 'The token to access Hashicorp Vault. This could be a plain
text
+ or a configmap/secret The content of the hashicorp vault token is
expected to
+ be a text containing a valid Hashicorp Vault Token. Syntax:
[configmap|secret]:name[/key],
+ where name represents the resource name, key optionally represents the
resource
+ key to be filtered (default key value = hashicorp-vault-token).'
- name: scheme
type: string
description: The scheme to access Hashicorp Vault