This is an automated email from the ASF dual-hosted git repository.
aleks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new b96cae3 FINERACT-1490: SSL configuration based on
application.properties
b96cae3 is described below
commit b96cae37edefbbea7fe474324f66b451e2b42dd3
Author: Aleksandar Vidakovic <[email protected]>
AuthorDate: Mon Jan 17 01:59:49 2022 +0100
FINERACT-1490: SSL configuration based on application.properties
---
README.md | 13 +++
.../org/apache/fineract/ServerApplication.java | 3 -
.../boot/EmbeddedTomcatWithSSLConfiguration.java | 112 ---------------------
.../core/config/OAuth2SecurityConfig.java | 13 ++-
.../infrastructure/core/config/SecurityConfig.java | 12 ++-
.../src/main/resources/application.properties | 18 ++++
.../EmbeddedTomcatWithSSLConfigurationTest.java | 56 -----------
.../src/test/resources/application-test.properties | 8 ++
integration-tests/build.gradle | 1 +
9 files changed, 61 insertions(+), 175 deletions(-)
diff --git a/README.md b/README.md
index 153bf25..987826b 100644
--- a/README.md
+++ b/README.md
@@ -186,6 +186,19 @@ Please check `application.properties` to see which
connection pool settings can
NOTE: we'll keep backwards compatibility until one of the next releases to
ensure that things are working as expected. Environment variables prefixed
`fineract_tenants_*` can still be used to configure the database connection,
but we strongly encourage using `FINERACT_HIKARI_*` with more options.
+SSL configuration
+=================
+
+By default SSL is enabled, but all SSL related properties are now tunable. SSL
can be turned off by setting the environment variable
`FINERACT_SERVER_SSL_ENABLED` to false. If you do that then please make sure to
also change the server port to `8080` via the variable `FINERACT_SERVER_PORT`,
just for the sake of keeping the conventions.
+You can choose now easily a different SSL keystore by setting
`FINERACT_SERVER_SSL_KEY_STORE` with a path to a different (not embedded)
keystore. The password can be set via `FINERACT_SERVER_SSL_KEY_STORE_PASSWORD`.
See the `application.properties` file and the latest Spring Boot documentation
(https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html)
for more details.
+
+
+Tomcat configuration
+====================
+
+Please refer to the `application.properties` and the official Spring Boot
documentation
(https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html)
on how to do performance tuning for Tomcat. Note: you can set now the
acceptable form POST size (default is 2MB) via environment variable
`FINERACT_SERVER_TOMCAT_MAX_HTTP_FORM_POST_SIZE`.
+
+
Instructions to run on Kubernetes
=================================
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/ServerApplication.java
b/fineract-provider/src/main/java/org/apache/fineract/ServerApplication.java
index e206351..f567a6c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/ServerApplication.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/ServerApplication.java
@@ -20,12 +20,10 @@ package org.apache.fineract;
import java.io.IOException;
import
org.apache.fineract.infrastructure.core.boot.AbstractApplicationConfiguration;
-import
org.apache.fineract.infrastructure.core.boot.EmbeddedTomcatWithSSLConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.builder.SpringApplicationBuilder;
import
org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.context.annotation.Import;
/**
* Fineract main() application which launches Fineract in an embedded Tomcat
HTTP (using Spring Boot).
@@ -42,7 +40,6 @@ import org.springframework.context.annotation.Import;
public class ServerApplication extends SpringBootServletInitializer {
- @Import({ EmbeddedTomcatWithSSLConfiguration.class })
private static class Configuration extends
AbstractApplicationConfiguration {}
@Override
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/EmbeddedTomcatWithSSLConfiguration.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/EmbeddedTomcatWithSSLConfiguration.java
deleted file mode 100644
index 8f5d26c..0000000
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/EmbeddedTomcatWithSSLConfiguration.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * 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.fineract.infrastructure.core.boot;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import org.apache.catalina.connector.Connector;
-import org.apache.commons.io.FileUtils;
-import org.apache.coyote.http11.Http11NioProtocol;
-import
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
-import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-
-@Configuration
-public class EmbeddedTomcatWithSSLConfiguration {
-
- //
https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/html/howto.html#howto-enable-multiple-connectors-in-tomcat
-
- @Bean
- public ServletWebServerFactory servletContainer() {
- TomcatServletWebServerFactory tomcat = new
TomcatServletWebServerFactory();
- tomcat.setContextPath(getContextPath());
- tomcat.addAdditionalTomcatConnectors(createSslConnector());
- return tomcat;
- }
-
- private String getContextPath() {
- return "/fineract-provider";
- }
-
- protected Connector createSslConnector() {
- Connector connector = new
Connector("org.apache.coyote.http11.Http11NioProtocol");
- Http11NioProtocol protocol = (Http11NioProtocol)
connector.getProtocolHandler();
- try {
- File keystore = getFile(getKeystore());
- connector.setScheme("https");
- connector.setSecure(true);
- connector.setPort(getHTTPSPort());
- protocol.setSSLEnabled(true);
- protocol.setKeystoreFile(keystore.getAbsolutePath());
- protocol.setKeystorePass(getKeystorePass());
- return connector;
- } catch (IOException ex) {
- throw new IllegalStateException("can't access keystore: [" +
"keystore" + "] or truststore: [" + "keystore" + "]", ex);
- }
- }
-
- protected int getHTTPSPort() {
- // TODO This shouldn't be hard-coded here, but configurable
- return 8443;
- }
-
- protected String getKeystorePass() {
- return "openmf";
- }
-
- protected Resource getKeystore() {
- return new ClassPathResource("/keystore.jks");
- }
-
- public File getFile(Resource resource) throws IOException {
- try {
- return resource.getFile();
- } catch (IOException e) {
- // Uops.. OK, try again (below)
- }
-
- try {
- URL url = resource.getURL();
- /**
- * // If this creates filenames that are too long on Win, // then
could just use resource.getFilename(), //
- * even though not unique, real risk prob. min.bon String tempDir
= System.getProperty("java.io.tmpdir");
- * tempDir = tempDir + "/" + getClass().getSimpleName() + "/";
String path = url.getPath(); String uniqName
- * = path.replace("file:/", "").replace('!', '_'); String
tempFullPath = tempDir + uniqName;
- **/
- // instead of File.createTempFile(prefix?, suffix?);
- File targetFile = new File(resource.getFilename());
- long len = resource.contentLength();
- if (!targetFile.exists() || targetFile.length() != len) { // Only
- // copy
- // new
- // files
- FileUtils.copyURLToFile(url, targetFile);
- }
- return targetFile;
- } catch (IOException e) {
- // Uops.. erm, give up:
- throw new IOException("Cannot obtain a File for Resource: " +
resource.toString(), e);
- }
-
- }
-}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
index 32202a6..6266d1e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
@@ -30,6 +30,7 @@ import
org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatfor
import
org.apache.fineract.infrastructure.security.vote.SelfServiceUserAccessVote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -72,6 +73,9 @@ public class OAuth2SecurityConfig extends
WebSecurityConfigurerAdapter {
@Autowired
private TenantAwareJpaPlatformUserDetailsService userDetailsService;
+ @Autowired
+ private ServerProperties serverProperties;
+
private static final JwtGrantedAuthoritiesConverter
jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
@Override
@@ -97,8 +101,13 @@ public class OAuth2SecurityConfig extends
WebSecurityConfigurerAdapter {
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) //
.and() //
.addFilterAfter(tenantAwareTenantIdentifierFilter,
SecurityContextPersistenceFilter.class) //
- .addFilterAfter(twoFactorAuthenticationFilter,
BasicAuthenticationFilter.class) //
- .requiresChannel(channel ->
channel.antMatchers("/api/**").requiresSecure());
+ .addFilterAfter(twoFactorAuthenticationFilter,
BasicAuthenticationFilter.class); //
+
+ if (serverProperties.getSsl().isEnabled()) {
+ http.requiresChannel(channel ->
channel.antMatchers("/api/**").requiresSecure());
+ } else {
+ http.requiresChannel(channel ->
channel.antMatchers("/api/**").requiresInsecure());
+ }
}
@Bean
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
index 8fac767..ed9dce5 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
@@ -24,6 +24,7 @@ import
org.apache.fineract.infrastructure.security.filter.TwoFactorAuthenticatio
import
org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatformUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -52,6 +53,9 @@ public class SecurityConfig extends
WebSecurityConfigurerAdapter {
@Autowired
private TwoFactorAuthenticationFilter twoFactorAuthenticationFilter;
+ @Autowired
+ private ServerProperties serverProperties;
+
@Override
protected void configure(HttpSecurity http) throws Exception {
@@ -74,9 +78,13 @@ public class SecurityConfig extends
WebSecurityConfigurerAdapter {
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) //
.and() //
.addFilterAfter(tenantAwareBasicAuthenticationFilter(),
SecurityContextPersistenceFilter.class) //
- .addFilterAfter(twoFactorAuthenticationFilter,
BasicAuthenticationFilter.class) //
- .requiresChannel(channel ->
channel.antMatchers("/api/**").requiresSecure());
+ .addFilterAfter(twoFactorAuthenticationFilter,
BasicAuthenticationFilter.class); //
+ if (serverProperties.getSsl().isEnabled()) {
+ http.requiresChannel(channel ->
channel.antMatchers("/api/**").requiresSecure());
+ } else {
+ http.requiresChannel(channel ->
channel.antMatchers("/api/**").requiresInsecure());
+ }
}
@Bean
diff --git a/fineract-provider/src/main/resources/application.properties
b/fineract-provider/src/main/resources/application.properties
index 7940a79..c880e0c 100644
--- a/fineract-provider/src/main/resources/application.properties
+++ b/fineract-provider/src/main/resources/application.properties
@@ -46,6 +46,24 @@ management.endpoints.web.exposure.include=health,info
# FINERACT-914
server.forward-headers-strategy=framework
+server.port=${FINERACT_SERVER_PORT:8443}
+server.servlet.context-path=${FINERACT_SERVER_SERVLET_CONTEXT_PATH:/fineract-provider}
+server.compression.enabled=${FINERACT_SERVER_COMPRESSION_ENABLED:true}
+
+server.ssl.enabled=${FINERACT_SERVER_SSL_ENABLED:true}
+server.ssl.protocol=TLS
+#server.ssl.ciphers=${FINERACT_SERVER_SSL_CIPHERS:TLS_RSA_WITH_AES_128_CBC_SHA256}
+#server.ssl.enabled-protocols=${FINERACT_SERVER_SSL_PROTOCOLS:TLSv1.2}
+server.ssl.key-store=${FINERACT_SERVER_SSL_KEY_STORE:classpath:keystore.jks}
+server.ssl.key-store-password=${FINERACT_SERVER_SSL_KEY_STORE_PASSWORD:openmf}
+
+server.tomcat.accept-count=${FINERACT_SERVER_TOMCAT_ACCEPT_COUNT:100}
+server.tomcat.accesslog.enabled=${FINERACT_SERVER_TOMCAT_ACCESSLOG_ENABLED:false}
+server.tomcat.max-connections=${FINERACT_SERVER_TOMCAT_MAX_CONNECTIONS:8192}
+server.tomcat.max-http-form-post-size=${FINERACT_SERVER_TOMCAT_MAX_HTTP_FORM_POST_SIZE:2MB}
+server.tomcat.max-keep-alive-requests=${FINERACT_SERVER_TOMCAT_MAX_KEEP_ALIVE_REQUESTS:100}
+server.tomcat.threads.max=${FINERACT_SERVER_TOMCAT_THREADS_MAX:200}
+server.tomcat.threads.min-spare=${FINERACT_SERVER_TOMCAT_THREADS_MIN_SPARE:10}
# OAuth authorisation server endpoint
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:9000/auth/realms/fineract
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/boot/tests/EmbeddedTomcatWithSSLConfigurationTest.java
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/boot/tests/EmbeddedTomcatWithSSLConfigurationTest.java
deleted file mode 100644
index b16f7d3..0000000
---
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/boot/tests/EmbeddedTomcatWithSSLConfigurationTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * 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.fineract.infrastructure.core.boot.tests;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-
-import
org.apache.fineract.infrastructure.core.boot.EmbeddedTomcatWithSSLConfiguration;
-import org.junit.jupiter.api.Test;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-
-public class EmbeddedTomcatWithSSLConfigurationTest {
-
- @Test
- public void testGetFileWithFileResource() throws IOException {
- // Test class probably isn't in a JAR
- checkClassResource(getClass());
- }
-
- @Test
- public void testGetFileWithClasspathResource() throws IOException {
- // Spring Resource class probably is in a JAR
- File f1 = checkClassResource(Resource.class);
- f1.delete();
- checkClassResource(Resource.class);
- }
-
- protected File checkClassResource(Class<?> clazz) throws IOException {
- String testClasspathResourcePath =
clazz.getCanonicalName().replace('.', '/') + ".class";
- Resource r = new ClassPathResource(testClasspathResourcePath);
- File f = new EmbeddedTomcatWithSSLConfiguration().getFile(r);
- assertTrue(f.exists());
- f = new EmbeddedTomcatWithSSLConfiguration().getFile(r);
- assertTrue(f.exists());
- return f;
- }
-}
diff --git a/fineract-provider/src/test/resources/application-test.properties
b/fineract-provider/src/test/resources/application-test.properties
index 6a6f765..b778947 100644
--- a/fineract-provider/src/test/resources/application-test.properties
+++ b/fineract-provider/src/test/resources/application-test.properties
@@ -46,6 +46,14 @@ management.endpoints.web.exposure.include=health,info
# FINERACT-914
server.forward-headers-strategy=framework
+server.port=8443
+server.servlet.context-path=/fineract-provider
+server.compression.enabled=true
+
+server.ssl.enabled=true
+server.ssl.protocol=TLS
+server.ssl.key-store=keystore.jks
+server.ssl.key-store-password=openmf
spring.datasource.hikari.driverClassName=org.mariadb.jdbc.Driver
spring.datasource.hikari.jdbcUrl=jdbc:mariadb://localhost:3306/fineract_tenants
diff --git a/integration-tests/build.gradle b/integration-tests/build.gradle
index 3590869..4d4cfb8 100644
--- a/integration-tests/build.gradle
+++ b/integration-tests/build.gradle
@@ -38,6 +38,7 @@ cargo {
}
local {
+ logLevel = 'medium'
installer {
installConfiguration = configurations.tomcat
downloadDir = file("$buildDir/download")