Skip to content

Commit 7a8a5a7

Browse files
gnodetclaude
andcommitted
CAMEL-23250: Add security policy documentation and apply formatter
Add a Security Policy section to spring-boot.adoc covering available camel.security.* properties, category overrides, allowed-properties exclusion, and per-environment policies via Spring profiles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 27c4054 commit 7a8a5a7

4 files changed

Lines changed: 100 additions & 66 deletions

File tree

core/camel-spring-boot/src/main/docs/spring-boot.adoc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,75 @@ management.server.accesslog.pattern=combined
502502
----
503503

504504

505+
== Security Policy
506+
507+
Camel Spring Boot automatically enforces security policies at startup, detecting insecure configuration such as disabled SSL verification, plain-text secrets, enabled Java deserialization, or development-only features.
508+
509+
The global policy controls how Camel reacts when insecure configuration is detected:
510+
511+
[source,properties]
512+
----
513+
# allow — no warnings, allow the configuration
514+
# warn — log a warning at startup (default)
515+
# fail — throw an exception and prevent startup
516+
camel.security.policy=warn
517+
----
518+
519+
=== Category Overrides
520+
521+
Each security category can override the global policy independently:
522+
523+
[source,properties]
524+
----
525+
camel.security.policy=fail
526+
camel.security.insecure-ssl-policy=warn
527+
camel.security.insecure-serialization-policy=warn
528+
camel.security.insecure-dev-policy=allow
529+
camel.security.secret-policy=fail
530+
----
531+
532+
To exclude specific properties from all checks, use `allowed-properties`:
533+
534+
[source,properties]
535+
----
536+
camel.security.allowed-properties=camel.component.http.trustAllCertificates,camel.component.netty.allowJavaSerializedObject
537+
----
538+
539+
=== Per-Environment Policies with Spring Profiles
540+
541+
Spring profiles allow you to enforce strict security in production while keeping a relaxed policy during development.
542+
543+
In `application-prod.properties`:
544+
545+
[source,properties]
546+
----
547+
camel.security.policy=fail
548+
----
549+
550+
In `application-dev.properties`:
551+
552+
[source,properties]
553+
----
554+
camel.security.policy=allow
555+
----
556+
557+
Activate the profile via `spring.profiles.active`:
558+
559+
[source,properties]
560+
----
561+
# application.properties
562+
spring.profiles.active=dev
563+
----
564+
565+
Or at runtime:
566+
567+
[source,bash]
568+
----
569+
java -Dspring.profiles.active=prod -jar myApp.jar
570+
----
571+
572+
This way, developers can freely use options like `trustAllCertificates=true` locally, while production deployments will fail fast if any insecure configuration is detected.
573+
505574
== Virtual Threads Support
506575

507576
Camel Spring Boot provides comprehensive support for JDK 21+ Virtual Threads, offering significant performance improvements for I/O-intensive applications. Virtual threads are lightweight threads that can dramatically reduce memory overhead and improve scalability compared to traditional platform threads.

core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/security/CamelSecurityPolicyAutoConfiguration.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Set;
24-
2524
import org.apache.camel.CamelContext;
2625
import org.apache.camel.RuntimeCamelException;
2726
import org.apache.camel.main.SecurityConfigurationProperties;
@@ -48,19 +47,15 @@ public class CamelSecurityPolicyAutoConfiguration {
4847
private static final Logger LOG = LoggerFactory.getLogger(CamelSecurityPolicyAutoConfiguration.class);
4948

5049
@Bean
51-
SecurityPolicyResult camelSecurityPolicyResult(
52-
CamelContext camelContext,
53-
CamelSecurityPolicyConfigurationProperties config,
54-
Environment environment) {
50+
SecurityPolicyResult camelSecurityPolicyResult(CamelContext camelContext,
51+
CamelSecurityPolicyConfigurationProperties config, Environment environment) {
5552

5653
SecurityConfigurationProperties securityConfig = applySecurityProperties(camelContext, config);
5754

5855
Map<String, Object> camelProperties = extractCamelProperties(environment);
5956

60-
List<SecurityViolation> violations = SecurityUtils.detectViolations(
61-
camelProperties,
62-
(k, v) -> containsSensitive(camelContext, k, v),
63-
securityConfig::resolvePolicy,
57+
List<SecurityViolation> violations = SecurityUtils.detectViolations(camelProperties,
58+
(k, v) -> containsSensitive(camelContext, k, v), securityConfig::resolvePolicy,
6459
securityConfig.getAllowedPropertySet());
6560

6661
SecurityPolicyResult result = new SecurityPolicyResult(violations);
@@ -71,14 +66,12 @@ SecurityPolicyResult camelSecurityPolicyResult(
7166
return result;
7267
}
7368

74-
private SecurityConfigurationProperties applySecurityProperties(
75-
CamelContext camelContext,
69+
private SecurityConfigurationProperties applySecurityProperties(CamelContext camelContext,
7670
CamelSecurityPolicyConfigurationProperties config) {
7771

7872
// get the security config from camel-main's MainConfigurationProperties
7973
// which is already bound by CamelAutoConfiguration via CamelConfigurationProperties
80-
SecurityConfigurationProperties securityConfig
81-
= new SecurityConfigurationProperties(null);
74+
SecurityConfigurationProperties securityConfig = new SecurityConfigurationProperties(null);
8275

8376
securityConfig.setPolicy(config.getPolicy());
8477
if (config.getSecretPolicy() != null) {
@@ -143,8 +136,8 @@ private static void enforceViolations(List<SecurityViolation> violations) {
143136
if (!failures.isEmpty()) {
144137
throw new RuntimeCamelException(
145138
"Security policy violations detected (policy=fail):\n - " + String.join("\n - ", failures)
146-
+ "\nTo allow specific properties, add them to camel.security.allowed-properties"
147-
+ " or change the policy to 'warn' or 'allow'.");
139+
+ "\nTo allow specific properties, add them to camel.security.allowed-properties"
140+
+ " or change the policy to 'warn' or 'allow'.");
148141
}
149142
}
150143

core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/security/CamelSecurityPolicyConfigurationProperties.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ public class CamelSecurityPolicyConfigurationProperties {
5151
private String insecureSslPolicy;
5252

5353
/**
54-
* Security policy for insecure deserialization configuration. When set, overrides the global policy for options that
55-
* enable dangerous deserialization of untrusted data.
54+
* Security policy for insecure deserialization configuration. When set, overrides the global policy for options
55+
* that enable dangerous deserialization of untrusted data.
5656
*/
5757
private String insecureSerializationPolicy;
5858

5959
/**
60-
* Security policy for development-only features. When set, overrides the global policy for options intended only for
61-
* development environments.
60+
* Security policy for development-only features. When set, overrides the global policy for options intended only
61+
* for development environments.
6262
*/
6363
private String insecureDevPolicy;
6464

core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/security/CamelSecurityPolicyAutoConfigurationTest.java

Lines changed: 19 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,8 @@
2727

2828
public class CamelSecurityPolicyAutoConfigurationTest {
2929

30-
private final ApplicationContextRunner runner = new ApplicationContextRunner()
31-
.withConfiguration(AutoConfigurations.of(
32-
CamelAutoConfiguration.class,
33-
CamelSecurityPolicyAutoConfiguration.class));
30+
private final ApplicationContextRunner runner = new ApplicationContextRunner().withConfiguration(
31+
AutoConfigurations.of(CamelAutoConfiguration.class, CamelSecurityPolicyAutoConfiguration.class));
3432

3533
@Test
3634
public void noSecurityPropertiesShouldStartNormally() {
@@ -44,9 +42,7 @@ public void noSecurityPropertiesShouldStartNormally() {
4442

4543
@Test
4644
public void policyAllowShouldIgnoreInsecureConfig() {
47-
runner.withPropertyValues(
48-
"camel.security.policy=allow",
49-
"camel.component.http.trustAllCertificates=true")
45+
runner.withPropertyValues("camel.security.policy=allow", "camel.component.http.trustAllCertificates=true")
5046
.run(context -> {
5147
assertThat(context).hasNotFailed();
5248
SecurityPolicyResult result = context.getBean(SecurityPolicyResult.class);
@@ -56,9 +52,7 @@ public void policyAllowShouldIgnoreInsecureConfig() {
5652

5753
@Test
5854
public void policyWarnShouldStartWithViolations() {
59-
runner.withPropertyValues(
60-
"camel.security.policy=warn",
61-
"camel.component.http.trustAllCertificates=true")
55+
runner.withPropertyValues("camel.security.policy=warn", "camel.component.http.trustAllCertificates=true")
6256
.run(context -> {
6357
assertThat(context).hasNotFailed();
6458
SecurityPolicyResult result = context.getBean(SecurityPolicyResult.class);
@@ -70,25 +64,18 @@ public void policyWarnShouldStartWithViolations() {
7064

7165
@Test
7266
public void policyFailShouldPreventStartup() {
73-
runner.withPropertyValues(
74-
"camel.security.policy=fail",
75-
"camel.component.http.trustAllCertificates=true")
67+
runner.withPropertyValues("camel.security.policy=fail", "camel.component.http.trustAllCertificates=true")
7668
.run(context -> {
7769
assertThat(context).hasFailed();
78-
assertThat(context.getStartupFailure())
79-
.rootCause()
80-
.isInstanceOf(RuntimeCamelException.class)
70+
assertThat(context.getStartupFailure()).rootCause().isInstanceOf(RuntimeCamelException.class)
8171
.hasMessageContaining("Security policy violations detected");
8272
});
8373
}
8474

8575
@Test
8676
public void categoryOverrideShouldTakePrecedence() {
87-
runner.withPropertyValues(
88-
"camel.security.policy=fail",
89-
"camel.security.insecure-ssl-policy=allow",
90-
"camel.component.http.trustAllCertificates=true")
91-
.run(context -> {
77+
runner.withPropertyValues("camel.security.policy=fail", "camel.security.insecure-ssl-policy=allow",
78+
"camel.component.http.trustAllCertificates=true").run(context -> {
9279
assertThat(context).hasNotFailed();
9380
SecurityPolicyResult result = context.getBean(SecurityPolicyResult.class);
9481
assertThat(result.hasViolations()).isFalse();
@@ -97,26 +84,20 @@ public void categoryOverrideShouldTakePrecedence() {
9784

9885
@Test
9986
public void categoryOverrideWarnWhileGlobalFail() {
100-
runner.withPropertyValues(
101-
"camel.security.policy=fail",
102-
"camel.security.insecure-ssl-policy=warn",
103-
"camel.component.http.trustAllCertificates=true")
104-
.run(context -> {
87+
runner.withPropertyValues("camel.security.policy=fail", "camel.security.insecure-ssl-policy=warn",
88+
"camel.component.http.trustAllCertificates=true").run(context -> {
10589
assertThat(context).hasNotFailed();
10690
SecurityPolicyResult result = context.getBean(SecurityPolicyResult.class);
10791
assertThat(result.hasViolations()).isTrue();
108-
assertThat(result.getViolations()).anyMatch(
109-
v -> "warn".equals(v.policy()));
92+
assertThat(result.getViolations()).anyMatch(v -> "warn".equals(v.policy()));
11093
});
11194
}
11295

11396
@Test
11497
public void allowedPropertiesShouldExcludeFromChecks() {
115-
runner.withPropertyValues(
116-
"camel.security.policy=fail",
98+
runner.withPropertyValues("camel.security.policy=fail",
11799
"camel.security.allowed-properties=camel.component.http.trustAllCertificates",
118-
"camel.component.http.trustAllCertificates=true")
119-
.run(context -> {
100+
"camel.component.http.trustAllCertificates=true").run(context -> {
120101
assertThat(context).hasNotFailed();
121102
SecurityPolicyResult result = context.getBean(SecurityPolicyResult.class);
122103
assertThat(result.hasViolations()).isFalse();
@@ -125,11 +106,8 @@ public void allowedPropertiesShouldExcludeFromChecks() {
125106

126107
@Test
127108
public void multipleViolationsDetected() {
128-
runner.withPropertyValues(
129-
"camel.security.policy=warn",
130-
"camel.component.http.trustAllCertificates=true",
131-
"camel.component.netty.allowJavaSerializedObject=true")
132-
.run(context -> {
109+
runner.withPropertyValues("camel.security.policy=warn", "camel.component.http.trustAllCertificates=true",
110+
"camel.component.netty.allowJavaSerializedObject=true").run(context -> {
133111
assertThat(context).hasNotFailed();
134112
SecurityPolicyResult result = context.getBean(SecurityPolicyResult.class);
135113
assertThat(result.getViolationCount()).isGreaterThanOrEqualTo(2);
@@ -138,22 +116,16 @@ public void multipleViolationsDetected() {
138116

139117
@Test
140118
public void insecureDevPolicyOverride() {
141-
runner.withPropertyValues(
142-
"camel.security.policy=fail",
143-
"camel.security.insecure-dev-policy=allow",
144-
"camel.main.devConsoleEnabled=true")
145-
.run(context -> {
119+
runner.withPropertyValues("camel.security.policy=fail", "camel.security.insecure-dev-policy=allow",
120+
"camel.main.devConsoleEnabled=true").run(context -> {
146121
assertThat(context).hasNotFailed();
147122
});
148123
}
149124

150125
@Test
151126
public void insecureSerializationPolicyOverride() {
152-
runner.withPropertyValues(
153-
"camel.security.policy=fail",
154-
"camel.security.insecure-serialization-policy=warn",
155-
"camel.component.netty.allowJavaSerializedObject=true")
156-
.run(context -> {
127+
runner.withPropertyValues("camel.security.policy=fail", "camel.security.insecure-serialization-policy=warn",
128+
"camel.component.netty.allowJavaSerializedObject=true").run(context -> {
157129
assertThat(context).hasNotFailed();
158130
SecurityPolicyResult result = context.getBean(SecurityPolicyResult.class);
159131
assertThat(result.hasViolations()).isTrue();

0 commit comments

Comments
 (0)