Fix security risk 'Improper Input Validation' 78/131478/7
authorvasraz <vasyl.razinkov@est.tech>
Fri, 14 Oct 2022 12:35:39 +0000 (13:35 +0100)
committerMichael Morris <michael.morris@est.tech>
Tue, 18 Oct 2022 08:27:16 +0000 (08:27 +0000)
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
Change-Id: I6a52148aec3b567db43ec57109214e52d106f73c
Issue-ID: SDC-4189

42 files changed:
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ByActionStatusComponentException.java
catalog-be/src/main/java/org/openecomp/sdc/be/filters/BeRestrictionAccessFilter.java
catalog-be/src/main/java/org/openecomp/sdc/be/filters/DataValidatorFilter.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/filters/GatewayFilter.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/exception/StorageExceptionMapper.java
catalog-be/src/main/resources/config/configuration.yaml
catalog-be/src/main/resources/config/error-configuration.yaml
catalog-be/src/main/webapp/WEB-INF/web.xml
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/utils/DataValidatorTest.java [new file with mode: 0644]
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-fe/src/main/java/org/openecomp/sdc/fe/filters/DataValidatorFilter.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/User.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/UserTest.java
catalog-ui/src/app/ng2/pages/composition/panel/panel-header/edit-name-modal/edit-name-modal.component.html
catalog-ui/src/app/ng2/pages/workspace/deployment/panel/panel-tabs/edit-module-name/edit-module-name.component.html
catalog-ui/src/assets/languages/en_US.json
common-app-api/src/main/java/org/openecomp/sdc/be/config/Configuration.java
common-app-api/src/main/java/org/openecomp/sdc/common/filters/DataValidatorFilterAbstract.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/common/filters/RequestWrapper.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/common/servlets/BasicServlet.java
common-app-api/src/main/java/org/openecomp/sdc/common/util/DataValidator.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/common/util/NoHtml.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/common/util/NoHtmlValidator.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/common/util/SecureString.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/exception/NotAllowedSpecialCharsException.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/fe/config/Configuration.java
docs/configuration.rst
openecomp-be/api/openecomp-sdc-rest-webapp/notifications-fe/src/main/webapp/WEB-INF/web.xml
openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/beans-services.xml
openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml
openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb
openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/errors/DefaultExceptionMapper.java
openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/filters/DataValidatorFilter.java [new file with mode: 0644]
openecomp-be/tools/migration/README
utils/webseal-simulator/src/main/java/org/openecomp/sdc/webseal/simulator/DataValidatorFilter.java [new file with mode: 0644]
utils/webseal-simulator/src/main/java/org/openecomp/sdc/webseal/simulator/Login.java
utils/webseal-simulator/src/main/java/org/openecomp/sdc/webseal/simulator/RequestsClient.java
utils/webseal-simulator/src/main/java/org/openecomp/sdc/webseal/simulator/conf/Conf.java
utils/webseal-simulator/src/main/webapp/WEB-INF/web.xml

index 532ee3e..75f8904 100644 (file)
@@ -2411,7 +2411,7 @@ errors:
       # %1 - property name
         code: 400,
         message: 'Error: Invalid Content. %1 has invalid format.',
-        messageId: "SVC4723"
+        messageId: "SVC4731"
     }
     #---------SVC4734------------------------------
     # %1 - list of validation errors
@@ -2822,6 +2822,13 @@ errors:
         message: "Capability '%1' not found in '%2' '%3'."
         messageId: "SVC4186"
 
+    #---------SVC4001------------------------------
+    NOT_PERMITTED_SPECIAL_CHARS: {
+        code: 406,
+        message: 'Error: HTML elements not permitted in field values.',
+        messageId: "SVC4001"
+    }
+
     # %1 - The data type Uid
     DATA_TYPE_NOT_FOUND:
         code: 404
index 5706a16..9a2437c 100644 (file)
@@ -1293,5 +1293,8 @@ externalCsarStore:
 #This configuration specifies the delimiter used to differentiate instance name and count
 componentInstanceCounterDelimiter: " "
 
+# Comma separated list of excluded URLs by the DataValidatorFilter
+dataValidatorFilterExcludedUrls: "/healthCheck,/followed,/authorize"
+
 #Space separated list of permitted ancestors
 permittedAncestors: <%= @permittedAncestors %>
index e973fe4..bd0e6bb 100644 (file)
 package org.openecomp.sdc.be.components.impl.exceptions;
 
 import java.util.Arrays;
+import lombok.Getter;
 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.exception.ResponseFormat;
 
 public class ByActionStatusComponentException extends ComponentException {
 
+    @Getter
     private final ActionStatus actionStatus;
     private final String[] params;
 
@@ -35,10 +37,6 @@ public class ByActionStatusComponentException extends ComponentException {
         this.params = params.clone();
     }
 
-    public ActionStatus getActionStatus() {
-        return actionStatus;
-    }
-
     public String[] getParams() {
         return params.clone();
     }
index e40dfe4..0e8f945 100644 (file)
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
 @Component("beRestrictionAccessFilter")
 public class BeRestrictionAccessFilter extends RestrictionAccessFilter {
 
-    private static final Logger log = Logger.getLogger(RestrictionAccessFilter.class.getName());
+    private static final Logger log = Logger.getLogger(BeRestrictionAccessFilter.class.getName());
 
     public BeRestrictionAccessFilter(FilterConfiguration configuration, ThreadLocalUtils threadLocalUtils, PortalClient portalClient) {
         super(configuration, threadLocalUtils, portalClient);
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/filters/DataValidatorFilter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/filters/DataValidatorFilter.java
new file mode 100644 (file)
index 0000000..2cdbf93
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.filters;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.common.filters.DataValidatorFilterAbstract;
+import org.openecomp.sdc.common.util.DataValidator;
+import org.openecomp.sdc.exception.NotAllowedSpecialCharsException;
+
+/**
+ * Implement DataValidatorFilter for back-end.
+ * Extends {@link DataValidatorFilterAbstract}
+ */
+public class DataValidatorFilter extends DataValidatorFilterAbstract {
+
+    @Override
+    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
+        try {
+            super.doFilter(request, response, chain);
+        } catch (NotAllowedSpecialCharsException e) {
+            throw new ByActionStatusComponentException(ActionStatus.NOT_PERMITTED_SPECIAL_CHARS);
+        }
+    }
+
+    @Override
+    protected List<String> getDataValidatorFilterExcludedUrls() {
+        final String dataValidatorFilterExcludedUrls = ConfigurationManager.getConfigurationManager().getConfiguration()
+            .getDataValidatorFilterExcludedUrls();
+        if (StringUtils.isNotBlank(dataValidatorFilterExcludedUrls)) {
+            return Arrays.asList(dataValidatorFilterExcludedUrls.split(","));
+        }
+        return new ArrayList<>();
+    }
+
+}
index c5f0881..b675ec9 100644 (file)
@@ -44,7 +44,7 @@ import org.springframework.stereotype.Component;
 @Component("gatewayFilter")
 public class GatewayFilter implements Filter {
 
-    private static final Logger log = Logger.getLogger(BeServletFilter.class);
+    private static final Logger log = Logger.getLogger(GatewayFilter.class);
     private Configuration.CookieConfig authCookieConf;
     private Configuration config;
     @Autowired
index 7bec5d5..7c9101d 100644 (file)
@@ -321,10 +321,8 @@ public class BeGenericServlet extends BasicServlet {
 
     protected String propertyToJson(Map.Entry<String, PropertyDefinition> property) {
         JSONObject root = new JSONObject();
-        String propertyName = property.getKey();
         PropertyDefinition propertyDefinition = property.getValue();
-        JSONObject propertyDefinitionO = getPropertyDefinitionJSONObject(propertyDefinition);
-        root.put(propertyName, propertyDefinitionO);
+        root.put(property.getKey(), getPropertyDefinitionJSONObject(propertyDefinition));
         propertyDefinition.getType();
         return root.toString();
     }
index 18e5a15..f89a134 100644 (file)
@@ -35,7 +35,7 @@ import org.springframework.stereotype.Component;
 @Provider
 public class StorageExceptionMapper implements ExceptionMapper<StorageException> {
 
-    private static final Logger log = Logger.getLogger(DefaultExceptionMapper.class);
+    private static final Logger log = Logger.getLogger(StorageExceptionMapper.class);
     private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
     private final ComponentsUtils componentsUtils;
 
index c34d674..820034e 100644 (file)
@@ -930,3 +930,6 @@ directives:
 
 #Space separated list of permitted ancestors
 permittedAncestors: ""
+
+# Comma separated list of excluded URLs by the DataValidatorFilter
+dataValidatorFilterExcludedUrls: "/healthCheck,/followed,/authorize"
index 0081525..0830dda 100644 (file)
@@ -2411,7 +2411,7 @@ errors:
       # %1 - property name
         code: 400,
         message: 'Error: Invalid Content. %1 has invalid format.',
-        messageId: "SVC4723"
+        messageId: "SVC4731"
     }
     #---------SVC4734------------------------------
     # %1 - list of validation errors
@@ -2822,6 +2822,13 @@ errors:
         message: "Capability '%1' not found in '%2' '%3'."
         messageId: "SVC4186"
 
+    #---------SVC4001------------------------------
+    NOT_PERMITTED_SPECIAL_CHARS: {
+        code: 406,
+        message: 'Error: HTML elements not permitted in field values.',
+        messageId: "SVC4001"
+    }
+
     # %1 - The data type Uid
     DATA_TYPE_NOT_FOUND:
         code: 404
index 7cbfd1a..9761b38 100644 (file)
@@ -20,6 +20,7 @@
                 org.glassfish.jersey.media.multipart.MultiPartFeature,
                 org.openecomp.sdc.be.filters.BasicAuthenticationFilter,
                 org.openecomp.sdc.be.filters.BeServletFilter,
+                org.openecomp.sdc.be.filters.DataValidatorFilter,
                 org.openecomp.sdc.be.filters.ComponentsAvailabilityFilter,
                 org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature,
                 org.openecomp.sdc.be.servlets.exception.DefaultExceptionMapper,
@@ -59,6 +60,7 @@
             <param-value>
                 org.glassfish.jersey.media.multipart.MultiPartFeature,
                 org.openecomp.sdc.be.filters.BeServletFilter,
+                org.openecomp.sdc.be.filters.DataValidatorFilter,
                 org.openecomp.sdc.be.filters.ComponentsAvailabilityFilter,
                 org.openecomp.sdc.be.servlets.exception.DefaultExceptionMapper,
                 org.openecomp.sdc.be.servlets.exception.ComponentExceptionMapper,
         <url-pattern>/sdc/*</url-pattern>
     </filter-mapping>
 
+    <filter>
+        <filter-name>dataValidatorFilter</filter-name>
+        <filter-class>
+            org.openecomp.sdc.be.filters.DataValidatorFilter
+        </filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>dataValidatorFilter</filter-name>
+        <url-pattern>/sdc2/rest/*</url-pattern>
+        <url-pattern>/sdc/*</url-pattern>
+    </filter-mapping>
+
     <error-page>
         <exception-type>java.lang.RuntimeException</exception-type>
         <location>/sdc2/rest/v1/catalog/handleException/</location>
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/utils/DataValidatorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/utils/DataValidatorTest.java
new file mode 100644 (file)
index 0000000..8804e49
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.servlets.utils;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.common.util.DataValidator;
+import org.openecomp.sdc.common.util.SecureString;
+
+@ExtendWith(MockitoExtension.class)
+class DataValidatorTest {
+
+    @InjectMocks
+    private DataValidator dataValidator;
+
+    @Test
+    void isValidSecureString() {
+        final SecureString secureString = new SecureString("<script>alert(“XSS”);</script>");
+        assertFalse(dataValidator.isValid(secureString));
+    }
+
+    @Test
+    void isValidEPUser() {
+        final User user = new User();
+        user.setEmail("“><script>alert(“XSS”)</script>");
+        user.setUserId("<IMG SRC=”javascript:alert(‘XSS’);”>");
+        user.setFirstName("<IMG SRC=javascript:alert(‘XSS’)> ");
+        assertFalse(dataValidator.isValid(user));
+    }
+
+}
index 2c7c724..55297f9 100644 (file)
@@ -22,7 +22,7 @@ package org.openecomp.sdc.be.dao.api;
 
 public enum ActionStatus {
     OK, ACCEPTED, CREATED, NO_CONTENT, GENERAL_ERROR, NOT_ALLOWED, MISSING_INFORMATION, RESTRICTED_OPERATION,
-    RESTRICTED_ACCESS, INVALID_CONTENT, INVALID_PROPERTY_VALUES, NOT_SUPPORTED, INVALID_ARTIFACT_LABEL_NAME,
+    RESTRICTED_ACCESS, INVALID_CONTENT, INVALID_PROPERTY_VALUES, NOT_SUPPORTED, INVALID_ARTIFACT_LABEL_NAME, NOT_PERMITTED_SPECIAL_CHARS,
     // User related
     USER_ALREADY_EXIST, USER_INACTIVE, USER_NOT_FOUND, USER_HAS_ACTIVE_ELEMENTS, INVALID_EMAIL_ADDRESS, INVALID_ROLE, DELETE_USER_ADMIN_CONFLICT, UPDATE_USER_ADMIN_CONFLICT, CANNOT_DELETE_USER_WITH_ACTIVE_ELEMENTS, CANNOT_UPDATE_USER_WITH_ACTIVE_ELEMENTS, INVALID_USER_ID, USER_DEFINED,
     // CapabilityType related
diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/filters/DataValidatorFilter.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/filters/DataValidatorFilter.java
new file mode 100644 (file)
index 0000000..5b82a3c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.fe.filters;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.openecomp.sdc.common.filters.DataValidatorFilterAbstract;
+import org.openecomp.sdc.exception.NotAllowedSpecialCharsException;
+import org.openecomp.sdc.fe.config.Configuration;
+import org.openecomp.sdc.fe.config.ConfigurationManager;
+
+/**
+ * Implement DataValidatorFilter for front-end.
+ * Extends {@link DataValidatorFilterAbstract}
+ */
+public class DataValidatorFilter extends DataValidatorFilterAbstract {
+
+    @Override
+    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+        throws IOException, ServletException, NotAllowedSpecialCharsException {
+        try {
+            super.doFilter(request, response, chain);
+        } catch (final NotAllowedSpecialCharsException e) {
+            // error handing to show 'Error: Special characters not allowed.'
+            ((HttpServletResponse) response).sendError(400, DataValidatorFilter.ERROR_SPECIAL_CHARACTERS_NOT_ALLOWED);
+        }
+
+    }
+
+    @Override
+    protected List<String> getDataValidatorFilterExcludedUrls() {
+        final ConfigurationManager configurationManager = ConfigurationManager.getConfigurationManager();
+        if (configurationManager != null) {
+            final Configuration configuration = configurationManager.getConfiguration();
+            if (configuration != null) {
+                final String dataValidatorFilterExcludedUrls = configuration.getDataValidatorFilterExcludedUrls();
+                if (StringUtils.isNotBlank(dataValidatorFilterExcludedUrls)) {
+                    return Arrays.asList(dataValidatorFilterExcludedUrls.split(","));
+                }
+            }
+        }
+        return new ArrayList<>();
+    }
+}
index 7b83dae..72dc4aa 100644 (file)
 package org.openecomp.sdc.be.model;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.openecomp.sdc.be.dao.utils.UserStatusEnum;
-import org.openecomp.sdc.be.resources.data.UserData;
+import org.openecomp.sdc.common.util.NoHtml;
 
 @JsonInclude
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+@EqualsAndHashCode
 public class User {
 
     public static final String FORCE_DELETE_HEADER_FLAG = "FORCE_DELETE";
+    @NoHtml
     private String firstName;
+    @NoHtml
     private String lastName;
+    @NoHtml
     private String userId;
+    @NoHtml
     private String email;
+    @NoHtml
     private String role;
     private Long lastLoginTime;
+    @ToString.Exclude
+    @EqualsAndHashCode.Exclude
     private UserStatusEnum status = UserStatusEnum.ACTIVE;
 
-    public User() {
-    }
-
     public User(String userId) {
         this.userId = userId;
     }
 
-    public User(UserData userDate) {
-        this(userDate.getFirstName(), userDate.getLastName(), userDate.getUserId(), userDate.getEmail(), userDate.getRole(),
-            userDate.getLastLoginTime());
-    }
-
     public User(String firstName, String lastName, String userId, String emailAddress, String role, Long lastLoginTime) {
         this.firstName = firstName;
         this.lastName = lastName;
@@ -74,46 +83,6 @@ public class User {
         this.lastLoginTime = other.getLastLoginTime();
     }
 
-    public String getFirstName() {
-        return firstName;
-    }
-
-    public void setFirstName(String firstName) {
-        this.firstName = firstName;
-    }
-
-    public String getLastName() {
-        return lastName;
-    }
-
-    public void setLastName(String lastName) {
-        this.lastName = lastName;
-    }
-
-    public String getUserId() {
-        return userId;
-    }
-
-    public void setUserId(String userId) {
-        this.userId = userId;
-    }
-
-    public String getEmail() {
-        return email;
-    }
-
-    public void setEmail(String email) {
-        this.email = email;
-    }
-
-    public String getRole() {
-        return role;
-    }
-
-    public void setRole(String role) {
-        this.role = role;
-    }
-
     public String getFullName() {
         return this.getFirstName() + " " + this.getLastName();
     }
@@ -123,95 +92,4 @@ public class User {
         this.lastLoginTime = now.getMillis();
     }
 
-    public Long getLastLoginTime() {
-        return this.lastLoginTime;
-    }
-
-    public void setLastLoginTime(Long time) {
-        this.lastLoginTime = time;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
-        result = prime * result + ((email == null) ? 0 : email.hashCode());
-        result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
-        result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
-        result = prime * result + ((role == null) ? 0 : role.hashCode());
-        result = prime * result + ((lastLoginTime == null) ? 0 : lastLoginTime.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        User other = (User) obj;
-        if (userId == null) {
-            if (other.userId != null) {
-                return false;
-            }
-        } else if (!userId.equals(other.userId)) {
-            return false;
-        }
-        if (email == null) {
-            if (other.email != null) {
-                return false;
-            }
-        } else if (!email.equals(other.email)) {
-            return false;
-        }
-        if (firstName == null) {
-            if (other.firstName != null) {
-                return false;
-            }
-        } else if (!firstName.equals(other.firstName)) {
-            return false;
-        }
-        if (lastName == null) {
-            if (other.lastName != null) {
-                return false;
-            }
-        } else if (!lastName.equals(other.lastName)) {
-            return false;
-        }
-        if (role == null) {
-            if (other.role != null) {
-                return false;
-            }
-        } else if (!role.equals(other.role)) {
-            return false;
-        }
-        if (lastLoginTime == null) {
-            if (other.lastLoginTime != null) {
-                return false;
-            }
-        } else if (!lastLoginTime.equals(other.lastLoginTime)) {
-            return false;
-        }
-        return true;
-    }
-
-    public UserStatusEnum getStatus() {
-        return status;
-    }
-
-    public void setStatus(UserStatusEnum status) {
-        this.status = status;
-    }
-
-    @Override
-    public String toString() {
-        return "User [firstName=" + firstName + ", lastName=" + lastName + ", userId=" + userId + ", email=" + email + ", role=" + role
-            + ", last login time=" + lastLoginTime + "]";
-    }
 }
index 13684e1..50fcd41 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed 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.
@@ -23,228 +23,226 @@ package org.openecomp.sdc.be.model;
 import org.junit.Assert;
 import org.junit.Test;
 import org.openecomp.sdc.be.dao.utils.UserStatusEnum;
-import org.openecomp.sdc.be.resources.data.UserData;
 
 public class UserTest {
 
-       private User createTestSubject() {
-               return new User();
-       }
-
-       @Test
-       public void testCtor() throws Exception {
-               new User(new User());
-               new User(new UserData());
-               new User("mock", "mock", "mock", "mock", "mock", 0L);
-       }
-       
-       @Test
-       public void testCopyData() throws Exception {
-               User testSubject;
-               User other = null;
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.copyData(other);
-               testSubject.copyData(new User());
-       }
-
-       @Test
-       public void testGetFirstName() throws Exception {
-               User testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getFirstName();
-       }
-
-       @Test
-       public void testSetFirstName() throws Exception {
-               User testSubject;
-               String firstName = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setFirstName(firstName);
-       }
-
-       @Test
-       public void testGetLastName() throws Exception {
-               User testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getLastName();
-       }
-
-       @Test
-       public void testSetLastName() throws Exception {
-               User testSubject;
-               String lastName = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setLastName(lastName);
-       }
-
-       @Test
-       public void testGetUserId() throws Exception {
-               User testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getUserId();
-       }
-
-       @Test
-       public void testSetUserId() throws Exception {
-               User testSubject;
-               String userId = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setUserId(userId);
-       }
-
-       @Test
-       public void testGetEmail() throws Exception {
-               User testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getEmail();
-       }
-
-       @Test
-       public void testSetEmail() throws Exception {
-               User testSubject;
-               String email = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setEmail(email);
-       }
-
-       @Test
-       public void testGetRole() throws Exception {
-               User testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getRole();
-       }
-
-       @Test
-       public void testSetRole() throws Exception {
-               User testSubject;
-               String role = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setRole(role);
-       }
-
-       @Test
-       public void testGetFullName() throws Exception {
-               User testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getFullName();
-       }
-
-       @Test
-       public void testSetLastLoginTime() throws Exception {
-               User testSubject;
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setLastLoginTime();
-       }
-
-       @Test
-       public void testSetLastLoginTime_1() throws Exception {
-               User testSubject;
-               Long time = null;
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setLastLoginTime(time);
-       }
-
-       @Test
-       public void testGetLastLoginTime() throws Exception {
-               User testSubject;
-               Long result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getLastLoginTime();
-       }
-
-       @Test
-       public void testHashCode() throws Exception {
-               User testSubject;
-               int result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.hashCode();
-       }
-
-       @Test
-       public void testEquals() throws Exception {
-               User testSubject;
-               Object obj = null;
-               boolean result;
-
-               // test 1
-               testSubject = createTestSubject();
-               result = testSubject.equals(obj);
-               Assert.assertEquals(false, result);
-
-               result = testSubject.equals(new Object());
-               Assert.assertEquals(false, result);
-               
-               result = testSubject.equals(testSubject);
-               Assert.assertEquals(true, result);
-               result = testSubject.equals(createTestSubject());
-               Assert.assertEquals(true, result);
-       }
-
-       @Test
-       public void testGetStatus() throws Exception {
-               User testSubject;
-               UserStatusEnum result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getStatus();
-       }
-
-       @Test
-       public void testSetStatus() throws Exception {
-               User testSubject;
-               UserStatusEnum status = null;
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setStatus(status);
-       }
-
-       @Test
-       public void testToString() throws Exception {
-               User testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.toString();
-       }
+    private User createTestSubject() {
+        return new User();
+    }
+
+    @Test
+    public void testCtor() throws Exception {
+        new User(new User());
+        new User("mock", "mock", "mock", "mock", "mock", 0L);
+    }
+
+    @Test
+    public void testCopyData() throws Exception {
+        User testSubject;
+        User other = null;
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.copyData(other);
+        testSubject.copyData(new User());
+    }
+
+    @Test
+    public void testGetFirstName() throws Exception {
+        User testSubject;
+        String result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.getFirstName();
+    }
+
+    @Test
+    public void testSetFirstName() throws Exception {
+        User testSubject;
+        String firstName = "";
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.setFirstName(firstName);
+    }
+
+    @Test
+    public void testGetLastName() throws Exception {
+        User testSubject;
+        String result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.getLastName();
+    }
+
+    @Test
+    public void testSetLastName() throws Exception {
+        User testSubject;
+        String lastName = "";
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.setLastName(lastName);
+    }
+
+    @Test
+    public void testGetUserId() throws Exception {
+        User testSubject;
+        String result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.getUserId();
+    }
+
+    @Test
+    public void testSetUserId() throws Exception {
+        User testSubject;
+        String userId = "";
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.setUserId(userId);
+    }
+
+    @Test
+    public void testGetEmail() throws Exception {
+        User testSubject;
+        String result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.getEmail();
+    }
+
+    @Test
+    public void testSetEmail() throws Exception {
+        User testSubject;
+        String email = "";
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.setEmail(email);
+    }
+
+    @Test
+    public void testGetRole() throws Exception {
+        User testSubject;
+        String result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.getRole();
+    }
+
+    @Test
+    public void testSetRole() throws Exception {
+        User testSubject;
+        String role = "";
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.setRole(role);
+    }
+
+    @Test
+    public void testGetFullName() throws Exception {
+        User testSubject;
+        String result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.getFullName();
+    }
+
+    @Test
+    public void testSetLastLoginTime() throws Exception {
+        User testSubject;
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.setLastLoginTime();
+    }
+
+    @Test
+    public void testSetLastLoginTime_1() throws Exception {
+        User testSubject;
+        Long time = null;
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.setLastLoginTime(time);
+    }
+
+    @Test
+    public void testGetLastLoginTime() throws Exception {
+        User testSubject;
+        Long result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.getLastLoginTime();
+    }
+
+    @Test
+    public void testHashCode() throws Exception {
+        User testSubject;
+        int result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.hashCode();
+    }
+
+    @Test
+    public void testEquals() throws Exception {
+        User testSubject;
+        Object obj = null;
+        boolean result;
+
+        // test 1
+        testSubject = createTestSubject();
+        result = testSubject.equals(obj);
+        Assert.assertEquals(false, result);
+
+        result = testSubject.equals(new Object());
+        Assert.assertEquals(false, result);
+
+        result = testSubject.equals(testSubject);
+        Assert.assertEquals(true, result);
+        result = testSubject.equals(createTestSubject());
+        Assert.assertEquals(true, result);
+    }
+
+    @Test
+    public void testGetStatus() throws Exception {
+        User testSubject;
+        UserStatusEnum result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.getStatus();
+    }
+
+    @Test
+    public void testSetStatus() throws Exception {
+        User testSubject;
+        UserStatusEnum status = null;
+
+        // default test
+        testSubject = createTestSubject();
+        testSubject.setStatus(status);
+    }
+
+    @Test
+    public void testToString() throws Exception {
+        User testSubject;
+        String result;
+
+        // default test
+        testSubject = createTestSubject();
+        result = testSubject.toString();
+    }
 }
index 75ee2d5..3b6575c 100644 (file)
@@ -23,6 +23,6 @@
         testId="instanceName"></sdc-input>
      <sdc-validation [validateElement]="updateNameInput" (validityChanged)="validityChanged($event)">
         <sdc-required-validator message="Name is required."></sdc-required-validator>
-        <sdc-regex-validator message="Special characters not allowed." [pattern]="pattern"></sdc-regex-validator>
+        <sdc-regex-validator message="HTML elements not permitted in field values." [pattern]="pattern"></sdc-regex-validator>
     </sdc-validation>
 </div>
\ No newline at end of file
index d5b9d9e..9d38195 100644 (file)
@@ -7,7 +7,7 @@
             [placeHolder]="'Enter Name'">
         </sdc-input>
         <sdc-validation [validateElement]="heatName">
-            <sdc-regex-validator [message]="'Special characters not allowed.'" [pattern]="pattern"></sdc-regex-validator>
+            <sdc-regex-validator [message]="'HTML elements not permitted in field values.'" [pattern]="pattern"></sdc-regex-validator>
         </sdc-validation>
     </div>
     <div class="edit-module-name-label module-name" data-tests-id="'popover-module-name'" sdc-tooltip [tooltip-text]="selectModule.moduleName">{{selectModule.moduleName}}</div>
index c3a6bc9..fc5445a 100644 (file)
@@ -4,7 +4,7 @@
   "VALIDATION_ERROR_MAX_LENGTH": "Max length {{max}} characters.",
   "VALIDATION_ERROR_MIN_LENGTH": "Min length {{min}} characters.",
   "VALIDATION_ERROR_REQUIRED": "{{field}} is required.",
-  "VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED": "Special characters not allowed.",
+  "VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED": "HTML elements not permitted in field values.",
   "LABEL_MAX_SIZE_XX": "Max size is up to {{size}}",
   "LABEL_ALL_FIELDS_ARE_MANDATORY": "All fields are mandatory.",
   "VALIDATION_ERROR_BOOLEAN": "Value should be 'TRUE' or 'FALSE'.",
   "NEW_SERVICE_RESOURCE_ERROR_MAX_LENGTH_128": "Max length 128 characters.",
   "NEW_SERVICE_RESOURCE_ERROR_MAX_LENGTH_1024": "Max length 1024 characters.",
   "NEW_SERVICE_RESOURCE_ERROR_NAME_EXISTS": "Name already exists.",
-  "NEW_SERVICE_RESOURCE_ERROR_SPECIAL_CHARS": "Special characters not allowed.",
+  "NEW_SERVICE_RESOURCE_ERROR_SPECIAL_CHARS": "HTML elements not permitted in field values.",
   "NEW_SERVICE_RESOURCE_ERROR_CATEGORY_REQUIRED": "category is required.",
   "NEW_SERVICE_RESOURCE_ERROR_CATEGORY_NOT_VALID": "Category not valid for base type.",
   "NEW_SERVICE_RESOURCE_ERROR_CONTACT_REQUIRED": "Contact is required.",
index da849f3..f2bad70 100644 (file)
@@ -147,6 +147,7 @@ public class Configuration extends BasicConfiguration {
     private ExternalCsarStore externalCsarStore;
     private CsarFormat csarFormat;
     private String componentInstanceCounterDelimiter;
+    private String dataValidatorFilterExcludedUrls; // Comma separated list of excluded URLs by the DataValidatorFilter
     private String permittedAncestors; // Space separated list of permitted ancestors
 
     @SuppressWarnings("unchecked")
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/filters/DataValidatorFilterAbstract.java b/common-app-api/src/main/java/org/openecomp/sdc/common/filters/DataValidatorFilterAbstract.java
new file mode 100644 (file)
index 0000000..44c0cbb
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.filters;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.HttpMethod;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.openecomp.sdc.common.util.DataValidator;
+import org.openecomp.sdc.common.util.SecureString;
+import org.openecomp.sdc.exception.NotAllowedSpecialCharsException;
+
+/**
+ * Provides mechanism to filter request according to {@link DataValidator} and {@code dataValidatorFilterExcludedUrlsList}.
+ */
+public abstract class DataValidatorFilterAbstract implements Filter {
+
+    protected static final String DATA_VALIDATOR_FILTER_EXCLUDED_URLS = "dataValidatorFilterExcludedUrls";
+    protected static final String ERROR_SPECIAL_CHARACTERS_NOT_ALLOWED = "Error: HTML elements not permitted in field values.";
+    private DataValidator dataValidator;
+
+    @Override
+    public void init(final FilterConfig filterConfig) throws ServletException {
+        dataValidator = new DataValidator();
+    }
+
+    @Override
+    public void destroy() {
+        dataValidator = null;
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, final ServletResponse response, final FilterChain chain)
+        throws IOException, ServletException {
+        if (isExcluded(((HttpServletRequest) request).getRequestURI()) || !isPostOrPut(((HttpServletRequest) request).getMethod())) {
+            chain.doFilter(request, response);
+        } else {
+            if (!skipCheckBody((HttpServletRequest) request)) {
+                request = new RequestWrapper((HttpServletRequest) request);
+            }
+            if (isValid((HttpServletRequest) request)) {
+                chain.doFilter(request, response);
+            } else {
+                throw new NotAllowedSpecialCharsException();
+            }
+        }
+    }
+
+    private boolean isPostOrPut(final String method) {
+        return method.equals(HttpMethod.POST) || method.equals(HttpMethod.PUT);
+    }
+
+    private boolean isExcluded(final String path) {
+        final List<String> dataValidatorFilterExcludedUrlsList = getDataValidatorFilterExcludedUrls();
+        return CollectionUtils.isNotEmpty(dataValidatorFilterExcludedUrlsList)
+            && dataValidatorFilterExcludedUrlsList.stream().anyMatch(s -> path.trim().contains(s.trim()));
+    }
+
+    protected abstract List<String> getDataValidatorFilterExcludedUrls();
+
+    private boolean skipCheckBody(final HttpServletRequest requestWrapper) {
+        final String contentType = requestWrapper.getContentType();
+        return StringUtils.isNotEmpty(contentType) && contentType.contains("multipart/form-data");
+    }
+
+    private boolean isValid(final HttpServletRequest request) {
+        final boolean skipCheckBody = skipCheckBody(request);
+        return (skipCheckBody || checkBody((RequestWrapper) request))
+            && checkHeaders(request)
+            && checkCookies(request)
+            && checkParameters(request)
+            && checkQuery(request);
+    }
+
+    private boolean checkParameters(final HttpServletRequest httpRequest) {
+        final Iterator<String> parameterNamesIterator = httpRequest.getParameterNames().asIterator();
+        while (parameterNamesIterator.hasNext()) {
+            final String parameterName = parameterNamesIterator.next();
+            final String parameter = httpRequest.getParameter(parameterName);
+            if (!dataValidator.isValid(new SecureString(parameter))) {
+                return false;
+            }
+            final String[] parameterValues = httpRequest.getParameterValues(parameterName);
+            if (parameterValues != null) {
+                for (final String parameterValue : parameterValues) {
+                    if (!dataValidator.isValid(new SecureString(parameterValue))) {
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean checkHeaders(final HttpServletRequest httpRequest) {
+        final Iterator<String> headerNamesIterator = httpRequest.getHeaderNames().asIterator();
+        while (headerNamesIterator.hasNext()) {
+            final String headerName = headerNamesIterator.next();
+            final String header = httpRequest.getHeader(headerName);
+            if (!dataValidator.isValid(new SecureString(header))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean checkCookies(final HttpServletRequest httpRequest) {
+        final Cookie[] cookies = httpRequest.getCookies();
+        if (cookies != null) {
+            for (final Cookie cookie : cookies) {
+                if (!dataValidator.isValid(new SecureString(cookie.getValue()))) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean checkQuery(final HttpServletRequest httpRequest) {
+        final String queryString = httpRequest.getQueryString();
+        return StringUtils.isEmpty(queryString) || dataValidator.isValid(new SecureString(queryString));
+    }
+
+    private boolean checkBody(final RequestWrapper httpRequest) {
+        final String body = httpRequest.getBody();
+        return StringUtils.isEmpty(body) || dataValidator.isValid(new SecureString(body));
+    }
+
+}
+
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/filters/RequestWrapper.java b/common-app-api/src/main/java/org/openecomp/sdc/common/filters/RequestWrapper.java
new file mode 100644 (file)
index 0000000..79ef42d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.filters;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import lombok.Getter;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+
+/**
+ * Provides mechanism to wrap request's InputStream and read it more than once.
+ */
+public class RequestWrapper extends HttpServletRequestWrapper {
+
+    private static final Logger LOGGER = Logger.getLogger(RequestWrapper.class);
+
+    @Getter
+    private final String body;
+
+    public RequestWrapper(final HttpServletRequest request) throws IOException {
+        //So that other request method behave just like before
+        super(request);
+
+        final StringBuilder stringBuilder = new StringBuilder();
+        try (final InputStream inputStream = request.getInputStream();
+            final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
+            final char[] charBuffer = new char[128];
+            int bytesRead;
+            while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+                stringBuilder.append(charBuffer, 0, bytesRead);
+            }
+        } catch (IOException ex) {
+            LOGGER.warn(EcompLoggerErrorCode.UNKNOWN_ERROR, RequestWrapper.class.getName(), "Failed to read InputStream from request", ex);
+            throw ex;
+        }
+        //Store request body content in 'body' variable
+        body = stringBuilder.toString();
+    }
+
+    @Override
+    public String getParameter(final String name) {
+        if (body.contains(name) && super.getParameter(name) == null) {
+            final String[] split = body.split("&");
+            return Arrays.stream(split).filter(s -> s.contains(name)).findFirst().get().replace(name + '=', "");
+        } else {
+            return super.getParameter(name);
+        }
+    }
+
+    @Override
+    public ServletInputStream getInputStream() {
+        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
+        return new ServletInputStream() {
+            @Override
+            public boolean isFinished() {
+                return false;
+            }
+
+            @Override
+            public boolean isReady() {
+                return true;
+            }
+
+            @Override
+            public void setReadListener(final ReadListener readListener) {
+                // Nothing to override
+            }
+
+            public int read() {
+                return byteArrayInputStream.read();
+            }
+        };
+    }
+
+    @Override
+    public BufferedReader getReader() {
+        return new BufferedReader(new InputStreamReader(this.getInputStream()));
+    }
+
+}
index 658f095..baee946 100644 (file)
@@ -24,5 +24,5 @@ import com.google.gson.GsonBuilder;
 
 public abstract class BasicServlet {
 
-    protected Gson gson = new GsonBuilder().setPrettyPrinting().create();
+    protected final Gson gson = new GsonBuilder().setPrettyPrinting().create();
 }
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/DataValidator.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/DataValidator.java
new file mode 100644 (file)
index 0000000..58b4a87
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.util;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+
+/**
+ * Provides mechanism to validate input for Constraint Violations. For more info see {@link ValidatorFactory}, {@link ConstraintViolation},
+ * {@link Validator}.
+ */
+public class DataValidator {
+
+    private final ValidatorFactory validatorFactory;
+
+    public DataValidator() {
+        validatorFactory = Validation.buildDefaultValidatorFactory();
+    }
+
+    private <E> Set<ConstraintViolation<E>> getConstraintViolations(E classToValid) {
+        final Validator validator = validatorFactory.getValidator();
+        return validator.validate(classToValid);
+    }
+
+    /**
+     * Validates input for Constraint Violations
+     *
+     * @param classToValid - class to validate
+     * @param <E>
+     * @return true if input is valid, false if not
+     */
+    public <E> boolean isValid(E classToValid) {
+        return getConstraintViolations(classToValid).isEmpty();
+    }
+
+}
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/NoHtml.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/NoHtml.java
new file mode 100644 (file)
index 0000000..f1e9d6d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.util;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * Provides mechanism to annotate METHOD and/or FIELD to be validated by {@link NoHtmlValidator}.
+ */
+@Documented
+@Constraint(validatedBy = NoHtmlValidator.class)
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+public @interface NoHtml {
+
+    String message() default "Unsafe html content";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/NoHtmlValidator.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/NoHtmlValidator.java
new file mode 100644 (file)
index 0000000..38d4e7d
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.util;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import org.jsoup.Jsoup;
+import org.jsoup.safety.Safelist;
+
+/**
+ * Provides mechanism to check if code annotated with {@link NoHtml} contains no html.
+ */
+public class NoHtmlValidator implements ConstraintValidator<NoHtml, String> {
+
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext ctx) {
+        return value == null || Jsoup.isValid(value, Safelist.none());
+    }
+}
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/SecureString.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/SecureString.java
new file mode 100644 (file)
index 0000000..97afcb5
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.util;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Provides wrapper for string to be checked by {@link DataValidator}.
+ */
+@Getter
+@AllArgsConstructor
+public class SecureString {
+
+    @NoHtml
+    private String data;
+
+}
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/exception/NotAllowedSpecialCharsException.java b/common-app-api/src/main/java/org/openecomp/sdc/exception/NotAllowedSpecialCharsException.java
new file mode 100644 (file)
index 0000000..39a59ae
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.exception;
+
+
+import lombok.Getter;
+
+@Getter
+public class NotAllowedSpecialCharsException extends RuntimeException {
+
+    private static final String ERROR_SPECIAL_CHARACTERS_NOT_ALLOWED = "Error: HTML elements not permitted in field values.";
+    private final String errorId;
+    private final String message;
+
+    public NotAllowedSpecialCharsException() {
+        this.errorId = "NOT_PERMITTED_SPECIAL_CHARS";
+        this.message = ERROR_SPECIAL_CHARACTERS_NOT_ALLOWED;
+    }
+
+}
index 279f183..4c97a4a 100644 (file)
@@ -75,6 +75,7 @@ public class Configuration extends BasicConfiguration {
     private List<List<String>> identificationHeaderFields;
     private List<List<String>> optionalHeaderFields;
     private List<String> forwardHeaderFields;
+    private String dataValidatorFilterExcludedUrls; // Comma separated list of excluded URLs by the DataValidatorFilter
     private String permittedAncestors; // Space separated list of permitted ancestors
 
     public Integer getHealthCheckSocketTimeoutInMs(int defaultVal) {
index 20d164b..5de8ede 100644 (file)
@@ -976,6 +976,9 @@ BE-configuration.yaml
     definedResourceNamespace:
        - org.openecomp.resource.
 
+    # Comma separated list of excluded URLs by the DataValidatorFilter
+    dataValidatorFilterExcludedUrls: "/healthCheck,/followed,/authorize"
+
 BE-distribution-engine-configuration.yaml
 *****************************************
 
@@ -1341,6 +1344,9 @@ FE-configuration.yaml
         # What is the interval of the statistics collection
         probeIntervalInSeconds: 15
 
+    # Comma separated list of excluded URLs by the DataValidatorFilter
+    dataValidatorFilterExcludedUrls: "/healthCheck,/followed,/authorize"
+
 
 FE-plugins-configuration.yaml
 *****************************
index b51399c..f0291cb 100644 (file)
         <listener-class>org.openecomp.server.listeners.OnboardingAppStartupListener</listener-class>
     </listener>
 
+    <filter>
+        <filter-name>dataValidatorFilter</filter-name>
+        <filter-class>org.openecomp.sdc.common.filters.DataValidatorFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>dataValidatorFilter</filter-name>
+        <url-pattern>/v1.0/*</url-pattern>
+    </filter-mapping>
+
     <filter>
         <filter-name>contentSecurityPolicyHeaderFilter</filter-name>
         <filter-class>org.openecomp.sdc.common.filters.ContentSecurityPolicyHeaderFilter</filter-class>
@@ -54,6 +63,7 @@
         <filter-name>RestrictionAccessFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
+
     <!-- Spring WS Mapping -->
     <servlet>
         <servlet-name>spring-mapper</servlet-name>
         </servlet-class>
         <load-on-startup>1</load-on-startup>
     </servlet>
+    <servlet-mapping>
+        <servlet-name>spring-mapper</servlet-name>
+        <url-pattern>/ws/*</url-pattern>
+    </servlet-mapping>
     <!-- CXF -->
     <servlet>
         <servlet-name>CXFServlet</servlet-name>
-        <display-name>CXF Servlet</display-name>
         <servlet-class>
             org.apache.cxf.transport.servlet.CXFServlet
         </servlet-class>
         </init-param>
         <load-on-startup>1</load-on-startup>
     </servlet>
+    <servlet-mapping>
+        <servlet-name>CXFServlet</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
 
     <context-param>
         <param-name>org.eclipse.jetty.servlet.Default.dirAllowed</param-name>
         <param-value>false</param-value>
     </context-param>
 
-    <servlet-mapping>
-        <servlet-name>spring-mapper</servlet-name>
-        <url-pattern>/ws/*</url-pattern>
-    </servlet-mapping>
-    <servlet-mapping>
-        <servlet-name>CXFServlet</servlet-name>
-        <url-pattern>/*</url-pattern>
-    </servlet-mapping>
-
 </web-app>
index eb8bd9e..31400f8 100644 (file)
         <listener-class>org.openecomp.server.listeners.OnboardingAppStartupListener</listener-class>
     </listener>
 
+    <filter>
+        <filter-name>dataValidatorFilter</filter-name>
+        <filter-class>org.openecomp.sdc.common.filters.DataValidatorFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>dataValidatorFilter</filter-name>
+        <url-pattern>/v1.0/*</url-pattern>
+    </filter-mapping>
+
     <filter>
         <filter-name>contentSecurityPolicyHeaderFilter</filter-name>
-        <filter-class>org.openecomp.sdc.common.filters.ContentSecurityPolicyHeaderFilter</filter-class>
+        <filter-class>org.openecomp.sdc.common.filters.ContentSecurityPolicyHeaderFilter
+        </filter-class>
         <async-supported>true</async-supported>
     </filter>
     <filter-mapping>
@@ -41,9 +51,6 @@
     <filter-mapping>
         <filter-name>PermissionsFilter</filter-name>
         <url-pattern>/v1.0/vendor-license-models/*</url-pattern>
-    </filter-mapping>
-    <filter-mapping>
-        <filter-name>PermissionsFilter</filter-name>
         <url-pattern>/v1.0/vendor-software-products/*</url-pattern>
     </filter-mapping>
 
             <param-value>*</param-value>
         </init-param>
     </filter>
+    <filter-mapping>
+        <filter-name>cross-origin</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
 
     <filter>
         <filter-name>RestrictionAccessFilter</filter-name>
         <filter-name>RestrictionAccessFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
+
     <filter>
         <filter-name>BasicAuth</filter-name>
         <filter-class>org.openecomp.server.filters.BasicAuthenticationFilter</filter-class>
     </filter>
-    <filter>
-        <filter-name>AuthN</filter-name>
-        <filter-class>org.openecomp.server.filters.ActionAuthenticationFilter</filter-class>
-    </filter>
-    <filter>
-        <filter-name>AuthZ</filter-name>
-        <filter-class>org.openecomp.server.filters.ActionAuthorizationFilter</filter-class>
-    </filter>
-    <filter-mapping>
-        <filter-name>cross-origin</filter-name>
-        <url-pattern>/*</url-pattern>
-    </filter-mapping>
     <filter-mapping>
         <filter-name>BasicAuth</filter-name>
         <url-pattern>/1.0/*</url-pattern>
     </filter-mapping>
+
+    <filter>
+        <filter-name>AuthN</filter-name>
+        <filter-class>org.openecomp.server.filters.ActionAuthenticationFilter</filter-class>
+    </filter>
     <filter-mapping>
         <filter-name>AuthN</filter-name>
         <url-pattern>/workflow/v1.0/actions/*</url-pattern>
     </filter-mapping>
+
+    <filter>
+        <filter-name>AuthZ</filter-name>
+        <filter-class>org.openecomp.server.filters.ActionAuthorizationFilter</filter-class>
+    </filter>
     <filter-mapping>
         <filter-name>AuthZ</filter-name>
         <url-pattern>/workflow/v1.0/actions/*</url-pattern>
     </filter-mapping>
+
     <filter>
         <filter-name>SessionContextFilter</filter-name>
         <filter-class>org.openecomp.server.filters.OnboardingSessionContextFilter</filter-class>
         <filter-name>SessionContextFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
+
     <!-- Spring WS Mapping -->
     <servlet>
         <servlet-name>spring-mapper</servlet-name>
         </servlet-class>
         <load-on-startup>1</load-on-startup>
     </servlet>
+    <servlet-mapping>
+        <servlet-name>spring-mapper</servlet-name>
+        <url-pattern>/ws/*</url-pattern>
+    </servlet-mapping>
     <!-- CXF -->
     <servlet>
         <servlet-name>CXFServlet</servlet-name>
         </init-param>
         <load-on-startup>1</load-on-startup>
     </servlet>
-    <servlet-mapping>
-        <servlet-name>spring-mapper</servlet-name>
-        <url-pattern>/ws/*</url-pattern>
-    </servlet-mapping>
     <servlet-mapping>
         <servlet-name>CXFServlet</servlet-name>
         <url-pattern>/*</url-pattern>
index a059434..4ad6fd7 100644 (file)
 package org.openecomp.sdc.common.errors;
 
 import com.fasterxml.jackson.databind.JsonMappingException;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.ConstraintViolation;
 import javax.validation.ConstraintViolationException;
 import javax.validation.Path;
@@ -29,8 +31,12 @@ import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.ext.ExceptionMapper;
 import org.apache.commons.collections4.CollectionUtils;
 import org.hibernate.validator.internal.engine.path.PathImpl;
+import org.onap.sdc.security.RepresentationUtils;
 import org.openecomp.core.utilities.file.FileUtils;
 import org.openecomp.core.utilities.json.JsonUtil;
+import org.openecomp.sdc.exception.NotAllowedSpecialCharsException;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.openecomp.sdc.exception.ServiceException;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
 
@@ -113,4 +119,14 @@ public class DefaultExceptionMapper implements ExceptionMapper<Exception> {
     private Object toEntity(final Status status, final ErrorCode code) {
         return new ErrorCodeAndMessage(status, code);
     }
+
+    public void writeToResponse(final NotAllowedSpecialCharsException e, final HttpServletResponse httpResponse) throws IOException {
+        final ResponseFormat responseFormat = new ResponseFormat(400);
+        responseFormat.setServiceException(new ServiceException(e.getErrorId(), e.getMessage(), new String[0]));
+        httpResponse.setStatus(responseFormat.getStatus());
+        httpResponse.setContentType("application/json");
+        httpResponse.setCharacterEncoding("UTF-8");
+        httpResponse.getWriter().write(RepresentationUtils.toRepresentation(responseFormat.getRequestError()));
+    }
+
 }
diff --git a/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/filters/DataValidatorFilter.java b/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/filters/DataValidatorFilter.java
new file mode 100644 (file)
index 0000000..6e3f665
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.filters;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.openecomp.sdc.common.CommonConfigurationManager;
+import org.openecomp.sdc.common.errors.DefaultExceptionMapper;
+import org.openecomp.sdc.exception.NotAllowedSpecialCharsException;
+
+/**
+ * Implements DataValidatorFilter for onboarding.
+ * Extends {@link DataValidatorFilterAbstract}
+ */
+public class DataValidatorFilter extends DataValidatorFilterAbstract {
+
+    private final DefaultExceptionMapper defaultExceptionMapper;
+
+    public DataValidatorFilter() {
+        defaultExceptionMapper = new DefaultExceptionMapper();
+    }
+
+    @Override
+    public void doFilter(final ServletRequest request, ServletResponse response, final FilterChain chain)
+        throws IOException, ServletException, NotAllowedSpecialCharsException {
+        try {
+            super.doFilter(request, response, chain);
+        } catch (final NotAllowedSpecialCharsException e) {
+            defaultExceptionMapper.writeToResponse(e, (HttpServletResponse) response);
+        }
+    }
+
+    @Override
+    protected List<String> getDataValidatorFilterExcludedUrls() {
+        final CommonConfigurationManager commonConfigurationManager = CommonConfigurationManager.getInstance();
+        if (commonConfigurationManager != null) {
+            final String dataValidatorFilterExcludedUrls = commonConfigurationManager.getConfigValue(DATA_VALIDATOR_FILTER_EXCLUDED_URLS, "");
+            if (StringUtils.isNotBlank(dataValidatorFilterExcludedUrls)) {
+                return Arrays.asList(dataValidatorFilterExcludedUrls.split(","));
+            }
+        }
+        return new ArrayList<>();
+    }
+
+}
index 2245aaf..74f62f5 100644 (file)
@@ -42,7 +42,7 @@ Usage -
                The migration result will be listed in a CSV file: upgradereport.csv
                "None" is an indication that the VSP was not in a checkout status prior to the upgrade.
 
-       Exmample for a valid output:
+       Example for a valid output:
 
                Name: VSP-OK, Id: 9DB0E1563B22481D911ECD33989E1FDD, Vendor: ABC, locked by: None, status not started
                Service VSP-OK was tested and does not need a migration
diff --git a/utils/webseal-simulator/src/main/java/org/openecomp/sdc/webseal/simulator/DataValidatorFilter.java b/utils/webseal-simulator/src/main/java/org/openecomp/sdc/webseal/simulator/DataValidatorFilter.java
new file mode 100644 (file)
index 0000000..a226faf
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.webseal.simulator;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.openecomp.sdc.common.filters.DataValidatorFilterAbstract;
+import org.openecomp.sdc.exception.NotAllowedSpecialCharsException;
+import org.openecomp.sdc.webseal.simulator.conf.Conf;
+
+/**
+ * Implement DataValidatorFilter for webseal.
+ * Extends {@link DataValidatorFilterAbstract}
+ */
+public class DataValidatorFilter extends DataValidatorFilterAbstract {
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws IOException, ServletException, NotAllowedSpecialCharsException {
+        try {
+            super.doFilter(request, response, chain);
+        } catch (final NotAllowedSpecialCharsException e) {
+            // error handing to show 'Error: Special characters not allowed.'
+            ((HttpServletResponse) response).sendError(400, ERROR_SPECIAL_CHARACTERS_NOT_ALLOWED);
+        }
+    }
+
+    @Override
+    protected List<String> getDataValidatorFilterExcludedUrls() {
+        String dataValidatorFilterExcludedUrls = Conf.getInstance().getDataValidatorFilterExcludedUrls();
+        if (StringUtils.isNotBlank(dataValidatorFilterExcludedUrls)) {
+            return Arrays.asList(dataValidatorFilterExcludedUrls.split(","));
+        }
+        return new ArrayList<>();
+    }
+}
index 32d8c29..292f4a3 100644 (file)
@@ -113,7 +113,7 @@ public class Login extends HttpServlet {
     }
 
     @Override
-    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
 
         String userId = request.getParameter("userId");
         String password = request.getParameter("password");
index 7aa48e6..e8c4631 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed 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.
 
 package org.openecomp.sdc.webseal.simulator;
 
-import org.apache.commons.io.IOUtils;
-import org.openecomp.sdc.webseal.simulator.conf.Conf;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.IOUtils;
+import org.openecomp.sdc.webseal.simulator.conf.Conf;
 
 public class RequestsClient extends HttpServlet {
 
-       private static final long serialVersionUID = 1L;
-
-       @Override
-       protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
-
-               String adminId = request.getParameter("adminId") != null ? request.getParameter("adminId") : "jh0003";
-               String createAll = request.getParameter("all");
-               String url = Conf.getInstance().getFeHost() + "/sdc1/feProxy/rest/v1/user";
-
-               PrintWriter writer = response.getWriter();
-               
-               int resultCode;
-               
-               if ("true".equals(createAll)) {
-                       Map<String, User> users = Conf.getInstance().getUsers();
-                       for (User user : users.values()) {
-                               resultCode = createUser(response, user.getUserId(), user.getRole().toUpperCase(), user.getFirstName(), user.getLastName(), user.getEmail(), url, adminId);
-                               writer.println("User "+ user.getFirstName() + " " + user.getLastName() + getResultMessage(resultCode) + "<br>");
-                       }
-               } else {
-                       String userId = request.getParameter("userId");
-                       String role = request.getParameter("role").toUpperCase();
-                       String firstName = request.getParameter("firstName");
-                       String lastName = request.getParameter("lastName");
-                       String email = request.getParameter("email");
-                                               
-                       resultCode = createUser(response, userId, role, firstName, lastName, email, url, adminId);
-                       
-                       writer.println("User "+ firstName + " " + lastName +getResultMessage(resultCode));      
-               }
-
-               
-
-       }
-       
-       private String getResultMessage(int resultCode){
-               return 201 == resultCode? " created successfuly":" not created ("+ resultCode +")";
-       }
-
-       private int createUser(final HttpServletResponse response, String userId, String role, String firstName, String lastName, String email, String url, String adminId) throws IOException {
-               response.setContentType("text/html");
-
-               String body = "{\"firstName\":\"" + firstName + "\", \"lastName\":\"" + lastName + "\", \"userId\":\"" + userId + "\", \"email\":\"" + email + "\",\"role\":\"" + role + "\"}";
-
-               HashMap<String, String> headers = new HashMap<String, String>();
-               headers.put("Content-Type", "application/json");
-               headers.put("USER_ID", adminId);
-               return sendHttpPost(url, body, headers);
-       }
-
-       private int sendHttpPost(String url, String body, Map<String, String> headers) throws IOException {
-
-               String responseString = "";
-               URL obj = new URL(url);
-               HttpURLConnection con = (HttpURLConnection) obj.openConnection();
-
-               // add request method
-               con.setRequestMethod("POST");
-
-               // add request headers
-               if (headers != null) {
-                       for (Entry<String, String> header : headers.entrySet()) {
-                               String key = header.getKey();
-                               String value = header.getValue();
-                               con.setRequestProperty(key, value);
-                       }
-               }
-
-               // Send post request
-               if (body != null) {
-                       con.setDoOutput(true);
-                       DataOutputStream wr = new DataOutputStream(con.getOutputStream());
-                       wr.writeBytes(body);
-                       wr.flush();
-                       wr.close();
-               }
-
-               int responseCode = con.getResponseCode();
-               // logger.debug("Send POST http request, url: {}", url);
-               // logger.debug("Response Code: {}", responseCode);
-
-               StringBuilder response = new StringBuilder();
-               try {
-                       BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
-                       String inputLine;
-                       while ((inputLine = in.readLine()) != null) {
-                               response.append(inputLine);
-                       }
-                       in.close();
-               } catch (Exception e) {
-                       // logger.debug("response body is null");
-               }
-
-               String result;
-
-               try {
-                       result = IOUtils.toString(con.getErrorStream());
-                       response.append(result);
-               } catch (Exception e2) {
-               }
-
-               con.disconnect();
-               return responseCode;
-
-       }
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
+
+        String adminId = request.getParameter("adminId") != null ? request.getParameter("adminId") : "jh0003";
+        String createAll = request.getParameter("all");
+        String url = Conf.getInstance().getFeHost() + "/sdc1/feProxy/rest/v1/user";
+
+        PrintWriter writer = response.getWriter();
+
+        int resultCode;
+
+        if ("true".equals(createAll)) {
+            Map<String, User> users = Conf.getInstance().getUsers();
+            for (User user : users.values()) {
+                resultCode = createUser(response, user.getUserId(), user.getRole().toUpperCase(), user.getFirstName(), user.getLastName(),
+                    user.getEmail(), url, adminId);
+                writer.println("User " + user.getFirstName() + " " + user.getLastName() + getResultMessage(resultCode) + "<br>");
+            }
+        } else {
+            String userId = request.getParameter("userId");
+            String role = request.getParameter("role").toUpperCase();
+            String firstName = request.getParameter("firstName");
+            String lastName = request.getParameter("lastName");
+            String email = request.getParameter("email");
+
+            resultCode = createUser(response, userId, role, firstName, lastName, email, url, adminId);
+
+            writer.println("User " + firstName + " " + lastName + getResultMessage(resultCode));
+        }
+
+    }
+
+    private String getResultMessage(int resultCode) {
+        return 201 == resultCode ? " created successfuly" : " not created (" + resultCode + ")";
+    }
+
+    private int createUser(final HttpServletResponse response, String userId, String role, String firstName, String lastName, String email,
+                           String url, String adminId) throws IOException {
+        response.setContentType("text/html");
+
+        String body = "{\"firstName\":\"" + firstName + "\", \"lastName\":\"" + lastName + "\", \"userId\":\"" + userId + "\", \"email\":\"" + email
+            + "\",\"role\":\"" + role + "\"}";
+
+        HashMap<String, String> headers = new HashMap<String, String>();
+        headers.put("Content-Type", "application/json");
+        headers.put("USER_ID", adminId);
+        return sendHttpPost(url, body, headers);
+    }
+
+    private int sendHttpPost(String url, String body, Map<String, String> headers) throws IOException {
+
+        String responseString = "";
+        URL obj = new URL(url);
+        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
+
+        // add request method
+        con.setRequestMethod("POST");
+
+        // add request headers
+        if (headers != null) {
+            for (Entry<String, String> header : headers.entrySet()) {
+                String key = header.getKey();
+                String value = header.getValue();
+                con.setRequestProperty(key, value);
+            }
+        }
+
+        // Send post request
+        if (body != null) {
+            con.setDoOutput(true);
+            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
+            wr.writeBytes(body);
+            wr.flush();
+            wr.close();
+        }
+
+        int responseCode = con.getResponseCode();
+        // logger.debug("Send POST http request, url: {}", url);
+        // logger.debug("Response Code: {}", responseCode);
+
+        StringBuilder response = new StringBuilder();
+        try {
+            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+            String inputLine;
+            while ((inputLine = in.readLine()) != null) {
+                response.append(inputLine);
+            }
+            in.close();
+        } catch (Exception e) {
+            // logger.debug("response body is null");
+        }
+
+        String result;
+
+        try {
+            result = IOUtils.toString(con.getErrorStream());
+            response.append(result);
+        } catch (Exception e2) {
+        }
+
+        con.disconnect();
+        return responseCode;
+
+    }
 
 }
index eb498c9..3ce7f23 100644 (file)
@@ -39,6 +39,7 @@ public class Conf {
     private Map<String, User> users = new HashMap<String, User>();
     private String portalCookieName;
     private String permittedAncestors; // Space separated list of permitted ancestors
+    private String dataValidatorFilterExcludedUrls; // Comma separated list of excluded URLs by the DataValidatorFilter
 
     private Conf() {
         initConf();
index c23e265..08a3222 100644 (file)
         <url-pattern>/create</url-pattern>
     </servlet-mapping>
 
+    <filter>
+        <filter-name>dataValidatorFilter</filter-name>
+        <filter-class>org.openecomp.sdc.webseal.simulator.DataValidatorFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>dataValidatorFilter</filter-name>
+        <url-pattern>/login</url-pattern>
+        <url-pattern>/create</url-pattern>
+    </filter-mapping>
+
     <filter>
         <filter-name>contentSecurityPolicyHeaderFilter</filter-name>
         <filter-class>org.openecomp.sdc.webseal.simulator.ContentSecurityPolicyHeaderFilter</filter-class>