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 09d149a1c Kamelet - Inject secret in Vaults - AWS Secret Manager 
(#4794)
09d149a1c is described below

commit 09d149a1c565c340e237d65989cdb904a08d73ad
Author: Andrea Cosentino <anco...@gmail.com>
AuthorDate: Thu Oct 5 12:57:26 2023 +0200

    Kamelet - Inject secret in Vaults - AWS Secret Manager (#4794)
    
    Signed-off-by: Andrea Cosentino <anco...@gmail.com>
---
 addons/vault/aws/aws_secrets_manager.go            | 36 +++++++-
 addons/vault/aws/aws_secrets_manager_test.go       | 96 +++++++++++++++++++++-
 docs/modules/traits/pages/aws-secrets-manager.adoc |  8 +-
 pkg/resources/resources.go                         |  4 +-
 resources/traits.yaml                              | 12 ++-
 5 files changed, 144 insertions(+), 12 deletions(-)

diff --git a/addons/vault/aws/aws_secrets_manager.go 
b/addons/vault/aws/aws_secrets_manager.go
index 8ad20e026..81aa15c1b 100644
--- a/addons/vault/aws/aws_secrets_manager.go
+++ b/addons/vault/aws/aws_secrets_manager.go
@@ -18,8 +18,11 @@ limitations under the License.
 package aws
 
 import (
+       "regexp"
        "strconv"
 
+       "github.com/apache/camel-k/v2/pkg/util/kubernetes"
+
        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"
@@ -46,9 +49,13 @@ type Trait struct {
        traitv1.Trait `property:",squash"`
        // Enables automatic configuration of the trait.
        Auto *bool `property:"auto" json:"auto,omitempty"`
-       // The AWS Access Key to use
+       // The AWS Access Key to use. This could be a plain text or a 
configmap/secret
+       // The content of the aws access key is expected to be a text 
containing a valid AWS access key.
+       // Syntax: [configmap|secret]:name[/key], where name represents the 
resource name, key optionally represents the resource key to be filtered 
(default key value = aws-access-key).
        AccessKey string `property:"access-key" json:"accessKey,omitempty"`
-       // The AWS Secret Key to use
+       // The AWS Secret Key to use. This could be a plain text or a 
configmap/secret
+       // The content of the aws secret key is expected to be a text 
containing a valid AWS secret key.
+       // Syntax: [configmap|secret]:name[/key], where name represents the 
resource name, key optionally represents the resource key to be filtered 
(default key value = aws-secret-key).
        SecretKey string `property:"secret-key" json:"secretKey,omitempty"`
        // The AWS Region to use
        Region string `property:"region" json:"region,omitempty"`
@@ -98,6 +105,7 @@ func (t *awsSecretsManagerTrait) Configure(environment 
*trait.Environment) (bool
 }
 
 func (t *awsSecretsManagerTrait) 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.CapabilityAwsSecretsManager)
                // Deprecated
@@ -106,8 +114,28 @@ func (t *awsSecretsManagerTrait) Apply(environment 
*trait.Environment) error {
        }
 
        if environment.IntegrationInRunningPhases() {
-               environment.ApplicationProperties["camel.vault.aws.accessKey"] 
= t.AccessKey
-               environment.ApplicationProperties["camel.vault.aws.secretKey"] 
= t.SecretKey
+               hits := rex.FindAllStringSubmatch(t.AccessKey, -1)
+               if len(hits) >= 1 {
+                       var res, _ = v1.DecodeValueSource(t.AccessKey, 
"aws-access-key", "The access Key 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.aws.accessKey"] = 
string([]byte(secretValue))
+                       }
+               } else {
+                       
environment.ApplicationProperties["camel.vault.aws.accessKey"] = t.AccessKey
+               }
+               hits = rex.FindAllStringSubmatch(t.SecretKey, -1)
+               if len(hits) >= 1 {
+                       var res, _ = v1.DecodeValueSource(t.SecretKey, 
"aws-secret-key", "The secret Key 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.aws.secretKey"] = 
string([]byte(secretValue))
+                       }
+               } else {
+                       
environment.ApplicationProperties["camel.vault.aws.secretKey"] = t.SecretKey
+               }
                environment.ApplicationProperties["camel.vault.aws.region"] = 
t.Region
                
environment.ApplicationProperties["camel.vault.aws.defaultCredentialsProvider"] 
= strconv.FormatBool(*t.UseDefaultCredentialsProvider)
                
environment.ApplicationProperties["camel.vault.aws.refreshEnabled"] = 
strconv.FormatBool(*t.RefreshEnabled)
diff --git a/addons/vault/aws/aws_secrets_manager_test.go 
b/addons/vault/aws/aws_secrets_manager_test.go
index a1084c3b0..aeb1e86f4 100644
--- a/addons/vault/aws/aws_secrets_manager_test.go
+++ b/addons/vault/aws/aws_secrets_manager_test.go
@@ -20,6 +20,9 @@ package aws
 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 TestAwsSecretsManagerTraitApply(t *testing.T) {
@@ -75,25 +79,113 @@ func TestAwsSecretsManagerTraitNoDefaultCreds(t 
*testing.T) {
        assert.Equal(t, "false", 
e.ApplicationProperties["camel.vault.aws.defaultCredentialsProvider"])
 }
 
-func createEnvironment(t *testing.T, catalogGen func() (*camel.RuntimeCatalog, 
error)) *trait.Environment {
+func TestAwsSecretsManagerTraitWithSecrets(t *testing.T) {
+       e := createEnvironment(t, camel.QuarkusCatalog, &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-secret1",
+               },
+               Data: map[string][]byte{
+                       "aws-secret-key": []byte("my-secret-key"),
+               },
+       }, &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-secret2",
+               },
+               Data: map[string][]byte{
+                       "aws-access-key": []byte("my-access-key"),
+               },
+       })
+
+       aws := NewAwsSecretsManagerTrait()
+       secrets, _ := aws.(*awsSecretsManagerTrait)
+       secrets.Enabled = pointer.Bool(true)
+       secrets.Region = "eu-west-1"
+       secrets.AccessKey = "secret:my-secret2/aws-access-key"
+       secrets.SecretKey = "secret:my-secret1/aws-secret-key"
+       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, "eu-west-1", 
e.ApplicationProperties["camel.vault.aws.region"])
+       assert.Equal(t, "my-access-key", 
e.ApplicationProperties["camel.vault.aws.accessKey"])
+       assert.Equal(t, "my-secret-key", 
e.ApplicationProperties["camel.vault.aws.secretKey"])
+       assert.Equal(t, "false", 
e.ApplicationProperties["camel.vault.aws.defaultCredentialsProvider"])
+}
+
+func TestAwsSecretsManagerTraitWithConfigMap(t *testing.T) {
+       e := createEnvironment(t, camel.QuarkusCatalog, &corev1.ConfigMap{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-configmap1",
+               },
+               Data: map[string]string{
+                       "aws-secret-key": "my-secret-key",
+               },
+       }, &corev1.ConfigMap{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-configmap2",
+               },
+               Data: map[string]string{
+                       "aws-access-key": "my-access-key",
+               },
+       })
+
+       aws := NewAwsSecretsManagerTrait()
+       secrets, _ := aws.(*awsSecretsManagerTrait)
+       secrets.Enabled = pointer.Bool(true)
+       secrets.Region = "eu-west-1"
+       secrets.AccessKey = "configmap:my-configmap2/aws-access-key"
+       secrets.SecretKey = "configmap:my-configmap1/aws-secret-key"
+       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, "eu-west-1", 
e.ApplicationProperties["camel.vault.aws.region"])
+       assert.Equal(t, "my-access-key", 
e.ApplicationProperties["camel.vault.aws.accessKey"])
+       assert.Equal(t, "my-secret-key", 
e.ApplicationProperties["camel.vault.aws.secretKey"])
+       assert.Equal(t, "false", 
e.ApplicationProperties["camel.vault.aws.defaultCredentialsProvider"])
+}
+
+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/aws-secrets-manager.adoc 
b/docs/modules/traits/pages/aws-secrets-manager.adoc
index 03383744a..4a67be3c1 100644
--- a/docs/modules/traits/pages/aws-secrets-manager.adoc
+++ b/docs/modules/traits/pages/aws-secrets-manager.adoc
@@ -43,11 +43,15 @@ The following configuration options are available:
 
 | aws-secrets-manager.access-key
 | string
-| The AWS Access Key to use
+| The AWS Access Key to use. This could be a plain text or a configmap/secret
+The content of the aws access key is expected to be a text containing a valid 
AWS access key.
+Syntax: [configmap\|secret]:name[/key], where name represents the resource 
name, key optionally represents the resource key to be filtered (default key 
value = aws-access-key).
 
 | aws-secrets-manager.secret-key
 | string
-| The AWS Secret Key to use
+| The AWS Secret Key to use. This could be a plain text or a configmap/secret
+       // The content of the aws secret key is expected to be a text 
containing a valid AWS secret key.
+       // Syntax: [configmap\|secret]:name[/key], where name represents the 
resource name, key optionally represents the resource key to be filtered 
(default key value = aws-secret-key).
 
 | aws-secrets-manager.region
 | string
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 3cc8b4665..ebf4104c9 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -625,9 +625,9 @@ var assets = func() http.FileSystem {
                "/traits.yaml": &vfsgen۰CompressedFileInfo{
                        name:             "traits.yaml",
                        modTime:          time.Time{},
-                       uncompressedSize: 70800,
+                       uncompressedSize: 71502,
 
-                       compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\xfb\x77\x1b\xb9\x91\x30\xfa\xbb\xff\x0a\x1c\xce\xdd\x23\xc9\x97\x0f\x79\xb2\xc9\xce\x6a\xe3\xec\xd5\xd8\x9e\x44\x19\x3f\x74\x2d\xcd\x64\x73\xfc\xf9\x84\x60\x37\x48\x62\xd4\x04\x3a\x00\x5a\x32\xe7\xcb\xf7\xbf\x7f\x07\x55\x85\x47\x37\x9b\x22\x65\x4b\xb3\xd1\x26\x93\x73\x62\x91\xec\x2e\x14\x0a\x85\x42\xa1\x9e\x5f\xb1\xd1\xfd\xfd\xf7\xe4\x2b\xf6\x5a\x16\x42\x59\x51\x32\xa7\x99\x5b\x0a\x76\x5a\xf3\x62\x29\xd8\x85\x
 [...]
+                       compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7b\x77\x1b\xb9\x91\x38\xfa\xbf\x3f\x05\x0e\xe7\xee\x91\xe4\xcb\x87\x3c\xd9\x64\x67\xb5\x71\xf6\x6a\x6c\x4f\xa2\x8c\x1f\xba\x96\x66\xb2\x39\x5e\x9f\x10\xec\x06\x49\x8c\x9a\x40\x07\x40\x4b\xe6\xdc\xdc\xef\xfe\x3b\xa8\x2a\x3c\xba\xd9\x14\x29\x5b\x9a\x8d\x36\x99\x9c\x13\x8b\x64\x37\x50\x28\x14\x0a\xf5\xae\xaf\xd8\xe8\xfe\xfe\x7b\xf2\x15\x7b\x2d\x0b\xa1\xac\x28\x99\xd3\xcc\x2d\x05\x3b\xad\x79\xb1\x14\xec\x42\xcf\x
 [...]
                },
        }
        fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
diff --git a/resources/traits.yaml b/resources/traits.yaml
index d2d95bed7..826996269 100755
--- a/resources/traits.yaml
+++ b/resources/traits.yaml
@@ -109,10 +109,18 @@ traits:
     description: Enables automatic configuration of the trait.
   - name: access-key
     type: string
-    description: The AWS Access Key to use
+    description: 'The AWS Access Key to use. This could be a plain text or a 
configmap/secret
+      The content of the aws access key is expected to be a text containing a 
valid
+      AWS access key. Syntax: [configmap|secret]:name[/key], where name 
represents
+      the resource name, key optionally represents the resource key to be 
filtered
+      (default key value = aws-access-key).'
   - name: secret-key
     type: string
-    description: The AWS Secret Key to use
+    description: "The AWS Secret Key to use. This could be a plain text or a 
configmap/secret
+      \t// The content of the aws secret key is expected to be a text 
containing a
+      valid AWS secret key. \t// Syntax: [configmap|secret]:name[/key], where 
name
+      represents the resource name, key optionally represents the resource key 
to
+      be filtered (default key value = aws-secret-key)."
   - name: region
     type: string
     description: The AWS Region to use

Reply via email to