Skip to content

Commit 635c769

Browse files
authored
Merge pull request #50 from 4PointSolutions/49-add-support-for-using-spring-ssl-bundles
49 add support for using spring ssl bundles
2 parents 9092387 + 4921896 commit 635c769

15 files changed

Lines changed: 199 additions & 55 deletions

File tree

spring/ConfigurationProperties.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ spring boot starter web site for more details.
2626
can be `true` or `false`. `true` will tell FLuentForms to log in with https, `false` will result in an http connection. This
2727
property is optional, and it defaults to `false` if it is not supplied.
2828

29+
`fluentforms.aem.sslBundle` - This is the name used to locate a Spring Security SSL Bundle that will be used as a trust store
30+
for SSL HTTPS connections to AEM. This property is optional, and it defaults to `aem` if it is not supplied.
31+
2932
### Adaptive Forms
3033

3134
`fluentforms.rproxy.enabled` - This is used to enable/disable the reverse proxying of secondary resources to AEM. If it is

spring/fluentforms-sample-cli-app/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.springframework.boot</groupId>
77
<artifactId>spring-boot-starter-parent</artifactId>
8-
<version>3.1.4</version>
8+
<version>3.3.5</version>
99
<relativePath /> <!-- lookup parent from repository -->
1010
</parent>
1111
<groupId>com._4point.aem.fluentforms</groupId>

spring/fluentforms-sample-web-app/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.springframework.boot</groupId>
77
<artifactId>spring-boot-starter-parent</artifactId>
8-
<version>3.1.4</version>
8+
<version>3.3.5</version>
99
</parent>
1010
<groupId>com._4point.aem.fluentforms</groupId>
1111
<artifactId>fluentforms-sample-web-app</artifactId>

spring/fluentforms-spring-boot-autoconfigure/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.springframework.boot</groupId>
77
<artifactId>spring-boot-starter-parent</artifactId>
8-
<version>3.1.4</version>
8+
<version>3.3.5</version>
99
<relativePath /> <!-- lookup parent from repository -->
1010
</parent>
1111
<groupId>com._4point.aem.fluentforms</groupId>

spring/fluentforms-spring-boot-autoconfigure/src/main/java/com/_4point/aem/fluentforms/spring/AemConfiguration.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ public record AemConfiguration(
2222
Integer port, // "aem.port"
2323
String user, // "aem.user"
2424
String password, // "aem.password"
25-
@DefaultValue("false") Boolean useSsl // "aem.useSsl"
25+
@DefaultValue("false") Boolean useSsl, // "aem.useSsl"
26+
@DefaultValue("aem") String sslBundle // "aem.sslBundle" - Spring SSL Bundle for trust store
2627
) {
2728

2829
public String url() {

spring/fluentforms-spring-boot-autoconfigure/src/main/java/com/_4point/aem/fluentforms/spring/AemProxyAfSubmission.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@
1616

1717
import org.glassfish.jersey.client.ChunkedInput;
1818
import org.glassfish.jersey.client.ClientProperties;
19-
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
2019
import org.glassfish.jersey.media.multipart.BodyPartEntity;
2120
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
2221
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
23-
import org.glassfish.jersey.media.multipart.MultiPartFeature;
2422
import org.slf4j.Logger;
2523
import org.slf4j.LoggerFactory;
2624
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.boot.ssl.SslBundles;
2726
import org.springframework.util.MultiValueMap;
2827
import org.springframework.util.MultiValueMapAdapter;
2928

@@ -34,7 +33,6 @@
3433
import jakarta.ws.rs.PathParam;
3534
import jakarta.ws.rs.Produces;
3635
import jakarta.ws.rs.client.Client;
37-
import jakarta.ws.rs.client.ClientBuilder;
3836
import jakarta.ws.rs.client.Entity;
3937
import jakarta.ws.rs.client.WebTarget;
4038
import jakarta.ws.rs.core.Context;
@@ -176,9 +174,9 @@ static class AfSubmitAemProxyProcessor implements AfSubmitProcessor {
176174
private final AemConfiguration aemConfig;
177175
private final Client httpClient;
178176

179-
public AfSubmitAemProxyProcessor(AemConfiguration aemConfig) {
177+
public AfSubmitAemProxyProcessor(AemConfiguration aemConfig, SslBundles sslBundles) {
180178
this.aemConfig = aemConfig;
181-
this.httpClient = ClientBuilder.newClient().register(HttpAuthenticationFeature.basic(aemConfig.user(), aemConfig.password())).register(MultiPartFeature.class);
179+
this.httpClient = JerseyClientFactory.createClient(sslBundles, aemConfig.sslBundle(), aemConfig.user(), aemConfig.password());
182180
}
183181

184182
@Override

spring/fluentforms-spring-boot-autoconfigure/src/main/java/com/_4point/aem/fluentforms/spring/AemProxyAutoConfiguration.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.List;
44

5+
import org.springframework.beans.factory.annotation.Autowired;
56
import org.springframework.boot.autoconfigure.AutoConfiguration;
67
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
78
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -10,6 +11,7 @@
1011
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
1112
import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer;
1213
import org.springframework.boot.context.properties.EnableConfigurationProperties;
14+
import org.springframework.boot.ssl.SslBundles;
1315
import org.springframework.context.annotation.Bean;
1416

1517
import com._4point.aem.fluentforms.spring.AemProxyAfSubmission.AfSubmissionHandler;
@@ -43,8 +45,8 @@ public class AemProxyAutoConfiguration {
4345
* JAX-RS Resources (i.e. endpoints)
4446
*/
4547
@Bean
46-
public ResourceConfigCustomizer afProxyConfigurer(AemConfiguration aemConfig, AemProxyConfiguration aemProxyConfig) {
47-
return config->config.register(new AemProxyEndpoint(aemConfig, aemProxyConfig))
48+
public ResourceConfigCustomizer afProxyConfigurer(AemConfiguration aemConfig, AemProxyConfiguration aemProxyConfig, @Autowired(required = false) SslBundles sslBundles) {
49+
return config->config.register(new AemProxyEndpoint(aemConfig, aemProxyConfig, sslBundles))
4850
.register(new AemProxyAfSubmission())
4951
;
5052
}
@@ -85,8 +87,8 @@ public AfSubmitProcessor localSubmitProcessor(List<AfSubmissionHandler> submissi
8587
*/
8688
@ConditionalOnMissingBean({AfSubmitProcessor.class, AfSubmissionHandler.class})
8789
@Bean()
88-
public AfSubmitProcessor aemSubmitProcessor(AemConfiguration aemConfig) {
89-
return new AfSubmitAemProxyProcessor(aemConfig);
90+
public AfSubmitProcessor aemSubmitProcessor(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
91+
return new AfSubmitAemProxyProcessor(aemConfig, sslBundles);
9092
}
9193

9294
/**
@@ -105,7 +107,7 @@ public AfSubmitProcessor aemSubmitProcessor(AemConfiguration aemConfig) {
105107
@ConditionalOnMissingBean(InternalAfSubmitAemProxyProcessor.class)
106108
@ConditionalOnBean(AfSubmissionHandler.class)
107109
@Bean
108-
public InternalAfSubmitAemProxyProcessor aemProxyProcessor(AemConfiguration aemConfig) {
109-
return ()->new AfSubmitAemProxyProcessor(aemConfig);
110+
public InternalAfSubmitAemProxyProcessor aemProxyProcessor(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
111+
return ()->new AfSubmitAemProxyProcessor(aemConfig, sslBundles);
110112
}
111113
}

spring/fluentforms-spring-boot-autoconfigure/src/main/java/com/_4point/aem/fluentforms/spring/AemProxyEndpoint.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,27 @@
77
import java.util.stream.Collectors;
88

99
import javax.naming.ConfigurationException;
10+
11+
import org.glassfish.jersey.client.ChunkedInput;
12+
import org.glassfish.jersey.server.ChunkedOutput;
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
import org.springframework.boot.ssl.SslBundles;
16+
17+
import com._4point.aem.docservices.rest_services.client.helpers.ReplacingInputStream;
18+
1019
import jakarta.ws.rs.GET;
1120
import jakarta.ws.rs.HeaderParam;
1221
import jakarta.ws.rs.POST;
1322
import jakarta.ws.rs.Path;
1423
import jakarta.ws.rs.PathParam;
1524
import jakarta.ws.rs.client.Client;
16-
import jakarta.ws.rs.client.ClientBuilder;
1725
import jakarta.ws.rs.client.Entity;
1826
import jakarta.ws.rs.client.WebTarget;
1927
import jakarta.ws.rs.core.GenericType;
2028
import jakarta.ws.rs.core.MediaType;
2129
import jakarta.ws.rs.core.Response;
2230

23-
import org.glassfish.jersey.client.ChunkedInput;
24-
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
25-
import org.glassfish.jersey.media.multipart.MultiPartFeature;
26-
import org.glassfish.jersey.server.ChunkedOutput;
27-
import org.slf4j.Logger;
28-
import org.slf4j.LoggerFactory;
29-
30-
import com._4point.aem.docservices.rest_services.client.helpers.ReplacingInputStream;
31-
3231
/**
3332
* Reverse Proxy Code which reverse proxies secondary resources (.css, .js, etc.) that the browser will request.
3433
* These requests are forwarded to AEM.
@@ -55,10 +54,10 @@ public class AemProxyEndpoint {
5554
/**
5655
*
5756
*/
58-
public AemProxyEndpoint(AemConfiguration aemConfig, AemProxyConfiguration aemProxyConfig) {
57+
public AemProxyEndpoint(AemConfiguration aemConfig, AemProxyConfiguration aemProxyConfig, SslBundles sslBundles) {
5958
this.aemProxyConfig = aemProxyConfig;
6059
this.aemConfig = aemConfig;
61-
this.httpClient = ClientBuilder.newClient().register(HttpAuthenticationFeature.basic(aemConfig.user(), aemConfig.password())).register(MultiPartFeature.class);
60+
this.httpClient = JerseyClientFactory.createClient(sslBundles, aemConfig.sslBundle(), aemConfig.user(), aemConfig.password());
6261
}
6362

6463
@Path("libs/granite/csrf/token.json")

spring/fluentforms-spring-boot-autoconfigure/src/main/java/com/_4point/aem/fluentforms/spring/FluentFormsAutoConfiguration.java

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import java.io.InputStream;
44
import java.util.function.Function;
55

6+
import org.springframework.beans.factory.annotation.Autowired;
67
import org.springframework.boot.autoconfigure.AutoConfiguration;
78
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
89
import org.springframework.boot.context.properties.EnableConfigurationProperties;
10+
import org.springframework.boot.ssl.SslBundles;
911
import org.springframework.context.annotation.Bean;
1012
import org.springframework.context.annotation.Lazy;
1113

@@ -52,18 +54,19 @@
5254
public class FluentFormsAutoConfiguration {
5355

5456
@SuppressWarnings("unchecked")
55-
private <T extends Builder> T setAemFields(T builder, AemConfiguration aemConfig) {
57+
private <T extends Builder> T setAemFields(T builder, AemConfiguration aemConfig, SslBundles sslBundles) {
5658
return (T)(builder.machineName(aemConfig.servername())
5759
.port(aemConfig.port())
5860
.basicAuthentication(aemConfig.user(), aemConfig.password())
5961
.useSsl(aemConfig.useSsl())
62+
.clientFactory(()->JerseyClientFactory.createClient(sslBundles, aemConfig.sslBundle()))
6063
);
6164
}
6265

6366
@ConditionalOnMissingBean
6467
@Bean
65-
public AdaptiveFormsService adaptiveFormsService(AemConfiguration aemConfig, Function<InputStream, InputStream> afInputStreamFilter) {
66-
return setAemFields(AdaptiveFormsService.builder(), aemConfig)
68+
public AdaptiveFormsService adaptiveFormsService(AemConfiguration aemConfig, Function<InputStream, InputStream> afInputStreamFilter, @Autowired(required = false) SslBundles sslBundles) {
69+
return setAemFields(AdaptiveFormsService.builder(), aemConfig, sslBundles)
6770
.addRenderResultFilter(afInputStreamFilter)
6871
.build();
6972
}
@@ -83,58 +86,58 @@ private Function<InputStream, InputStream> buildInputFilter(String aemPrefix, St
8386

8487
@ConditionalOnMissingBean
8588
@Bean
86-
public AssemblerService assemblerService(AemConfiguration aemConfig) {
87-
RestServicesDocAssemblerServiceAdapter adapter = setAemFields(RestServicesDocAssemblerServiceAdapter.builder(), aemConfig).build();
89+
public AssemblerService assemblerService(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
90+
RestServicesDocAssemblerServiceAdapter adapter = setAemFields(RestServicesDocAssemblerServiceAdapter.builder(), aemConfig, sslBundles).build();
8891
return new AssemblerServiceImpl(adapter, UsageContext.CLIENT_SIDE);
8992
}
9093

9194
@ConditionalOnMissingBean
9295
@Bean
93-
public DocAssuranceService docAssuranceService(AemConfiguration aemConfig) {
94-
RestServicesDocAssuranceServiceAdapter adapter = setAemFields(RestServicesDocAssuranceServiceAdapter.builder(), aemConfig).build();
96+
public DocAssuranceService docAssuranceService(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
97+
RestServicesDocAssuranceServiceAdapter adapter = setAemFields(RestServicesDocAssuranceServiceAdapter.builder(), aemConfig, sslBundles).build();
9598
return new DocAssuranceServiceImpl(adapter);
9699
}
97100

98101
@ConditionalOnMissingBean
99102
@Bean
100-
public FormsService formsService(AemConfiguration aemConfig) {
101-
RestServicesFormsServiceAdapter adapter = setAemFields(RestServicesFormsServiceAdapter.builder(), aemConfig).build();
103+
public FormsService formsService(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
104+
RestServicesFormsServiceAdapter adapter = setAemFields(RestServicesFormsServiceAdapter.builder(), aemConfig, sslBundles).build();
102105
return new FormsServiceImpl(adapter, UsageContext.CLIENT_SIDE);
103106
}
104107

105108
@ConditionalOnMissingBean
106109
@Bean
107-
public GeneratePDFService generatePDFService(AemConfiguration aemConfig) {
108-
RestServicesGeneratePDFServiceAdapter adapter = setAemFields(RestServicesGeneratePDFServiceAdapter.builder(), aemConfig).build();
110+
public GeneratePDFService generatePDFService(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
111+
RestServicesGeneratePDFServiceAdapter adapter = setAemFields(RestServicesGeneratePDFServiceAdapter.builder(), aemConfig, sslBundles).build();
109112
return new GeneratePDFServiceImpl(adapter);
110113
}
111114

112115
@ConditionalOnMissingBean
113116
@Bean
114-
public Html5FormsService html5FormsService(AemConfiguration aemConfig, AemProxyConfiguration aemProxyConfig) {
115-
return setAemFields(Html5FormsService.builder(), aemConfig)
117+
public Html5FormsService html5FormsService(AemConfiguration aemConfig, AemProxyConfiguration aemProxyConfig, @Autowired(required = false) SslBundles sslBundles) {
118+
return setAemFields(Html5FormsService.builder(), aemConfig, sslBundles)
116119
.addRenderResultFilter(afInputStreamFilter(aemProxyConfig))
117120
.build();
118121
}
119122

120123
@ConditionalOnMissingBean
121124
@Bean
122-
public OutputService outputService(AemConfiguration aemConfig) {
123-
RestServicesOutputServiceAdapter adapter = setAemFields(RestServicesOutputServiceAdapter.builder(), aemConfig).build();
125+
public OutputService outputService(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
126+
RestServicesOutputServiceAdapter adapter = setAemFields(RestServicesOutputServiceAdapter.builder(), aemConfig, sslBundles).build();
124127
return new OutputServiceImpl(adapter, UsageContext.CLIENT_SIDE);
125128
}
126129

127130
@ConditionalOnMissingBean
128131
@Bean
129-
public PdfUtilityService pdfUtilityService(AemConfiguration aemConfig) {
130-
RestServicesPdfUtilityServiceAdapter adapter = setAemFields(RestServicesPdfUtilityServiceAdapter.builder(), aemConfig).build();
132+
public PdfUtilityService pdfUtilityService(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
133+
RestServicesPdfUtilityServiceAdapter adapter = setAemFields(RestServicesPdfUtilityServiceAdapter.builder(), aemConfig, sslBundles).build();
131134
return new PdfUtilityServiceImpl(adapter);
132135
}
133136

134137
@ConditionalOnMissingBean
135138
@Bean
136-
public ConvertPdfService convertPdfService(AemConfiguration aemConfig) {
137-
RestServicesConvertPdfServiceAdapter adapter = setAemFields(RestServicesConvertPdfServiceAdapter.builder(), aemConfig).build();
139+
public ConvertPdfService convertPdfService(AemConfiguration aemConfig, @Autowired(required = false) SslBundles sslBundles) {
140+
RestServicesConvertPdfServiceAdapter adapter = setAemFields(RestServicesConvertPdfServiceAdapter.builder(), aemConfig, sslBundles).build();
138141
return new ConvertPdfServiceImpl(adapter);
139142
}
140143

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com._4point.aem.fluentforms.spring;
2+
3+
import javax.net.ssl.SSLContext;
4+
5+
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
6+
import org.glassfish.jersey.media.multipart.MultiPartFeature;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
import org.springframework.boot.ssl.NoSuchSslBundleException;
10+
import org.springframework.boot.ssl.SslBundle;
11+
import org.springframework.boot.ssl.SslBundles;
12+
13+
import jakarta.ws.rs.client.Client;
14+
import jakarta.ws.rs.client.ClientBuilder;
15+
16+
/**
17+
*
18+
*/
19+
public class JerseyClientFactory {
20+
private final static Logger logger = LoggerFactory.getLogger(JerseyClientFactory.class);
21+
22+
public static Client createClient(SslBundles sslBundles, String bundleName, String username, String password) {
23+
return createClient(sslBundles, bundleName)
24+
.register(HttpAuthenticationFeature.basic(username, password))
25+
.register(MultiPartFeature.class);
26+
}
27+
28+
public static Client createClient(SslBundles sslBundles, String bundleName) {
29+
if (sslBundles != null) {
30+
logger.info("SslBundles is not null");
31+
try {
32+
SslBundle bundle = sslBundles.getBundle(bundleName);
33+
logger.info("Client sslBundle is not null");
34+
SSLContext sslContext = bundle.createSslContext();
35+
return ClientBuilder.newBuilder().sslContext(sslContext).build();
36+
} catch (NoSuchSslBundleException e) {
37+
// Eat the exception and fall through to the default client
38+
}
39+
}
40+
logger.info("Creating default client");
41+
return ClientBuilder.newClient();
42+
}
43+
}

0 commit comments

Comments
 (0)