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.git
The following commit(s) were added to refs/heads/main by this push:
new c40a15d5ce2e CAMEL-22993 - Camel-Jbang-mcp: For hardening tool, static
information and data could a Quarkus MCP Resource (#21428)
c40a15d5ce2e is described below
commit c40a15d5ce2ef2ab48308434969ad7ea1d9bbc8e
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Feb 12 15:07:52 2026 +0100
CAMEL-22993 - Camel-Jbang-mcp: For hardening tool, static information and
data could a Quarkus MCP Resource (#21428)
Signed-off-by: Andrea Cosentino <[email protected]>
---
.../dsl/jbang/core/commands/mcp/HardenTools.java | 138 +------------
.../dsl/jbang/core/commands/mcp/SecurityData.java | 214 +++++++++++++++++++++
.../jbang/core/commands/mcp/SecurityResources.java | 159 +++++++++++++++
3 files changed, 381 insertions(+), 130 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/HardenTools.java
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/HardenTools.java
index 8832fd3c336a..d7db50edb202 100644
---
a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/HardenTools.java
+++
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/HardenTools.java
@@ -17,10 +17,10 @@
package org.apache.camel.dsl.jbang.core.commands.mcp;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
import io.quarkiverse.mcp.server.Tool;
import io.quarkiverse.mcp.server.ToolArg;
@@ -40,47 +40,8 @@ import org.apache.camel.util.json.JsonObject;
@ApplicationScoped
public class HardenTools {
- // Components with significant security considerations
- private static final List<String> SECURITY_SENSITIVE_COMPONENTS =
Arrays.asList(
- // Network/API components - need TLS, authentication
- "http", "https", "netty-http", "vertx-http", "websocket",
- "rest", "rest-api", "platform-http", "servlet", "undertow",
"jetty",
- // Messaging - need authentication, encryption
- "kafka", "jms", "activemq", "amqp", "rabbitmq", "pulsar",
- "aws2-sqs", "aws2-sns", "aws2-kinesis",
- "azure-servicebus", "azure-eventhubs",
- "google-pubsub",
- // File/Storage - need access control, path validation
- "file", "ftp", "sftp", "ftps",
- "aws2-s3", "azure-storage-blob", "azure-storage-queue",
"azure-files",
- "google-storage", "minio",
- // Database - need authentication, SQL injection prevention
- "sql", "jdbc", "mongodb", "couchdb", "cassandraql",
- "elasticsearch", "opensearch", "redis",
- // Email - need authentication, TLS
- "smtp", "smtps", "imap", "imaps", "pop3", "pop3s",
- // Remote execution - high risk, need strict validation
- "exec", "ssh", "docker",
- // Directory services - need secure binding
- "ldap", "ldaps",
- // Secrets management
- "hashicorp-vault", "aws2-secrets-manager", "azure-key-vault",
"google-secret-manager");
-
- private static final List<String> SECURITY_BEST_PRACTICES = Arrays.asList(
- "Use TLS/SSL (version 1.2+) for all network communications",
- "Store secrets in vault services (HashiCorp Vault, AWS Secrets
Manager, Azure Key Vault, etc.)",
- "Use property placeholders for sensitive configuration values",
- "Enable authentication for all endpoints and services",
- "Validate and sanitize all input data to prevent injection
attacks",
- "Use parameterized queries for database operations",
- "Implement proper certificate validation - do not disable SSL
verification",
- "Use principle of least privilege for service accounts and IAM
roles",
- "Enable audit logging for sensitive operations",
- "Implement proper error handling without exposing internal
details",
- "Use HTTPS instead of HTTP for all external communications",
- "Configure appropriate timeouts to prevent resource exhaustion",
- "Validate file paths to prevent path traversal attacks",
- "Use SFTP/FTPS instead of plain FTP");
+ @Inject
+ SecurityData securityData;
private final CamelCatalog catalog;
@@ -120,8 +81,8 @@ public class HardenTools {
compJson.put("title", model.getTitle());
compJson.put("description", model.getDescription());
compJson.put("label", model.getLabel());
- compJson.put("securityConsiderations",
getSecurityConsiderations(comp));
- compJson.put("riskLevel", getRiskLevel(comp));
+ compJson.put("securityConsiderations",
securityData.getSecurityConsiderations(comp));
+ compJson.put("riskLevel", securityData.getRiskLevel(comp));
securityComponentsJson.add(compJson);
}
}
@@ -133,7 +94,7 @@ public class HardenTools {
// Best practices
JsonArray bestPractices = new JsonArray();
- for (String practice : SECURITY_BEST_PRACTICES) {
+ for (String practice : securityData.getBestPractices()) {
bestPractices.add(practice);
}
result.put("securityBestPractices", bestPractices);
@@ -161,7 +122,7 @@ public class HardenTools {
List<String> found = new ArrayList<>();
String lowerRoute = route.toLowerCase();
- for (String comp : SECURITY_SENSITIVE_COMPONENTS) {
+ for (String comp : securityData.getSecuritySensitiveComponents()) {
if (containsComponent(lowerRoute, comp)) {
found.add(comp);
}
@@ -318,92 +279,9 @@ public class HardenTools {
return analysis;
}
- /**
- * Get security considerations for a specific component.
- */
- private String getSecurityConsiderations(String component) {
- return switch (component) {
- case "http" ->
- "Prefer HTTPS over HTTP. Validate certificates. Configure
appropriate timeouts. Set security headers.";
- case "https" ->
- "Verify TLS version is 1.2 or higher. Enable certificate
validation. Configure secure cipher suites.";
- case "kafka" ->
- "Enable SASL authentication (SCRAM-SHA-256/512 or GSSAPI). Use
SSL for encryption. Configure ACLs for authorization.";
- case "sql", "jdbc" ->
- "Use parameterized queries to prevent SQL injection. Limit
database user privileges. Enable connection encryption.";
- case "file" ->
- "Validate file paths to prevent traversal attacks. Restrict
directory access. Set appropriate file permissions.";
- case "ftp" ->
- "INSECURE: Use SFTP or FTPS instead. Plain FTP transmits
credentials in cleartext.";
- case "sftp" ->
- "Use key-based authentication. Validate host keys. Configure
known_hosts file.";
- case "ftps" ->
- "Enable explicit FTPS. Verify server certificates. Use strong
TLS version.";
- case "exec" ->
- "HIGH RISK: Validate and sanitize all inputs to prevent
command injection. Consider safer alternatives.";
- case "ssh" ->
- "Use key-based authentication. Validate host keys. Disable
password authentication if possible.";
- case "rest", "rest-api", "platform-http" ->
- "Implement authentication (OAuth2, JWT, API keys). Validate
all input. Set CORS policies. Add security headers.";
- case "ldap" ->
- "Use LDAPS for encryption. Escape special characters to
prevent LDAP injection. Use service account with minimal privileges.";
- case "ldaps" ->
- "Verify server certificates. Use strong TLS. Escape special
characters in queries.";
- case "mongodb" ->
- "Enable authentication. Use TLS for connections. Limit network
exposure. Use SCRAM authentication.";
- case "redis" ->
- "Enable authentication (requirepass or ACL). Use TLS. Limit
network exposure. Disable dangerous commands.";
- case "jms", "activemq", "amqp", "rabbitmq" ->
- "Enable authentication. Use SSL/TLS for connections. Configure
authorization policies.";
- case "aws2-s3", "aws2-sqs", "aws2-sns", "aws2-kinesis" ->
- "Use IAM roles instead of access keys. Enable server-side
encryption. Configure bucket/queue policies.";
- case "aws2-secrets-manager" ->
- "Use IAM roles for access. Enable automatic rotation. Audit
secret access.";
- case "azure-storage-blob", "azure-storage-queue", "azure-files" ->
- "Use managed identities. Enable encryption at rest. Configure
access policies.";
- case "azure-key-vault" ->
- "Use managed identities. Enable soft-delete. Configure access
policies and RBAC.";
- case "google-storage", "google-pubsub" ->
- "Use service accounts with minimal permissions. Enable
encryption. Configure IAM policies.";
- case "google-secret-manager" ->
- "Use service accounts. Enable automatic rotation. Audit
access.";
- case "hashicorp-vault" ->
- "Use AppRole or Kubernetes auth. Configure token TTLs. Enable
audit logging.";
- case "elasticsearch", "opensearch" ->
- "Enable authentication. Use TLS. Configure role-based access
control.";
- case "smtp", "smtps", "imap", "imaps", "pop3", "pop3s" ->
- "Use TLS variants (SMTPS, IMAPS, POP3S). Use secure
authentication. Store credentials securely.";
- case "websocket" ->
- "Use WSS (WebSocket Secure). Implement authentication.
Validate origin headers.";
- case "docker" ->
- "HIGH RISK: Validate all inputs. Use least privilege. Consider
container security policies.";
- case "netty-http", "vertx-http", "undertow", "jetty", "servlet" ->
- "Enable TLS. Implement authentication. Set security headers.
Validate input.";
- case "pulsar" ->
- "Enable TLS encryption. Configure authentication (JWT,
Athenz). Set authorization policies.";
- case "minio" ->
- "Enable TLS. Use access/secret keys securely. Configure bucket
policies.";
- case "couchdb", "cassandraql" ->
- "Enable authentication. Use TLS for connections. Configure
role-based access.";
- default -> "Review security configuration for this component";
- };
- }
-
- /**
- * Get risk level for a component.
- */
- private String getRiskLevel(String component) {
- return switch (component) {
- case "exec", "docker" -> "critical";
- case "http", "ftp", "ldap", "sql", "jdbc" -> "high";
- case "file", "ssh", "rest", "rest-api", "platform-http", "kafka",
"mongodb", "redis" -> "medium";
- default -> "low";
- };
- }
-
private int countComponentsByRisk(List<String> components, String
riskLevel) {
return (int) components.stream()
- .filter(c -> riskLevel.equals(getRiskLevel(c)))
+ .filter(c -> riskLevel.equals(securityData.getRiskLevel(c)))
.count();
}
diff --git
a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/SecurityData.java
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/SecurityData.java
new file mode 100644
index 000000000000..fdaae859481b
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/SecurityData.java
@@ -0,0 +1,214 @@
+/*
+ * 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.dsl.jbang.core.commands.mcp;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import jakarta.enterprise.context.ApplicationScoped;
+
+/**
+ * Shared holder for security reference data used by both {@link HardenTools}
(MCP Tool) and {@link SecurityResources}
+ * (MCP Resources).
+ * <p>
+ * Contains the registry of security-sensitive Camel components, best
practices, per-component security considerations,
+ * and risk levels.
+ */
+@ApplicationScoped
+public class SecurityData {
+
+ private static final List<String> SECURITY_SENSITIVE_COMPONENTS =
Arrays.asList(
+ // Network/API components - need TLS, authentication
+ "http", "https", "netty-http", "vertx-http", "websocket",
+ "rest", "rest-api", "platform-http", "servlet", "undertow",
"jetty",
+ // Messaging - need authentication, encryption
+ "kafka", "jms", "activemq", "amqp", "rabbitmq", "pulsar",
+ "aws2-sqs", "aws2-sns", "aws2-kinesis",
+ "azure-servicebus", "azure-eventhubs",
+ "google-pubsub",
+ // File/Storage - need access control, path validation
+ "file", "ftp", "sftp", "ftps",
+ "aws2-s3", "azure-storage-blob", "azure-storage-queue",
"azure-files",
+ "google-storage", "minio",
+ // Database - need authentication, SQL injection prevention
+ "sql", "jdbc", "mongodb", "couchdb", "cassandraql",
+ "elasticsearch", "opensearch", "redis",
+ // Email - need authentication, TLS
+ "smtp", "smtps", "imap", "imaps", "pop3", "pop3s",
+ // Remote execution - high risk, need strict validation
+ "exec", "ssh", "docker",
+ // Directory services - need secure binding
+ "ldap", "ldaps",
+ // Secrets management
+ "hashicorp-vault", "aws2-secrets-manager", "azure-key-vault",
"google-secret-manager");
+
+ private static final List<String> SECURITY_BEST_PRACTICES = Arrays.asList(
+ "Use TLS/SSL (version 1.2+) for all network communications",
+ "Store secrets in vault services (HashiCorp Vault, AWS Secrets
Manager, Azure Key Vault, etc.)",
+ "Use property placeholders for sensitive configuration values",
+ "Enable authentication for all endpoints and services",
+ "Validate and sanitize all input data to prevent injection
attacks",
+ "Use parameterized queries for database operations",
+ "Implement proper certificate validation - do not disable SSL
verification",
+ "Use principle of least privilege for service accounts and IAM
roles",
+ "Enable audit logging for sensitive operations",
+ "Implement proper error handling without exposing internal
details",
+ "Use HTTPS instead of HTTP for all external communications",
+ "Configure appropriate timeouts to prevent resource exhaustion",
+ "Validate file paths to prevent path traversal attacks",
+ "Use SFTP/FTPS instead of plain FTP");
+
+ private static final Map<String, List<String>> COMPONENTS_BY_CATEGORY;
+
+ static {
+ Map<String, List<String>> map = new LinkedHashMap<>();
+ map.put("Network/API", Arrays.asList(
+ "http", "https", "netty-http", "vertx-http", "websocket",
+ "rest", "rest-api", "platform-http", "servlet", "undertow",
"jetty"));
+ map.put("Messaging", Arrays.asList(
+ "kafka", "jms", "activemq", "amqp", "rabbitmq", "pulsar",
+ "aws2-sqs", "aws2-sns", "aws2-kinesis",
+ "azure-servicebus", "azure-eventhubs",
+ "google-pubsub"));
+ map.put("File/Storage", Arrays.asList(
+ "file", "ftp", "sftp", "ftps",
+ "aws2-s3", "azure-storage-blob", "azure-storage-queue",
"azure-files",
+ "google-storage", "minio"));
+ map.put("Database", Arrays.asList(
+ "sql", "jdbc", "mongodb", "couchdb", "cassandraql",
+ "elasticsearch", "opensearch", "redis"));
+ map.put("Email", Arrays.asList(
+ "smtp", "smtps", "imap", "imaps", "pop3", "pop3s"));
+ map.put("Remote Execution", Arrays.asList(
+ "exec", "ssh", "docker"));
+ map.put("Directory Services", Arrays.asList(
+ "ldap", "ldaps"));
+ map.put("Secrets Management", Arrays.asList(
+ "hashicorp-vault", "aws2-secrets-manager", "azure-key-vault",
"google-secret-manager"));
+ COMPONENTS_BY_CATEGORY = Collections.unmodifiableMap(map);
+ }
+
+ public List<String> getSecuritySensitiveComponents() {
+ return SECURITY_SENSITIVE_COMPONENTS;
+ }
+
+ public List<String> getBestPractices() {
+ return SECURITY_BEST_PRACTICES;
+ }
+
+ public Map<String, List<String>> getComponentsByCategory() {
+ return COMPONENTS_BY_CATEGORY;
+ }
+
+ /**
+ * Get the category for a given component name.
+ */
+ public String getCategory(String component) {
+ for (Map.Entry<String, List<String>> entry :
COMPONENTS_BY_CATEGORY.entrySet()) {
+ if (entry.getValue().contains(component)) {
+ return entry.getKey();
+ }
+ }
+ return "Other";
+ }
+
+ /**
+ * Get security considerations for a specific component.
+ */
+ public String getSecurityConsiderations(String component) {
+ return switch (component) {
+ case "http" ->
+ "Prefer HTTPS over HTTP. Validate certificates. Configure
appropriate timeouts. Set security headers.";
+ case "https" ->
+ "Verify TLS version is 1.2 or higher. Enable certificate
validation. Configure secure cipher suites.";
+ case "kafka" ->
+ "Enable SASL authentication (SCRAM-SHA-256/512 or GSSAPI). Use
SSL for encryption. Configure ACLs for authorization.";
+ case "sql", "jdbc" ->
+ "Use parameterized queries to prevent SQL injection. Limit
database user privileges. Enable connection encryption.";
+ case "file" ->
+ "Validate file paths to prevent traversal attacks. Restrict
directory access. Set appropriate file permissions.";
+ case "ftp" ->
+ "INSECURE: Use SFTP or FTPS instead. Plain FTP transmits
credentials in cleartext.";
+ case "sftp" ->
+ "Use key-based authentication. Validate host keys. Configure
known_hosts file.";
+ case "ftps" ->
+ "Enable explicit FTPS. Verify server certificates. Use strong
TLS version.";
+ case "exec" ->
+ "HIGH RISK: Validate and sanitize all inputs to prevent
command injection. Consider safer alternatives.";
+ case "ssh" ->
+ "Use key-based authentication. Validate host keys. Disable
password authentication if possible.";
+ case "rest", "rest-api", "platform-http" ->
+ "Implement authentication (OAuth2, JWT, API keys). Validate
all input. Set CORS policies. Add security headers.";
+ case "ldap" ->
+ "Use LDAPS for encryption. Escape special characters to
prevent LDAP injection. Use service account with minimal privileges.";
+ case "ldaps" ->
+ "Verify server certificates. Use strong TLS. Escape special
characters in queries.";
+ case "mongodb" ->
+ "Enable authentication. Use TLS for connections. Limit network
exposure. Use SCRAM authentication.";
+ case "redis" ->
+ "Enable authentication (requirepass or ACL). Use TLS. Limit
network exposure. Disable dangerous commands.";
+ case "jms", "activemq", "amqp", "rabbitmq" ->
+ "Enable authentication. Use SSL/TLS for connections. Configure
authorization policies.";
+ case "aws2-s3", "aws2-sqs", "aws2-sns", "aws2-kinesis" ->
+ "Use IAM roles instead of access keys. Enable server-side
encryption. Configure bucket/queue policies.";
+ case "aws2-secrets-manager" ->
+ "Use IAM roles for access. Enable automatic rotation. Audit
secret access.";
+ case "azure-storage-blob", "azure-storage-queue", "azure-files" ->
+ "Use managed identities. Enable encryption at rest. Configure
access policies.";
+ case "azure-key-vault" ->
+ "Use managed identities. Enable soft-delete. Configure access
policies and RBAC.";
+ case "google-storage", "google-pubsub" ->
+ "Use service accounts with minimal permissions. Enable
encryption. Configure IAM policies.";
+ case "google-secret-manager" ->
+ "Use service accounts. Enable automatic rotation. Audit
access.";
+ case "hashicorp-vault" ->
+ "Use AppRole or Kubernetes auth. Configure token TTLs. Enable
audit logging.";
+ case "elasticsearch", "opensearch" ->
+ "Enable authentication. Use TLS. Configure role-based access
control.";
+ case "smtp", "smtps", "imap", "imaps", "pop3", "pop3s" ->
+ "Use TLS variants (SMTPS, IMAPS, POP3S). Use secure
authentication. Store credentials securely.";
+ case "websocket" ->
+ "Use WSS (WebSocket Secure). Implement authentication.
Validate origin headers.";
+ case "docker" ->
+ "HIGH RISK: Validate all inputs. Use least privilege. Consider
container security policies.";
+ case "netty-http", "vertx-http", "undertow", "jetty", "servlet" ->
+ "Enable TLS. Implement authentication. Set security headers.
Validate input.";
+ case "pulsar" ->
+ "Enable TLS encryption. Configure authentication (JWT,
Athenz). Set authorization policies.";
+ case "minio" ->
+ "Enable TLS. Use access/secret keys securely. Configure bucket
policies.";
+ case "couchdb", "cassandraql" ->
+ "Enable authentication. Use TLS for connections. Configure
role-based access.";
+ default -> "Review security configuration for this component";
+ };
+ }
+
+ /**
+ * Get risk level for a component.
+ */
+ public String getRiskLevel(String component) {
+ return switch (component) {
+ case "exec", "docker" -> "critical";
+ case "http", "ftp", "ldap", "sql", "jdbc" -> "high";
+ case "file", "ssh", "rest", "rest-api", "platform-http", "kafka",
"mongodb", "redis" -> "medium";
+ default -> "low";
+ };
+ }
+}
diff --git
a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/SecurityResources.java
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/SecurityResources.java
new file mode 100644
index 000000000000..424a88252d29
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/SecurityResources.java
@@ -0,0 +1,159 @@
+/*
+ * 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.dsl.jbang.core.commands.mcp;
+
+import java.util.List;
+import java.util.Map;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
+import io.quarkiverse.mcp.server.Resource;
+import io.quarkiverse.mcp.server.ResourceTemplate;
+import io.quarkiverse.mcp.server.ResourceTemplateArg;
+import io.quarkiverse.mcp.server.TextResourceContents;
+import org.apache.camel.catalog.CamelCatalog;
+import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.tooling.model.ComponentModel;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+
+/**
+ * MCP Resources exposing security reference data for Camel components.
+ * <p>
+ * These resources provide browseable security data that clients can pull into
context independently of route analysis.
+ */
+@ApplicationScoped
+public class SecurityResources {
+
+ @Inject
+ SecurityData securityData;
+
+ private final CamelCatalog catalog;
+
+ public SecurityResources() {
+ this.catalog = new DefaultCamelCatalog();
+ }
+
+ /**
+ * All security-sensitive Camel components grouped by category with risk
levels and security considerations.
+ */
+ @Resource(uri = "camel://security/components",
+ name = "camel_security_components",
+ title = "Security-Sensitive Camel Components",
+ description = "Registry of all security-sensitive Camel
components grouped by category "
+ + "(Network/API, Messaging, File/Storage,
Database, Email, Remote Execution, "
+ + "Directory Services, Secrets Management) with
risk levels and security considerations.",
+ mimeType = "application/json")
+ public TextResourceContents securityComponents() {
+ JsonObject result = new JsonObject();
+
+ Map<String, List<String>> byCategory =
securityData.getComponentsByCategory();
+ JsonArray categories = new JsonArray();
+
+ for (Map.Entry<String, List<String>> entry : byCategory.entrySet()) {
+ JsonObject categoryJson = new JsonObject();
+ categoryJson.put("category", entry.getKey());
+
+ JsonArray components = new JsonArray();
+ for (String comp : entry.getValue()) {
+ JsonObject compJson = new JsonObject();
+ compJson.put("name", comp);
+ compJson.put("riskLevel", securityData.getRiskLevel(comp));
+ compJson.put("securityConsiderations",
securityData.getSecurityConsiderations(comp));
+
+ ComponentModel model = catalog.componentModel(comp);
+ if (model != null) {
+ compJson.put("title", model.getTitle());
+ compJson.put("description", model.getDescription());
+ }
+
+ components.add(compJson);
+ }
+ categoryJson.put("components", components);
+ categories.add(categoryJson);
+ }
+
+ result.put("categories", categories);
+ result.put("totalComponents",
securityData.getSecuritySensitiveComponents().size());
+
+ return new TextResourceContents("camel://security/components",
result.toJson(), "application/json");
+ }
+
+ /**
+ * Security best practices for Camel routes.
+ */
+ @Resource(uri = "camel://security/best-practices",
+ name = "camel_security_best_practices",
+ title = "Camel Security Best Practices",
+ description = "List of security best practices for Camel routes
covering TLS, secrets management, "
+ + "authentication, input validation, and more.",
+ mimeType = "application/json")
+ public TextResourceContents securityBestPractices() {
+ JsonObject result = new JsonObject();
+
+ JsonArray practices = new JsonArray();
+ for (String practice : securityData.getBestPractices()) {
+ practices.add(practice);
+ }
+
+ result.put("bestPractices", practices);
+ result.put("totalCount", practices.size());
+
+ return new TextResourceContents("camel://security/best-practices",
result.toJson(), "application/json");
+ }
+
+ /**
+ * Security detail for a specific Camel component.
+ */
+ @ResourceTemplate(uriTemplate = "camel://security/component/{name}",
+ name = "camel_security_component_detail",
+ title = "Component Security Detail",
+ description = "Security detail for a specific Camel
component including risk level, "
+ + "security considerations, category, and
catalog information.",
+ mimeType = "application/json")
+ public TextResourceContents securityComponentDetail(
+ @ResourceTemplateArg(name = "name") String name) {
+
+ String uri = "camel://security/component/" + name;
+
+ if (!securityData.getSecuritySensitiveComponents().contains(name)) {
+ JsonObject result = new JsonObject();
+ result.put("name", name);
+ result.put("securitySensitive", false);
+ result.put("message", "Component '" + name + "' is not in the
security-sensitive components registry. "
+ + "It may still require security
configuration depending on use case.");
+ return new TextResourceContents(uri, result.toJson(),
"application/json");
+ }
+
+ JsonObject result = new JsonObject();
+ result.put("name", name);
+ result.put("securitySensitive", true);
+ result.put("riskLevel", securityData.getRiskLevel(name));
+ result.put("securityConsiderations",
securityData.getSecurityConsiderations(name));
+ result.put("category", securityData.getCategory(name));
+
+ ComponentModel model = catalog.componentModel(name);
+ if (model != null) {
+ result.put("title", model.getTitle());
+ result.put("description", model.getDescription());
+ result.put("label", model.getLabel());
+ }
+
+ return new TextResourceContents(uri, result.toJson(),
"application/json");
+ }
+}