You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by al...@apache.org on 2023/02/21 06:27:58 UTC

[fineract] branch develop updated: FINERACT-1894: Template request fix

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 d27d9f343 FINERACT-1894: Template request fix
d27d9f343 is described below

commit d27d9f343d1454622b4067262213964826cbd95d
Author: Aleks <al...@apache.org>
AuthorDate: Sun Feb 19 23:36:47 2023 +0100

    FINERACT-1894: Template request fix
---
 .../core/config/FineractProperties.java            | 10 ++++++
 .../exception/TemplateForbiddenException.java      | 28 +++++++++++++++
 .../template/service/TemplateMergeService.java     | 40 +++++++++++++++++-----
 .../src/main/resources/application.properties      |  2 ++
 .../service/TemplateServiceStepDefinitions.java    |  4 ++-
 5 files changed, 75 insertions(+), 9 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
index 9a2299d9d..e84249351 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
@@ -52,6 +52,8 @@ public class FineractProperties {
 
     private FineractJobProperties job;
 
+    private FineractTemplateProperties template;
+
     @Getter
     @Setter
     public static class FineractTenantProperties {
@@ -234,4 +236,12 @@ public class FineractProperties {
 
         private int stuckRetryThreshold;
     }
+
+    @Getter
+    @Setter
+    public static class FineractTemplateProperties {
+
+        private boolean regexWhitelistEnabled;
+        private List<String> regexWhitelist;
+    }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/template/exception/TemplateForbiddenException.java b/fineract-provider/src/main/java/org/apache/fineract/template/exception/TemplateForbiddenException.java
new file mode 100644
index 000000000..c089b07f3
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/template/exception/TemplateForbiddenException.java
@@ -0,0 +1,28 @@
+/**
+ * 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.template.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+public class TemplateForbiddenException extends AbstractPlatformResourceNotFoundException {
+
+    public TemplateForbiddenException(final String url) {
+        super("error.msg.template.url.forbidden", "Template with url " + url + " not allowed");
+    }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/template/service/TemplateMergeService.java b/fineract-provider/src/main/java/org/apache/fineract/template/service/TemplateMergeService.java
index 0a87073ed..cd4d808ec 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/template/service/TemplateMergeService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/template/service/TemplateMergeService.java
@@ -38,20 +38,24 @@ import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.template.domain.Template;
 import org.apache.fineract.template.domain.TemplateFunctions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.fineract.template.exception.TemplateForbiddenException;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Service;
 
+@Slf4j
+@RequiredArgsConstructor
 @Service
 public class TemplateMergeService {
 
-    private static final Logger LOG = LoggerFactory.getLogger(TemplateMergeService.class);
-
-    // private final FromJsonHelper fromApiJsonHelper;
+    private final FineractProperties fineractProperties;
 
     // TODO Replace this with appropriate alternative available in Guava
     private static String getStringFromInputStream(final InputStream is) {
@@ -64,7 +68,7 @@ public class TemplateMergeService {
                 sb.append(line);
             }
         } catch (final IOException e) {
-            LOG.error("getStringFromInputStream() failed", e);
+            log.error("getStringFromInputStream() failed", e);
         }
 
         return sb.toString();
@@ -102,7 +106,7 @@ public class TemplateMergeService {
                 try {
                     scopes.put(entry.getKey(), getMapFromUrl(url));
                 } catch (final IOException e) {
-                    LOG.error("getCompiledMapFromMappers() failed", e);
+                    log.error("getCompiledMapFromMappers() failed", e);
                 }
             }
         }
@@ -124,6 +128,26 @@ public class TemplateMergeService {
     }
 
     private HttpURLConnection getConnection(final String url) {
+        if (fineractProperties.getTemplate() != null && fineractProperties.getTemplate().isRegexWhitelistEnabled()) {
+            boolean whitelisted = false;
+
+            if (fineractProperties.getTemplate().getRegexWhitelist() != null
+                    && !fineractProperties.getTemplate().getRegexWhitelist().isEmpty()) {
+                for (String urlPattern : fineractProperties.getTemplate().getRegexWhitelist()) {
+                    Pattern pattern = Pattern.compile(urlPattern);
+                    Matcher matcher = pattern.matcher(url);
+                    if (matcher.matches()) {
+                        whitelisted = true;
+                        break;
+                    }
+                }
+            }
+
+            if (!whitelisted) {
+                throw new TemplateForbiddenException(url);
+            }
+        }
+
         String authToken = ThreadLocalContextUtil.getAuthToken();
         if (authToken == null) {
             final String name = SecurityContextHolder.getContext().getAuthentication().getName();
@@ -149,7 +173,7 @@ public class TemplateMergeService {
             connection.setDoInput(true);
 
         } catch (IOException | KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
-            LOG.error("getConnection() failed, return null", e);
+            log.error("getConnection() failed, return null", e);
         }
 
         return connection;
diff --git a/fineract-provider/src/main/resources/application.properties b/fineract-provider/src/main/resources/application.properties
index d13c4c355..7c37d32b5 100644
--- a/fineract-provider/src/main/resources/application.properties
+++ b/fineract-provider/src/main/resources/application.properties
@@ -88,6 +88,8 @@ fineract.content.s3.bucketName=${FINERACT_CONTENT_S3_BUCKET_NAME:}
 fineract.content.s3.accessKey=${FINERACT_CONTENT_S3_ACCESS_KEY:}
 fineract.content.s3.secretKey=${FINERACT_CONTENT_S3_SECRET_KEY:}
 
+fineract.template.regex-whitelist-enabled=${FINERACT_TEMPLATE_REGEX_WHITELIST_ENABLED:true}
+fineract.template.regex-whitelist=${FINERACT_TEMPLATE_REGEX_WHITELIST:}
 
 fineract.report.export.s3.bucket=${FINERACT_REPORT_EXPORT_S3_BUCKET_NAME:}
 fineract.report.export.s3.enabled=${FINERACT_REPORT_EXPORT_S3_ENABLED:false}
diff --git a/fineract-provider/src/test/java/org/apache/fineract/template/service/TemplateServiceStepDefinitions.java b/fineract-provider/src/test/java/org/apache/fineract/template/service/TemplateServiceStepDefinitions.java
index 0cf4fd147..69f9ee6c4 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/template/service/TemplateServiceStepDefinitions.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/template/service/TemplateServiceStepDefinitions.java
@@ -34,10 +34,12 @@ import java.util.Map;
 import org.apache.commons.io.IOUtils;
 import org.apache.fineract.template.domain.Template;
 import org.apache.fineract.template.domain.TemplateMapper;
+import org.springframework.beans.factory.annotation.Autowired;
 
 public class TemplateServiceStepDefinitions implements En {
 
-    private TemplateMergeService tms = new TemplateMergeService();
+    @Autowired
+    private TemplateMergeService tms;
 
     private String template;