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

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 90fe4e194b3 camel-aws - Add dev console for AWS secrets
90fe4e194b3 is described below

commit 90fe4e194b354fa3c6ee3f773441dc9bfb01ea2b
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Sep 7 20:10:06 2022 +0200

    camel-aws - Add dev console for AWS secrets
---
 .../camel-aws/camel-aws-secrets-manager/pom.xml    |  4 +
 .../org/apache/camel/dev-console/aws-secrets       |  2 +
 .../aws/secretsmanager/SecretsDevConsole.java      | 90 ++++++++++++++++++++++
 .../SecretsManagerPropertiesFunction.java          | 18 +++++
 .../vault/CloudTrailReloadTriggerTask.java         | 33 +++++++-
 .../org/apache/camel/spi/PeriodTaskScheduler.java  |  9 ++-
 .../impl/engine/DefaultPeriodTaskScheduler.java    | 18 +++++
 .../apache/camel/support/TimerListenerManager.java |  8 ++
 8 files changed, 178 insertions(+), 4 deletions(-)

diff --git a/components/camel-aws/camel-aws-secrets-manager/pom.xml 
b/components/camel-aws/camel-aws-secrets-manager/pom.xml
index f11708d5124..74b56d01427 100644
--- a/components/camel-aws/camel-aws-secrets-manager/pom.xml
+++ b/components/camel-aws/camel-aws-secrets-manager/pom.xml
@@ -40,6 +40,10 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-support</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-console</artifactId>
+        </dependency>
         <dependency>
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>secretsmanager</artifactId>
diff --git 
a/components/camel-aws/camel-aws-secrets-manager/src/generated/resources/META-INF/services/org/apache/camel/dev-console/aws-secrets
 
b/components/camel-aws/camel-aws-secrets-manager/src/generated/resources/META-INF/services/org/apache/camel/dev-console/aws-secrets
new file mode 100644
index 00000000000..9817b4172b7
--- /dev/null
+++ 
b/components/camel-aws/camel-aws-secrets-manager/src/generated/resources/META-INF/services/org/apache/camel/dev-console/aws-secrets
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.aws.secretsmanager.SecretsDevConsole
diff --git 
a/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsDevConsole.java
 
b/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsDevConsole.java
new file mode 100644
index 00000000000..d87d839e8b1
--- /dev/null
+++ 
b/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsDevConsole.java
@@ -0,0 +1,90 @@
+/*
+ * 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 org.apache.camel.component.aws.secretsmanager;
+
+import java.util.Map;
+
+import 
org.apache.camel.component.aws.secretsmanager.vault.CloudTrailReloadTriggerTask;
+import org.apache.camel.impl.console.AbstractDevConsole;
+import org.apache.camel.spi.PropertiesFunction;
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+
+@DevConsole("aws-secrets")
+public class SecretsDevConsole extends AbstractDevConsole {
+
+    private SecretsManagerPropertiesFunction propertiesFunction;
+    private CloudTrailReloadTriggerTask secretsRefreshTask; // TODO:
+
+    public SecretsDevConsole() {
+        super("camel", "aws-secrets", "AWS Secrets", "AWS Secrets Manager");
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+
+        PropertiesFunction pf = 
getCamelContext().getPropertiesComponent().getPropertiesFunction("aws");
+        if (pf instanceof SecretsManagerPropertiesFunction) {
+            propertiesFunction = (SecretsManagerPropertiesFunction) pf;
+        }
+    }
+
+    @Override
+    protected String doCallText(Map<String, Object> options) {
+        StringBuilder sb = new StringBuilder();
+
+        if (propertiesFunction != null) {
+            sb.append("AWS Secrets Manager:");
+            sb.append(String.format("\n    Region: %s", 
propertiesFunction.getRegion()));
+            if (propertiesFunction.isDefaultCredentialsProvider()) {
+                sb.append("\n    Login: DefaultCredentialsProvider");
+            } else {
+                sb.append("\n    Login: Access and Secret Keys");
+            }
+            sb.append("\n\nSecrets in use:");
+            for (String sec : propertiesFunction.getSecrets()) {
+                sb.append(String.format("\n    %s", sec)); // TODO: update time
+            }
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    protected JsonObject doCallJson(Map<String, Object> options) {
+        JsonObject root = new JsonObject();
+        if (propertiesFunction != null) {
+            root.put("region", propertiesFunction.getRegion());
+            if (propertiesFunction.isDefaultCredentialsProvider()) {
+                root.put("login", "DefaultCredentialsProvider");
+            } else {
+                root.put("login", "Access and Secret Keys");
+            }
+            JsonArray arr = new JsonArray();
+            root.put("secrets", arr);
+            for (String sec : propertiesFunction.getSecrets()) {
+                JsonObject jo = new JsonObject();
+                jo.put("name", sec);
+                // TODO: update time
+                arr.add(jo);
+            }
+        }
+        return root;
+    }
+}
diff --git 
a/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsManagerPropertiesFunction.java
 
b/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsManagerPropertiesFunction.java
index ae147d7f974..547581c5133 100644
--- 
a/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsManagerPropertiesFunction.java
+++ 
b/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsManagerPropertiesFunction.java
@@ -87,6 +87,9 @@ public class SecretsManagerPropertiesFunction extends 
ServiceSupport implements
 
     private final Set<String> secrets = new HashSet<>();
 
+    private String region;
+    private boolean defaultCredentialsProvider;
+
     @Override
     protected void doStart() throws Exception {
         super.doStart();
@@ -105,6 +108,7 @@ public class SecretsManagerPropertiesFunction extends 
ServiceSupport implements
                 useDefaultCredentialsProvider = 
awsVaultConfiguration.isDefaultCredentialsProvider();
             }
         }
+        this.region = region;
         if (ObjectHelper.isNotEmpty(accessKey) && 
ObjectHelper.isNotEmpty(secretKey) && ObjectHelper.isNotEmpty(region)) {
             SecretsManagerClientBuilder clientBuilder = 
SecretsManagerClient.builder();
             AwsBasicCredentials cred = AwsBasicCredentials.create(accessKey, 
secretKey);
@@ -112,6 +116,7 @@ public class SecretsManagerPropertiesFunction extends 
ServiceSupport implements
             clientBuilder.region(Region.of(region));
             client = clientBuilder.build();
         } else if (useDefaultCredentialsProvider && 
ObjectHelper.isNotEmpty(region)) {
+            this.defaultCredentialsProvider = true;
             SecretsManagerClientBuilder clientBuilder = 
SecretsManagerClient.builder();
             clientBuilder.region(Region.of(region));
             client = clientBuilder.build();
@@ -251,4 +256,17 @@ public class SecretsManagerPropertiesFunction extends 
ServiceSupport implements
         return secrets;
     }
 
+    /**
+     * The region in use for connecting to AWS Secrets Manager
+     */
+    public String getRegion() {
+        return region;
+    }
+
+    /**
+     * Whether login is using default credentials provider, or access/secret 
keys
+     */
+    public boolean isDefaultCredentialsProvider() {
+        return defaultCredentialsProvider;
+    }
 }
diff --git 
a/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/vault/CloudTrailReloadTriggerTask.java
 
b/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/vault/CloudTrailReloadTriggerTask.java
index 31cd63f0a10..10edb759a9f 100644
--- 
a/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/vault/CloudTrailReloadTriggerTask.java
+++ 
b/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/vault/CloudTrailReloadTriggerTask.java
@@ -18,8 +18,10 @@ package org.apache.camel.component.aws.secretsmanager.vault;
 
 import java.time.Instant;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.camel.CamelContext;
@@ -60,10 +62,12 @@ public class CloudTrailReloadTriggerTask extends 
ServiceSupport implements Camel
     private static final String SECRETSMANAGER_AMAZONAWS_COM = 
"secretsmanager.amazonaws.com";
 
     private CamelContext camelContext;
-    private CloudTrailClient cloudTrailClient;
+    private boolean reloadEnabled = true;
     private String secrets;
+    private CloudTrailClient cloudTrailClient;
     private SecretsManagerPropertiesFunction propertiesFunction;
     private volatile Instant lastTime;
+    private final Map<String, Instant> updates = new HashMap<>();
 
     public CloudTrailReloadTriggerTask() {
     }
@@ -78,6 +82,24 @@ public class CloudTrailReloadTriggerTask extends 
ServiceSupport implements Camel
         this.camelContext = camelContext;
     }
 
+    public boolean isReloadEnabled() {
+        return reloadEnabled;
+    }
+
+    /**
+     * Whether Camel should be reloaded on AWS secret updated
+     */
+    public void setReloadEnabled(boolean reloadEnabled) {
+        this.reloadEnabled = reloadEnabled;
+    }
+
+    /**
+     * A map of the updated secrets with the latest updated time.
+     */
+    public Map<String, Instant> getUpdates() {
+        return Collections.unmodifiableMap(updates);
+    }
+
     @Override
     protected void doStart() throws Exception {
         super.doStart();
@@ -121,6 +143,8 @@ public class CloudTrailReloadTriggerTask extends 
ServiceSupport implements Camel
             }
             cloudTrailClient = null;
         }
+
+        updates.clear();
     }
 
     @Override
@@ -153,8 +177,11 @@ public class CloudTrailReloadTriggerTask extends 
ServiceSupport implements Camel
                         for (Resource res : a) {
                             String name = res.resourceName();
                             if (matchSecret(name)) {
-                                LOG.info("Update for secret: {} detected, 
triggering a CamelContext reload", name);
-                                triggerReloading = true;
+                                updates.put(name, event.eventTime());
+                                if (isReloadEnabled()) {
+                                    LOG.info("Update for secret: {} detected, 
triggering a CamelContext reload", name);
+                                    triggerReloading = true;
+                                }
                                 break;
                             }
                         }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/PeriodTaskScheduler.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/PeriodTaskScheduler.java
index cf29b710953..2dc5fcb2af9 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/PeriodTaskScheduler.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/PeriodTaskScheduler.java
@@ -23,7 +23,6 @@ package org.apache.camel.spi;
  * For example the AWS vault is using this to periodically check for secrets 
refreshed in AWS to trigger Camel to reload
  * to use the updated secrets.
  */
-@FunctionalInterface
 public interface PeriodTaskScheduler {
 
     /**
@@ -35,4 +34,12 @@ public interface PeriodTaskScheduler {
      */
     void schedulePeriodTask(Runnable task, long period);
 
+    /**
+     * Gets an existing task by a given type, assuming there is only one task 
of the given type.
+     *
+     * @param type the type of the task
+     * @return the task, or <tt>null</tt> if no tasks exists
+     */
+    <T> T getTaskByType(Class<T> type);
+
 }
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPeriodTaskScheduler.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPeriodTaskScheduler.java
index 754e3f6d43a..948f9c5b92e 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPeriodTaskScheduler.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPeriodTaskScheduler.java
@@ -35,6 +35,20 @@ public final class DefaultPeriodTaskScheduler extends 
TimerListenerManager imple
         addTimerListener(new TaskWrapper(task, period));
     }
 
+    @Override
+    public <T> T getTaskByType(Class<T> type) {
+        for (TimerListener listener : getListeners()) {
+            Object task = listener;
+            if (listener instanceof TaskWrapper) {
+                task = ((TaskWrapper) listener).getTask();
+            }
+            if (type.isInstance(task)) {
+                return type.cast(task);
+            }
+        }
+        return null;
+    }
+
     @Override
     public void addTimerListener(TimerListener listener) {
         if (listener instanceof TaskWrapper) {
@@ -55,6 +69,10 @@ public final class DefaultPeriodTaskScheduler extends 
TimerListenerManager imple
             this.period = period;
         }
 
+        public Runnable getTask() {
+            return task;
+        }
+
         @Override
         public void onTimer() {
             if (watch.taken() > period) {
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/TimerListenerManager.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/TimerListenerManager.java
index 252f6a86ba5..8ffa869dc44 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/TimerListenerManager.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/TimerListenerManager.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.support;
 
+import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.concurrent.ScheduledExecutorService;
@@ -133,6 +134,13 @@ public class TimerListenerManager extends ServiceSupport 
implements Runnable, Ca
         LOG.debug("Removed TimerListener: {}", listener);
     }
 
+    /**
+     * A read-only set of the registered listeners
+     */
+    protected Set<TimerListener> getListeners() {
+        return Collections.unmodifiableSet(listeners);
+    }
+
     @Override
     protected void doStart() throws Exception {
         ObjectHelper.notNull(camelContext, "camelContext", this);

Reply via email to