summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuli Shlosberg <ys9693@att.com>2019-01-07 16:23:36 +0200
committerAvi Gaffa <avi.gaffa@amdocs.com>2019-01-10 10:28:39 +0000
commita4eeb110b076672b3bb88f5e2f3420ae70c78f38 (patch)
tree73a205b1afa3ffca8057931cc080ff1b372af23a
parenta1f23ec5e7cd191b76271b5f33c237bad38c61c6 (diff)
Add restriction filter to onboarding
Change-Id: Ief36760c8d89ac3443c8b12bfdef09c2f83abfc3 Issue-ID: SDC-2039 Signed-off-by: Yuli Shlosberg <ys9693@att.com>
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/action-library-rest/action-library-rest-services/artifactName0
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/notifications-fe/src/main/webapp/WEB-INF/web.xml10
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/pom.xml6
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/configuration/CookieConfig.java97
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/RestrictionAccessFilter.java150
-rw-r--r--openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml10
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/pom.xml93
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/AuthenticationCookie.java97
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/AuthenticationCookieUtils.java107
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/CipherUtil.java123
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/CipherUtilException.java66
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/ISessionValidationCookieConfiguration.java12
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/ISessionValidationFilterConfiguration.java13
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/Passwords.java187
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/RepresentationUtils.java53
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/SecurityUtil.java134
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/FilterServletOutputStream.java38
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/ResponceWrapper.java53
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/SampleFilter.java132
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/SessionValidationFilter.java194
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/test/AuthenticationCookieUtilsTest.java54
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/test/CipherUtilTest.java56
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/test/PasswordsTest.java77
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/test/RepresentationUtilsTest.java34
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/test/SecurityUtilTest.java30
-rw-r--r--openecomp-be/backend/openecomp-sdc-security-util/src/test/SessionValidationFilterTest.java157
-rw-r--r--openecomp-be/backend/pom.xml1
-rw-r--r--openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb14
28 files changed, 1997 insertions, 1 deletions
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/action-library-rest/action-library-rest-services/artifactName b/openecomp-be/api/openecomp-sdc-rest-webapp/action-library-rest/action-library-rest-services/artifactName
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/openecomp-be/api/openecomp-sdc-rest-webapp/action-library-rest/action-library-rest-services/artifactName
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/notifications-fe/src/main/webapp/WEB-INF/web.xml b/openecomp-be/api/openecomp-sdc-rest-webapp/notifications-fe/src/main/webapp/WEB-INF/web.xml
index 354fcbfac6..f0bad66222 100644
--- a/openecomp-be/api/openecomp-sdc-rest-webapp/notifications-fe/src/main/webapp/WEB-INF/web.xml
+++ b/openecomp-be/api/openecomp-sdc-rest-webapp/notifications-fe/src/main/webapp/WEB-INF/web.xml
@@ -35,6 +35,16 @@
<filter-name>cross-origin</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
+
+ <filter>
+ <filter-name>RestrictionAccessFilter</filter-name>
+ <filter-class>org.openecomp.server.filters.RestrictionAccessFilter</filter-class>
+ <async-supported>true</async-supported>
+ </filter>
+ <filter-mapping>
+ <filter-name>RestrictionAccessFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
<!-- Spring WS Mapping -->
<servlet>
<servlet-name>spring-mapper</servlet-name>
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/pom.xml b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/pom.xml
index 3b8924594d..18ec957acf 100644
--- a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/pom.xml
+++ b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/pom.xml
@@ -192,6 +192,12 @@
<artifactId>togglz-servlet</artifactId>
<version>${togglz.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.openecomp.sdc</groupId>
+ <artifactId>openecomp-sdc-security-util</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/configuration/CookieConfig.java b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/configuration/CookieConfig.java
new file mode 100644
index 0000000000..9b03f638a6
--- /dev/null
+++ b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/configuration/CookieConfig.java
@@ -0,0 +1,97 @@
+package org.openecomp.server.configuration;
+
+import java.util.List;
+
+public class CookieConfig {
+
+ String securityKey = "";
+ long maxSessionTimeOut = 600*1000;
+ long sessionIdleTimeOut = 30*1000;
+ String cookieName = "AuthenticationCookie";
+ String redirectURL = "portal_url";
+ List<String> excludedUrls;
+ List<String> onboardingExcludedUrls;
+ String domain = "";
+ String path = "";
+ boolean isHttpOnly = true;
+
+ public String getSecurityKey() {
+ return securityKey;
+ }
+
+ public void setSecurityKey(String securityKey) {
+ this.securityKey = securityKey;
+ }
+
+ public long getMaxSessionTimeOut() {
+ return maxSessionTimeOut;
+ }
+
+ public void setMaxSessionTimeOut(long maxSessionTimeOut) {
+ this.maxSessionTimeOut = maxSessionTimeOut;
+ }
+
+ public long getSessionIdleTimeOut() {
+ return sessionIdleTimeOut;
+ }
+
+ public void setSessionIdleTimeOut(long sessionIdleTimeOut) {
+ this.sessionIdleTimeOut = sessionIdleTimeOut;
+ }
+
+ public String getCookieName() {
+ return cookieName;
+ }
+
+ public void setCookieName(String cookieName) {
+ this.cookieName = cookieName;
+ }
+
+ public String getRedirectURL() {
+ return redirectURL;
+ }
+
+ public void setRedirectURL(String redirectURL) {
+ this.redirectURL = redirectURL;
+ }
+
+ public List<String> getExcludedUrls() {
+ return excludedUrls;
+ }
+
+ public void setExcludedUrls(List<String> excludedUrls) {
+ this.excludedUrls = excludedUrls;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public void setDomain(String domain) {
+ this.domain = domain;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public boolean isHttpOnly() {
+ return isHttpOnly;
+ }
+
+ public void setIsHttpOnly(boolean isHttpOnly) {
+ this.isHttpOnly = isHttpOnly;
+ }
+
+ public List<String> getOnboardingExcludedUrls() {
+ return onboardingExcludedUrls;
+ }
+
+ public void setOnboardingExcludedUrls(List<String> onboardingExcludedUrls) {
+ this.onboardingExcludedUrls = onboardingExcludedUrls;
+ }
+}
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/RestrictionAccessFilter.java b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/RestrictionAccessFilter.java
new file mode 100644
index 0000000000..02ee236ae8
--- /dev/null
+++ b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/java/org/openecomp/server/filters/RestrictionAccessFilter.java
@@ -0,0 +1,150 @@
+package org.openecomp.server.filters;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onap.sdc.tosca.services.YamlUtil;
+import org.openecomp.sdc.securityutil.ISessionValidationFilterConfiguration;
+import org.openecomp.sdc.securityutil.filters.SessionValidationFilter;
+import org.openecomp.server.configuration.CookieConfig;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+import org.openecomp.sdcrests.item.rest.services.catalog.notification.EntryNotConfiguredException;
+
+import javax.servlet.http.Cookie;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public class RestrictionAccessFilter extends SessionValidationFilter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(RestrictionAccessFilter.class);
+ private static final String CONFIG_FILE_PROPERTY = "configuration.yaml";
+ private static final String CONFIG_SECTION = "authCookie";
+
+ private static class Configuration implements ISessionValidationFilterConfiguration {
+ private static Configuration instance;
+ private String securityKey;
+ private long maxSessionTimeOut;
+ private long sessionIdleTimeOut;
+ private String cookieName;
+ private String redirectURL;
+ private List<String> excludedUrls;
+ private String cookieDomain;
+ private String cookiePath;
+ private boolean isCookieHttpOnly;
+
+
+ private Configuration() {
+ try {
+
+ String file = Objects.requireNonNull(System.getProperty(CONFIG_FILE_PROPERTY),
+ "Config file location must be specified via system property " + CONFIG_FILE_PROPERTY);
+
+ Object config = getAuthenticationConfiguration(file);
+ ObjectMapper mapper = new ObjectMapper();
+ CookieConfig cookieConfig = mapper.convertValue(config, CookieConfig.class);
+ this.securityKey = cookieConfig.getSecurityKey();
+ this.maxSessionTimeOut = cookieConfig.getMaxSessionTimeOut();
+ this.sessionIdleTimeOut = cookieConfig.getSessionIdleTimeOut();
+ this.cookieName = cookieConfig.getCookieName();
+ this.redirectURL = cookieConfig.getRedirectURL();
+ this.excludedUrls = cookieConfig.getOnboardingExcludedUrls();
+ this.cookieDomain = cookieConfig.getDomain();
+ this.cookiePath = cookieConfig.getPath();
+ this.isCookieHttpOnly = cookieConfig.isHttpOnly();
+
+ } catch (Exception e) {
+ LOGGER.warn("Failed to load configuration. ", e);
+ }
+
+ }
+
+ public static Configuration getInstance() {
+ if (instance == null) {
+ instance = new Configuration();
+ }
+ return instance;
+ }
+
+ private static Object getAuthenticationConfiguration(String file) throws IOException {
+
+ Map<?, ?> configuration = Objects.requireNonNull(readConfigurationFile(file), "Configuration cannot be empty");
+ Object authenticationConfig = configuration.get(CONFIG_SECTION);
+ if (authenticationConfig == null) {
+ throw new EntryNotConfiguredException(CONFIG_SECTION + " section");
+ }
+
+ return authenticationConfig;
+ }
+
+ private static Map<?, ?> readConfigurationFile(String file) throws IOException {
+
+ try (InputStream fileInput = new FileInputStream(file)) {
+ YamlUtil yamlUtil = new YamlUtil();
+ return yamlUtil.yamlToMap(fileInput);
+ }
+ }
+
+ @Override
+ public String getSecurityKey() {
+ return securityKey;
+ }
+
+ @Override
+ public long getMaxSessionTimeOut() {
+ return maxSessionTimeOut;
+ }
+
+ @Override
+ public long getSessionIdleTimeOut() {
+ return sessionIdleTimeOut;
+ }
+
+ @Override
+ public String getCookieName() {
+ return cookieName;
+ }
+
+ @Override
+ public String getCookieDomain() {
+ return cookieDomain;
+ }
+
+ @Override
+ public String getCookiePath() {
+ return cookiePath;
+ }
+
+ @Override
+ public boolean isCookieHttpOnly() {
+ return isCookieHttpOnly;
+ }
+
+ @Override
+ public String getRedirectURL() {
+ return redirectURL;
+ }
+
+ @Override
+ public List<String> getExcludedUrls() {
+ return excludedUrls;
+ }
+ }
+
+ @Override
+ public ISessionValidationFilterConfiguration getFilterConfiguration() {
+ return Configuration.getInstance();
+ }
+
+ @Override
+ protected Cookie addRoleToCookie(Cookie cookie) {
+ return cookie;
+ }
+
+ @Override
+ protected boolean isRoleValid(Cookie cookie) {
+ return true;
+ }
+}
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml
index b98ae4e82d..2b1b9893b3 100644
--- a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml
+++ b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/web.xml
@@ -53,6 +53,16 @@
</filter>
<filter>
+ <filter-name>RestrictionAccessFilter</filter-name>
+ <filter-class>org.openecomp.server.filters.RestrictionAccessFilter</filter-class>
+ <async-supported>true</async-supported>
+ </filter>
+ <filter-mapping>
+ <filter-name>RestrictionAccessFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter>
<filter-name>AuthN</filter-name>
<filter-class>org.openecomp.server.filters.ActionAuthenticationFilter</filter-class>
</filter>
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/pom.xml b/openecomp-be/backend/openecomp-sdc-security-util/pom.xml
new file mode 100644
index 0000000000..4bff04f9a5
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/pom.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>backend</artifactId>
+ <groupId>org.openecomp.sdc</groupId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>openecomp-sdc-security-util</artifactId>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.25</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-crypto</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.functionaljava</groupId>
+ <artifactId>functionaljava</artifactId>
+ <version>4.7</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.8.10</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.11</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>2.8.9</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.7.4</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>1.7.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project> \ No newline at end of file
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/AuthenticationCookie.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/AuthenticationCookie.java
new file mode 100644
index 0000000000..c064f3e08f
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/AuthenticationCookie.java
@@ -0,0 +1,97 @@
+package org.openecomp.sdc.securityutil;
+
+import java.util.Set;
+
+
+public class AuthenticationCookie {
+
+ private String userID;
+ private Set<String> roles;
+ private long maxSessionTime;
+ private long currentSessionTime;
+
+ public AuthenticationCookie(){ }
+
+ public AuthenticationCookie(AuthenticationCookie authenticationCookie){
+ this.userID = authenticationCookie.userID;
+ this.roles = authenticationCookie.roles;
+ this.maxSessionTime = authenticationCookie.maxSessionTime;
+ this.currentSessionTime = authenticationCookie.currentSessionTime;
+ }
+
+ /**
+ * Create new cookie with max_session_time and current_session_time started with same value
+ * @param userId
+ */
+ public AuthenticationCookie(String userId) {
+ this.userID =userId;
+ long currentTimeMilliSec = System.currentTimeMillis();
+ this.maxSessionTime = currentTimeMilliSec;
+ this.currentSessionTime = currentTimeMilliSec;
+ }
+
+ public String getUserID() {
+ return userID;
+ }
+
+ public void setUserID(String userID) {
+ this.userID = userID;
+ }
+
+ public Set getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set<String> roles) {
+ this.roles = roles;
+ }
+
+ public long getMaxSessionTime() {
+ return maxSessionTime;
+ }
+
+ public void setMaxSessionTime(long maxSessionTime) {
+ this.maxSessionTime = maxSessionTime;
+ }
+
+
+ public long getCurrentSessionTime() {
+ return currentSessionTime;
+ }
+
+ public void setCurrentSessionTime(long currentSessionTime) {
+ this.currentSessionTime = currentSessionTime;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AuthenticationCookie)) return false;
+
+ AuthenticationCookie that = (AuthenticationCookie) o;
+
+ if (getMaxSessionTime() != that.getMaxSessionTime()) return false;
+ if (getCurrentSessionTime() != that.getCurrentSessionTime()) return false;
+ if (getUserID() != null ? !getUserID().equals(that.getUserID()) : that.getUserID() != null) return false;
+ return getRoles() != null ? getRoles().containsAll(that.getRoles()) : that.getRoles() == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = getUserID() != null ? getUserID().hashCode() : 0;
+ result = 31 * result + (getRoles() != null ? getRoles().hashCode() : 0);
+ result = 31 * result + (int) (getMaxSessionTime() ^ (getMaxSessionTime() >>> 32));
+ result = 31 * result + (int) (getCurrentSessionTime() ^ (getCurrentSessionTime() >>> 32));
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "AuthenticationCookie{" +
+ "userID='" + userID + '\'' +
+ ", roles=" + roles +
+ ", maxSessionTime=" + maxSessionTime +
+ ", currentSessionTime=" + currentSessionTime +
+ '}';
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/AuthenticationCookieUtils.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/AuthenticationCookieUtils.java
new file mode 100644
index 0000000000..24225a86f9
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/AuthenticationCookieUtils.java
@@ -0,0 +1,107 @@
+package org.openecomp.sdc.securityutil;
+
+import org.openecomp.sdc.securityutil.filters.SessionValidationFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.Cookie;
+import java.io.IOException;
+
+public class AuthenticationCookieUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(SessionValidationFilter.class.getName());
+
+ /**
+ * Update given cookie session time value to current time
+ *
+ * @param cookie
+ * @param filterConfiguration
+ * @return
+ * @throws CipherUtilException
+ * @throws IOException
+ */
+ public static Cookie updateSessionTime(Cookie cookie, ISessionValidationFilterConfiguration filterConfiguration) throws CipherUtilException, IOException {
+ AuthenticationCookie authenticationCookie = getAuthenticationCookie(cookie, filterConfiguration);
+ long newTime = System.currentTimeMillis();
+ log.debug("SessionValidationFilter: Going to set new session time in cookie, old value: {}, new value: {}", authenticationCookie.getCurrentSessionTime(), newTime);
+ authenticationCookie.setCurrentSessionTime(newTime);
+ String encryptedCookie = getEncryptedCookie(authenticationCookie, filterConfiguration);
+ return createUpdatedCookie(cookie, encryptedCookie, filterConfiguration);
+ }
+
+ /**
+ * Create new Cookie object with same attributes as original cookie
+ * @param cookie
+ * @param encryptedCookie
+ * @param cookieConfiguration
+ * @return
+ */
+ public static Cookie createUpdatedCookie(Cookie cookie, String encryptedCookie, ISessionValidationCookieConfiguration cookieConfiguration) {
+ Cookie updatedCookie = new Cookie(cookie.getName(), encryptedCookie );
+ updatedCookie.setPath(cookieConfiguration.getCookiePath());
+ updatedCookie.setDomain(cookieConfiguration.getCookieDomain());
+ updatedCookie.setHttpOnly(cookieConfiguration.isCookieHttpOnly());
+ return updatedCookie;
+ }
+
+ /**
+ * Convert AuthenticationCookie to JSON and encrypt with given key
+ *
+ * @param authenticationCookie
+ * @param filterConfiguration
+ * @return
+ * @throws IOException
+ * @throws CipherUtilException
+ */
+ public static String getEncryptedCookie(AuthenticationCookie authenticationCookie, ISessionValidationFilterConfiguration filterConfiguration) throws IOException, CipherUtilException {
+ String changedCookieJson = RepresentationUtils.toRepresentation(authenticationCookie);
+ return CipherUtil.encryptPKC(changedCookieJson, filterConfiguration.getSecurityKey());
+ }
+
+ /**
+ * Decrypt given Cookie to JSON and convert to AuthenticationCookie object
+ *
+ * @param cookie
+ * @param filterConfiguration
+ * @return
+ * @throws CipherUtilException
+ */
+ public static AuthenticationCookie getAuthenticationCookie(Cookie cookie, ISessionValidationFilterConfiguration filterConfiguration) throws CipherUtilException {
+ String originalCookieJson = CipherUtil.decryptPKC(cookie.getValue(), filterConfiguration.getSecurityKey());
+ return RepresentationUtils.fromRepresentation(originalCookieJson, AuthenticationCookie.class);
+ }
+
+ /**
+ * session expired if session was idle or max time reached
+ *
+ * @param cookie
+ * @param filterConfiguration
+ * @return
+ * @throws CipherUtilException
+ */
+ public static boolean isSessionExpired(Cookie cookie, ISessionValidationFilterConfiguration filterConfiguration) throws CipherUtilException {
+ AuthenticationCookie authenticationCookie = getAuthenticationCookie(cookie, filterConfiguration);
+ long sessionExpirationDate = authenticationCookie.getMaxSessionTime() + filterConfiguration.getMaxSessionTimeOut();
+ long sessionTime = authenticationCookie.getCurrentSessionTime();
+ long currentTime = System.currentTimeMillis();
+ log.debug("SessionValidationFilter: Checking if session expired: session time: {}, expiration time: {}, current time: {}", sessionTime, sessionExpirationDate, currentTime);
+ return currentTime > sessionExpirationDate || isSessionIdle(sessionTime, currentTime, filterConfiguration);
+ }
+
+ /**
+ * Session is idle if wasn't updated ( wasn't in use ) for more then value from filter configuration
+ *
+ * @param sessionTimeValue
+ * @param currentTime
+ * @param filterConfiguration
+ * @return
+ */
+ public static boolean isSessionIdle(long sessionTimeValue, long currentTime, ISessionValidationFilterConfiguration filterConfiguration) {
+ long currentIdleTime = currentTime - sessionTimeValue;
+ long maxIdleTime = filterConfiguration.getSessionIdleTimeOut();
+ log.debug("SessionValidationFilter: Checking if session idle: session time: {}, current idle time: {}, max idle time: {}", currentTime, currentIdleTime, maxIdleTime);
+ return currentIdleTime >= maxIdleTime;
+ }
+
+
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/CipherUtil.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/CipherUtil.java
new file mode 100644
index 0000000000..39553ca789
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/CipherUtil.java
@@ -0,0 +1,123 @@
+package org.openecomp.sdc.securityutil;
+
+import java.security.SecureRandom;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import org.apache.commons.codec.binary.Base64;
+
+public class CipherUtil {
+ private static Logger log = LoggerFactory.getLogger( CipherUtil.class.getName());
+ private static final String ALGORITHM = "AES";
+ private static final String ALGORYTHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING";
+ private static final String CIPHER_PROVIDER = "SunJCE";
+ private static final int BLOCK_SIZE = 128;
+ private static final int BYTE_SIZE = 8;
+ private static final int IV_SIZE = BLOCK_SIZE / BYTE_SIZE;
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+ private static final String ALGORITHM_NAME = "SHA1PRNG";
+
+ /**
+ * Encrypt the text using the secret key in key.properties file
+ *
+ * @param value string to encrypt
+ * @return The encrypted string
+ * @throws CipherUtilException
+ * In case of issue with the encryption
+ */
+ public static String encryptPKC(String value, String base64key) throws CipherUtilException {
+ Cipher cipher;
+ byte[] iv = new byte[IV_SIZE];
+ byte[] finalByte;
+ try {
+ cipher = Cipher.getInstance(ALGORYTHM_DETAILS, CIPHER_PROVIDER);
+ SecureRandom secureRandom = SecureRandom.getInstance(ALGORITHM_NAME);
+ secureRandom.nextBytes(iv);
+ IvParameterSpec ivspec = new IvParameterSpec(iv);
+ cipher.init(Cipher.ENCRYPT_MODE, getSecretKeySpec(base64key), ivspec);
+ finalByte = cipher.doFinal(value.getBytes());
+
+ } catch (Exception ex) {
+ log.error("encrypt failed", ex);
+ throw new CipherUtilException(ex);
+ }
+ return Base64.encodeBase64String(addAll(iv, finalByte));
+ }
+
+ /**
+ * Decrypts the text using the secret key in key.properties file.
+ *
+ * @param message
+ * The encrypted string that must be decrypted using the ONAP Portal
+ * Encryption Key
+ * @return The String decrypted
+ * @throws CipherUtilException
+ * if any decryption step fails
+ */
+
+ public static String decryptPKC(String message, String base64key) throws CipherUtilException {
+ byte[] encryptedMessage = Base64.decodeBase64(message);
+ Cipher cipher;
+ byte[] decrypted;
+ try {
+ cipher = Cipher.getInstance(ALGORYTHM_DETAILS, CIPHER_PROVIDER);
+ IvParameterSpec ivspec = new IvParameterSpec(subarray(encryptedMessage, 0, IV_SIZE));
+ byte[] realData = subarray(encryptedMessage, IV_SIZE, encryptedMessage.length);
+ cipher.init(Cipher.DECRYPT_MODE, getSecretKeySpec(base64key), ivspec);
+ decrypted = cipher.doFinal(realData);
+
+ } catch (Exception ex) {
+ log.error("decrypt failed", ex);
+ throw new CipherUtilException(ex);
+ }
+ return new String(decrypted);
+ }
+
+ private static SecretKeySpec getSecretKeySpec(String keyString) {
+ byte[] key = Base64.decodeBase64(keyString);
+ return new SecretKeySpec(key, ALGORITHM);
+ }
+
+ private static byte[] clone(byte[] array) {
+ return array == null ? null : array.clone();
+ }
+
+ private static byte[] addAll(byte[] array1, byte[] array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ } else {
+ byte[] joinedArray = new byte[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+ }
+
+ private static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ } else {
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+
+ int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_BYTE_ARRAY;
+ } else {
+ byte[] subarray = new byte[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+ }
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/CipherUtilException.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/CipherUtilException.java
new file mode 100644
index 0000000000..0e0d53a2f9
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/CipherUtilException.java
@@ -0,0 +1,66 @@
+package org.openecomp.sdc.securityutil;
+
+
+/* ============LICENSE_START==========================================
+ * ONAP Portal SDK
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software 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.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * 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============================================
+ *
+ *
+ */
+
+
+public class CipherUtilException extends Exception {
+
+ private static final long serialVersionUID = -4163367786939629691L;
+
+ public CipherUtilException() {
+ super();
+ }
+
+ public CipherUtilException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+ public CipherUtilException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CipherUtilException(String message) {
+ super(message);
+ }
+
+ public CipherUtilException(Throwable cause) {
+ super(cause);
+ }
+
+} \ No newline at end of file
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/ISessionValidationCookieConfiguration.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/ISessionValidationCookieConfiguration.java
new file mode 100644
index 0000000000..cb72dca941
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/ISessionValidationCookieConfiguration.java
@@ -0,0 +1,12 @@
+package org.openecomp.sdc.securityutil;
+
+/**
+ * Configuration for Cookie object , have to be same over all components of application
+ */
+public interface ISessionValidationCookieConfiguration {
+
+ String getCookieName();
+ String getCookieDomain();
+ String getCookiePath();
+ boolean isCookieHttpOnly();
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/ISessionValidationFilterConfiguration.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/ISessionValidationFilterConfiguration.java
new file mode 100644
index 0000000000..bf55ba947b
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/ISessionValidationFilterConfiguration.java
@@ -0,0 +1,13 @@
+package org.openecomp.sdc.securityutil;
+
+import java.util.List;
+
+public interface ISessionValidationFilterConfiguration extends ISessionValidationCookieConfiguration {
+
+ String getSecurityKey();
+ long getMaxSessionTimeOut();
+ long getSessionIdleTimeOut(); // max idle time for session
+ String getRedirectURL();
+ List<String> getExcludedUrls(); // comma separated URLs, like this "/config,/configmgr,/rest,/kibanaProxy"
+}
+
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/Passwords.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/Passwords.java
new file mode 100644
index 0000000000..e10bd81d0f
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/Passwords.java
@@ -0,0 +1,187 @@
+package org.openecomp.sdc.securityutil;/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. 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=========================================================
+ */
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Random;
+
+
+public class Passwords {
+
+ private static Logger log = LoggerFactory.getLogger( Passwords.class.getName());
+ private static final Random RANDOM = new SecureRandom();
+ private static final int SALT = 0;
+ private static final int HASH = 1;
+ private static final String HASH_ALGORITHM = "SHA-256";
+
+ /**
+ * static utility class
+ */
+ private Passwords() {
+ }
+
+ /**
+ * the method calculates a hash with a generated salt for the given password
+ *
+ * @param password
+ * @return a "salt:hash" value
+ */
+ public static String hashPassword(String password) {
+ if (password!=null){
+ byte[] salt = getNextSalt();
+ byte byteData[] = hash(salt, password.getBytes());
+ if (byteData != null) {
+ return toHex(salt) + ":" + toHex(byteData);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * the method checks if the given password matches the calculated hash
+ *
+ * @param password
+ * @param expectedHash
+ * @return
+ */
+ public static boolean isExpectedPassword(String password, String expectedHash) {
+ if (password==null && expectedHash==null)
+ return true;
+ if (password==null || expectedHash==null) //iff exactly 1 is null
+ return false;
+ if (!expectedHash.contains(":")){
+ log.error("invalid password expecting hash at the prefix of the password (ex. e0277df331f4ff8f74752ac4a8fbe03b:6dfbad308cdf53c9ff2ee2dca811ee92f1b359586b33027580e2ff92578edbd0)\n" +
+ "\t\t\t");
+ return false;
+ }
+ String[] params = expectedHash.split(":");
+ return isExpectedPassword(password, params[SALT], params[HASH]);
+ }
+
+ /**
+ * the method checks if the given password matches the calculated hash
+ *
+ * @param password
+ * @param salt
+ * @param hash
+ * the hash generated using the salt
+ * @return true if the password matched the hash
+ */
+ public static boolean isExpectedPassword(String password, String salt, String hash) {
+ if ( password == null && hash == null )
+ return true;
+ if ( salt == null ){
+ log.error("salt must be initialized");
+ return false;
+ }
+ //unintialized params
+ if ( password == null || hash == null )
+ return false;
+ byte[] saltBytes = fromHex(salt);
+ byte[] hashBytes = fromHex(hash);
+
+ byte byteData[] = hash(saltBytes, password.getBytes());
+ if (byteData != null) {
+ return Arrays.equals(byteData, hashBytes);
+ }
+ return false;
+ }
+
+ public static void main(String[] args) {
+ if (args.length > 1 || args.length > 0) {
+ System.out.println("[" + hashPassword(args[0]) + "]");
+ } else {
+ System.out.println("no passward passed.");
+ }
+
+ }
+
+ /**
+ * Returns a random salt to be used to hash a password.
+ *
+ * @return a 16 bytes random salt
+ */
+ private static byte[] getNextSalt() {
+ byte[] salt = new byte[16];
+ RANDOM.nextBytes(salt);
+ return salt;
+ }
+
+ /**
+ * hase's the salt and value using the chosen algorithm
+ *
+ * @param salt
+ * @param password
+ * @return an array of bytes resulting from the hash
+ */
+ private static byte[] hash(byte[] salt, byte[] password) {
+ MessageDigest md;
+ byte[] byteData = null;
+ try {
+ md = MessageDigest.getInstance(HASH_ALGORITHM);
+ md.update(salt);
+ md.update(password);
+ byteData = md.digest();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println("invalid algorithm name");
+ }
+ return byteData;
+ }
+
+ /**
+ * Converts a string of hexadecimal characters into a byte array.
+ *
+ * @param hex
+ * the hex string
+ * @return the hex string decoded into a byte array
+ */
+ private static byte[] fromHex(String hex) {
+ if ( hex == null )
+ return null;
+ byte[] binary = new byte[hex.length() / 2];
+ for (int i = 0; i < binary.length; i++) {
+ binary[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
+ }
+ return binary;
+ }
+
+ /**
+ * Converts a byte array into a hexadecimal string.
+ *
+ * @param array
+ * the byte array to convert
+ * @return a length*2 character string encoding the byte array
+ */
+ private static String toHex(byte[] array) {
+ BigInteger bi = new BigInteger(1, array);
+ String hex = bi.toString(16);
+ int paddingLength = (array.length * 2) - hex.length();
+ if (paddingLength > 0)
+ return String.format("%0" + paddingLength + "d", 0) + hex;
+ else
+ return hex;
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/RepresentationUtils.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/RepresentationUtils.java
new file mode 100644
index 0000000000..b647fa3a65
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/RepresentationUtils.java
@@ -0,0 +1,53 @@
+package org.openecomp.sdc.securityutil;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+public class RepresentationUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(RepresentationUtils.class.getName());
+
+ /**
+ * Build JSON Representation of given Object
+ *
+ * @param elementToRepresent
+ * @return
+ * @throws IOException
+ */
+ public static <T> String toRepresentation(T elementToRepresent) throws IOException {
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ return mapper.writeValueAsString(elementToRepresent);
+ }
+
+ /**
+ * Convert JSON representation to given class
+ *
+ * @param json
+ * @param clazz
+ * @param <T>
+ * @return
+ */
+ public static <T> T fromRepresentation(String json, Class<T> clazz) {
+ ObjectMapper mapper = new ObjectMapper();
+ T object = null;
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ try {
+ object = mapper.readValue(json, clazz);
+ } catch (Exception e) {
+ log.error("Error when parsing JSON of object of type {}", clazz.getSimpleName(), e);
+ } // return null in case of exception
+
+ return object;
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/SecurityUtil.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/SecurityUtil.java
new file mode 100644
index 0000000000..8dd4e33a44
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/SecurityUtil.java
@@ -0,0 +1,134 @@
+package org.openecomp.sdc.securityutil;
+
+import fj.data.Either;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+
+public class SecurityUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger( SecurityUtil.class );
+ private static final byte[] KEY = new byte[]{-64,5,-32 ,-117 ,-44,8,-39, 1, -9, 36,-46,-81, 62,-15,-63,-75};
+ public static final SecurityUtil INSTANCE = new SecurityUtil();
+ public static final String ALGORITHM = "AES" ;
+ public static final String CHARSET = StandardCharsets.UTF_8.name();
+
+ public static Key secKey = null ;
+
+ /**
+ *
+ * cmd commands >$PROGRAM_NAME decrypt "$ENCRYPTED_MSG"
+ * >$PROGRAM_NAME encrypt "message"
+ **/
+
+ private SecurityUtil(){ super(); }
+
+ static {
+ try{
+ secKey = generateKey( KEY, ALGORITHM );
+ }
+ catch(Exception e){
+ LOG.warn("cannot generate key for {}", ALGORITHM);
+ }
+ }
+
+
+
+ public static Key generateKey(final byte[] KEY, String algorithm){
+ return new SecretKeySpec(KEY, algorithm);
+ }
+
+ //obfuscates key prefix -> **********
+ public String obfuscateKey(String sensitiveData){
+
+ if (sensitiveData != null){
+ int len = sensitiveData.length();
+ StringBuilder builder = new StringBuilder(sensitiveData);
+ for (int i=0; i<len/2; i++){
+ builder.setCharAt(i, '*');
+ }
+ return builder.toString();
+ }
+ return sensitiveData;
+ }
+
+ /**
+ * @param strDataToEncrypt - plain string to encrypt
+ * Encrypt the Data
+ * a. Declare / Initialize the Data. Here the data is of type String
+ * b. Convert the Input Text to Bytes
+ * c. Encrypt the bytes using doFinal method
+ */
+ public Either<String,String> encrypt(String strDataToEncrypt){
+ if (strDataToEncrypt != null ){
+ try {
+ LOG.debug("Encrypt key -> {}", secKey);
+ Cipher aesCipherForEncryption = Cipher.getInstance("AES"); // Must specify the mode explicitly as most JCE providers default to ECB mode!!
+ aesCipherForEncryption.init(Cipher.ENCRYPT_MODE, secKey);
+ byte[] byteDataToEncrypt = strDataToEncrypt.getBytes();
+ byte[] byteCipherText = aesCipherForEncryption.doFinal(byteDataToEncrypt);
+ String strCipherText = new String( Base64.getMimeEncoder().encode(byteCipherText), CHARSET );
+ LOG.debug("Cipher Text generated using AES is {}", strCipherText);
+ return Either.left(strCipherText);
+ } catch( NoSuchAlgorithmException | UnsupportedEncodingException e){
+ LOG.warn( "cannot encrypt data unknown algorithm or missing encoding for {}" ,secKey.getAlgorithm());
+ } catch( InvalidKeyException e){
+ LOG.warn( "invalid key recieved - > {} | {}" , Base64.getDecoder().decode( secKey.getEncoded() ), e.getMessage() );
+ } catch( IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException e){
+ LOG.warn( "bad algorithm definition (Illegal Block Size or padding), please review you algorithm block&padding" , e.getMessage() );
+ }
+ }
+ return Either.right("Cannot encrypt "+strDataToEncrypt);
+ }
+
+ /**
+ * Decrypt the Data
+ * @param byteCipherText - should be valid bae64 input in the length of 16bytes
+ * @param isBase64Decoded - is data already base64 encoded&aligned to 16 bytes
+ * a. Initialize a new instance of Cipher for Decryption (normally don't reuse the same object)
+ * b. Decrypt the cipher bytes using doFinal method
+ */
+ public Either<String,String> decrypt(byte[] byteCipherText , boolean isBase64Decoded){
+ if (byteCipherText != null){
+ byte[] alignedCipherText = byteCipherText;
+ try{
+ if (isBase64Decoded)
+ alignedCipherText = Base64.getDecoder().decode(byteCipherText);
+ LOG.debug("Decrypt key -> "+secKey.getEncoded());
+ Cipher aesCipherForDecryption = Cipher.getInstance("AES"); // Must specify the mode explicitly as most JCE providers default to ECB mode!!
+ aesCipherForDecryption.init(Cipher.DECRYPT_MODE, secKey);
+ byte[] byteDecryptedText = aesCipherForDecryption.doFinal(alignedCipherText);
+ String strDecryptedText = new String(byteDecryptedText);
+ LOG.debug("Decrypted Text message is: {}" , obfuscateKey( strDecryptedText ));
+ return Either.left(strDecryptedText);
+ } catch( NoSuchAlgorithmException e){
+ LOG.warn( "cannot encrypt data unknown algorithm or missing encoding for {}" ,secKey.getAlgorithm());
+ } catch( InvalidKeyException e){
+ LOG.warn( "invalid key recieved - > {} | {}" , Base64.getDecoder().decode( secKey.getEncoded() ), e.getMessage() );
+ } catch( IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException e){
+ LOG.warn( "bad algorithm definition (Illegal Block Size or padding), please review you algorithm block&padding" , e.getMessage() );
+ }
+ }
+ return Either.right("Decrypt FAILED");
+ }
+
+ public Either<String,String> decrypt(String byteCipherText){
+ try {
+ return decrypt(byteCipherText.getBytes(CHARSET),true);
+ } catch( UnsupportedEncodingException e ){
+ LOG.warn( "Missing encoding for {} | {} " ,secKey.getAlgorithm() , e.getMessage());
+ }
+ return Either.right("Decrypt FAILED");
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/FilterServletOutputStream.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/FilterServletOutputStream.java
new file mode 100644
index 0000000000..14fa598a50
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/FilterServletOutputStream.java
@@ -0,0 +1,38 @@
+package org.openecomp.sdc.securityutil.filters;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class FilterServletOutputStream extends ServletOutputStream {
+
+ private DataOutputStream stream;
+
+ public FilterServletOutputStream(OutputStream output) {
+ stream = new DataOutputStream(output);
+ }
+
+ public void write(int b) throws IOException {
+ stream.write(b);
+ }
+
+ public void write(byte[] b) throws IOException {
+ stream.write(b);
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException {
+ stream.write(b,off,len);
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/ResponceWrapper.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/ResponceWrapper.java
new file mode 100644
index 0000000000..df5351fe78
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/ResponceWrapper.java
@@ -0,0 +1,53 @@
+package org.openecomp.sdc.securityutil.filters;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class ResponceWrapper extends HttpServletResponseWrapper {
+ private ByteArrayOutputStream output;
+ private int contentLength;
+ private String contentType;
+
+ public ResponceWrapper(HttpServletResponse response) {
+ super(response);
+ output = new ByteArrayOutputStream();
+ }
+
+ public byte[] getData() {
+ return output.toByteArray();
+ }
+
+ public ServletOutputStream getOutputStream() {
+ return new FilterServletOutputStream(output);
+ }
+
+ public PrintWriter getWriter() {
+ return new PrintWriter(getOutputStream(), true);
+ }
+
+ public void setContentLength(int length) {
+ this.contentLength = length;
+ super.setContentLength(length);
+ }
+
+ public int getContentLength() {
+ return contentLength;
+ }
+
+ public void setContentType(String type) {
+ this.contentType = type;
+ super.setContentType(type);
+ }
+
+
+ public String getContentType() {
+ return contentType;
+
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/SampleFilter.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/SampleFilter.java
new file mode 100644
index 0000000000..15cd4c537c
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/SampleFilter.java
@@ -0,0 +1,132 @@
+package org.openecomp.sdc.securityutil.filters;
+
+
+import org.openecomp.sdc.securityutil.ISessionValidationFilterConfiguration;
+
+import javax.servlet.http.Cookie;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class SampleFilter extends SessionValidationFilter {
+
+ private static class Configuration implements ISessionValidationFilterConfiguration {
+
+ private static Configuration instance;
+
+ private String securityKey;
+ private long maxSessionTimeOut;
+ private long sessionIdleTimeOut;
+ private String redirectURL;
+ private List<String> excludedUrls;
+
+ private String cookieName;
+ private String cookieDomain;
+ private String cookiePath;
+ private boolean isCookieHttpOnly;
+
+ private Configuration() {
+ //security key should be exactly 16 characters long clear text and then encoded to base64
+ this.securityKey = "AGLDdG4D04BKm2IxIWEr8o==";
+ this.maxSessionTimeOut = 24*60*60*1000;
+ this.sessionIdleTimeOut = 60*60*1000;
+ this.redirectURL = "https://www.e-access.att.com/ecomp_portal_ist/ecompportal/process_csp";
+ this.excludedUrls = new ArrayList<>(Arrays.asList("/config","/configmgr","/rest","/kibanaProxy","/healthcheck","/upload.*"));
+
+ this.cookieName = "kuku";
+ this.cookieDomain = "";
+ this.cookiePath = "/";
+ this.isCookieHttpOnly = true;
+ }
+
+ public void setSecurityKey(String securityKey) {
+ this.securityKey = securityKey;
+ }
+
+ public void setMaxSessionTimeOut(long maxSessionTimeOut) {
+ this.maxSessionTimeOut = maxSessionTimeOut;
+ }
+
+ public void setCookieName(String cookieName) {
+ this.cookieName = cookieName;
+ }
+
+ public void setRedirectURL(String redirectURL) {
+ this.redirectURL = redirectURL;
+ }
+
+ public void setExcludedUrls(List<String> excludedUrls) {
+ this.excludedUrls = excludedUrls;
+ }
+
+ public static Configuration getInstance(){
+ if (instance == null ){
+ instance = new Configuration();
+ }
+ return instance;
+ }
+
+ @Override
+ public String getSecurityKey() {
+ return securityKey;
+ }
+
+ @Override
+ public long getMaxSessionTimeOut() {
+ return maxSessionTimeOut;
+ }
+
+ @Override
+ public long getSessionIdleTimeOut() {
+ return sessionIdleTimeOut;
+ }
+
+ @Override
+ public String getCookieName() {
+ return cookieName;
+ }
+
+ @Override
+ public String getCookieDomain() {
+ return cookieDomain;
+ }
+
+ @Override
+ public String getCookiePath() {
+ return cookiePath;
+ }
+
+ @Override
+ public boolean isCookieHttpOnly() {
+ return isCookieHttpOnly;
+ }
+
+ @Override
+ public String getRedirectURL() {
+ return redirectURL;
+ }
+
+ @Override
+ public List<String> getExcludedUrls() {
+ return excludedUrls;
+ }
+ }
+
+ @Override
+ public ISessionValidationFilterConfiguration getFilterConfiguration() {
+ return Configuration.getInstance();
+ }
+
+ @Override
+ protected Cookie addRoleToCookie(Cookie updatedCookie) {
+ return updatedCookie;
+ }
+
+ @Override
+ protected boolean isRoleValid(Cookie cookie) {
+ return true;
+ }
+
+}
+
+
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/SessionValidationFilter.java b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/SessionValidationFilter.java
new file mode 100644
index 0000000000..9863d8f904
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/main/java/org/openecomp/sdc/securityutil/filters/SessionValidationFilter.java
@@ -0,0 +1,194 @@
+package org.openecomp.sdc.securityutil.filters;
+
+import org.openecomp.sdc.securityutil.AuthenticationCookieUtils;
+import org.openecomp.sdc.securityutil.CipherUtilException;
+import org.openecomp.sdc.securityutil.ISessionValidationFilterConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+public abstract class SessionValidationFilter implements Filter {
+ private static final Logger log = LoggerFactory.getLogger(SessionValidationFilter.class.getName());
+ private ISessionValidationFilterConfiguration filterConfiguration;
+ private List<String> excludedUrls;
+
+ public abstract ISessionValidationFilterConfiguration getFilterConfiguration();
+ protected abstract Cookie addRoleToCookie(Cookie updatedCookie);
+ protected abstract boolean isRoleValid(Cookie cookie);
+
+ @Override
+ public final void init(FilterConfig filterConfig) throws ServletException {
+ filterConfiguration = getFilterConfiguration();
+ excludedUrls = filterConfiguration.getExcludedUrls();
+ }
+
+ @Override
+ public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+ final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
+ final HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
+
+ long starTime = System.nanoTime();
+ log.debug("SessionValidationFilter: Validation started, received request with URL {}", httpRequest.getRequestURL());
+
+ // request preprocessing
+ boolean isContinueProcessing = preProcessingRequest(servletRequest, servletResponse, filterChain, httpRequest, httpResponse);
+ List<Cookie> cookies = null;
+
+ // request processing
+ if (isContinueProcessing) {
+ cookies = extractAuthenticationCookies(httpRequest.getCookies());
+ isContinueProcessing = processRequest(httpRequest, httpResponse, cookies.get(0));
+ }
+
+ // response processing
+ if(isContinueProcessing){
+ log.debug("SessionValidationFilter: Cookie from request {} is valid, passing request to session extension ...", httpRequest.getRequestURL());
+ Cookie updatedCookie = processResponse(cookies.get(cookies.size()-1));
+
+ cleanResponceFromLeftoverCookies(httpResponse, cookies);
+
+ // Use responce wrapper if servlet remove Cookie header from responce
+// OutputStream out = httpResponse.getOutputStream();
+// ResponceWrapper responceWrapper = new ResponceWrapper(httpResponse);
+
+ log.debug("SessionValidationFilter: request {} passed all validations, passing request to endpoint ...", httpRequest.getRequestURL());
+ httpResponse.addCookie(updatedCookie);
+ filterChain.doFilter(servletRequest, httpResponse);
+
+ // Use responce wrapper if servlet remove Cookie header from responce
+// responceWrapper.addCookie(updatedCookie);
+// httpResponse.setContentLength(responceWrapper.getData().length);
+// out.write(responceWrapper.getData());
+// out.close();
+ }
+ long durationSec = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - starTime);
+ long durationMil = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - starTime);
+ log.debug("SessionValidationFilter: Validation ended, running time for URL {} is: {} seconds {} miliseconds", httpRequest.getPathInfo(), durationSec, durationMil);
+ }
+
+
+ private boolean preProcessingRequest(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException {
+
+ boolean isPreProcessingSucceeded = true;
+ if (isUrlFromWhiteList(httpRequest)) {
+ log.debug("SessionValidationFilter: URL {} excluded from access validation , passing request to endpoint ... ", httpRequest.getRequestURL());
+ filterChain.doFilter(servletRequest, servletResponse);
+ isPreProcessingSucceeded = false;
+
+ } else if (!isCookiePresent(httpRequest.getCookies())) {
+ //redirect to portal app
+ log.debug("SessionValidationFilter: Cookie from request {} is not valid, redirecting request to portal", httpRequest.getRequestURL());
+ httpResponse.sendRedirect(filterConfiguration.getRedirectURL());
+ isPreProcessingSucceeded = false;
+ }
+ return isPreProcessingSucceeded;
+ }
+
+ private boolean processRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse, Cookie cookie) throws IOException {
+ boolean isProcessSuccessful= true;
+ try {
+ if (AuthenticationCookieUtils.isSessionExpired(cookie, filterConfiguration)) {
+ //redirect to portal app
+ log.debug("SessionValidationFilter: Session is expired, redirecting request {} to portal", httpRequest.getRequestURL());
+ httpResponse.sendRedirect(filterConfiguration.getRedirectURL());
+ isProcessSuccessful = false;
+ }
+ } catch (CipherUtilException e) {
+ log.error("SessionValidationFilter: Cookie decryption error : {}", e.getMessage());
+ log.debug("SessionValidationFilter: Cookie decryption error : {}", e.getMessage(), e);
+ isProcessSuccessful = false;
+ }
+
+ if (!isRoleValid(cookie)) {
+ //redirect to portal app
+ log.debug("SessionValidationFilter: Role is not valid, redirecting request {} to portal", httpRequest.getRequestURL());
+ httpResponse.sendRedirect(filterConfiguration.getRedirectURL());
+ isProcessSuccessful = false;
+ }
+ return isProcessSuccessful;
+ }
+
+ private Cookie processResponse(Cookie cookie) throws IOException, ServletException {
+ Cookie updatedCookie;
+ try {
+ updatedCookie = AuthenticationCookieUtils.updateSessionTime(cookie, filterConfiguration);
+ } catch (CipherUtilException e) {
+ log.error("SessionValidationFilter: Cookie cipher error ...");
+ log.debug("SessionValidationFilter: Cookie cipher error : {}", e.getMessage(), e);
+ throw new ServletException(e.getMessage());
+ }
+ updatedCookie = addRoleToCookie(updatedCookie);
+ return updatedCookie;
+ }
+
+ private boolean isCookiePresent(Cookie[] cookies) {
+ if (cookies == null) {
+ return false;
+ }
+ String actualCookieName = filterConfiguration.getCookieName();
+ boolean isPresent = Arrays.stream(cookies).anyMatch(c -> isCookieNameMatch(actualCookieName, c));
+ if (!isPresent) {
+ log.error("SessionValidationFilter: Session Validation Cookie missing ...");
+ return false;
+ }
+ return true;
+ }
+
+ private List<Cookie> extractAuthenticationCookies(Cookie[] cookies) {
+ String actualCookieName = filterConfiguration.getCookieName();
+ log.debug("SessionValidationFilter: Extracting authentication cookies, {} cookies in request", cookies.length);
+ List<Cookie> authenticationCookies = Arrays.stream(cookies).filter(c -> isCookieNameMatch(actualCookieName, c)).collect(Collectors.toList());
+ log.debug("SessionValidationFilter: Extracted {} authentication cookies from request", authenticationCookies.size());
+ if( authenticationCookies.size() > 1 ){
+ authenticationCookies.forEach( cookie -> log.debug("SessionValidationFilter: Multiple cookies found cookie name, {} cookie value {}", cookie.getName(), cookie.getValue()));
+ }
+ return authenticationCookies;
+ }
+
+
+ // use contains for matching due issue with ecomp portal ( change cookie name, add prefix ), temp solution
+ private boolean isCookieNameMatch(String actualCookieName, Cookie c) {
+ return c.getName().contains(actualCookieName);
+ }
+
+ private boolean isUrlFromWhiteList(HttpServletRequest httpRequest) {
+ if (httpRequest.getPathInfo() == null){
+ final String servletPath = httpRequest.getServletPath().toLowerCase();
+ log.debug("SessionValidationFilter: pathInfo is null, trying to check by servlet path white list validation -> ServletPath: {} ", servletPath);
+ return excludedUrls.stream().
+ anyMatch( e -> servletPath.matches(e));
+ }
+ String pathInfo = httpRequest.getPathInfo().toLowerCase();
+ log.debug("SessionValidationFilter: white list validation -> PathInfo: {} ", pathInfo);
+ return excludedUrls.stream().
+ anyMatch( e -> pathInfo.matches(e));
+ }
+
+ private void cleanResponceFromLeftoverCookies(HttpServletResponse httpResponse, List<Cookie> cookiesList) {
+ for (Cookie cookie:cookiesList){
+ Cookie cleanCookie = AuthenticationCookieUtils.createUpdatedCookie(cookie, null, filterConfiguration);
+ cleanCookie.setMaxAge(0);
+ log.debug("SessionValidationFilter Cleaning Cookie cookie name: {} added to responce", cleanCookie.getName());
+ httpResponse.addCookie(cleanCookie);
+ }
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/test/AuthenticationCookieUtilsTest.java b/openecomp-be/backend/openecomp-sdc-security-util/src/test/AuthenticationCookieUtilsTest.java
new file mode 100644
index 0000000000..c03bf9c65d
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/test/AuthenticationCookieUtilsTest.java
@@ -0,0 +1,54 @@
+package org.onap.sdc.security;
+
+import org.junit.Test;
+import org.onap.sdc.security.filters.SampleFilter;
+
+import javax.servlet.http.Cookie;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+public class AuthenticationCookieUtilsTest {
+
+ private SampleFilter sessionValidationFilter = new SampleFilter();
+ private ISessionValidationFilterConfiguration filterCfg = sessionValidationFilter.getFilterConfiguration();
+
+ @Test
+ public void vaildateThatCookieCurrentSessionTimeIncreased() throws IOException, CipherUtilException {
+ // original cookie, pojo and servlet cookie
+ AuthenticationCookie authenticationCookieOriginal = new AuthenticationCookie("kuku");
+ Cookie cookieWithOriginalTime = new Cookie(filterCfg.getCookieName(), AuthenticationCookieUtils.getEncryptedCookie(authenticationCookieOriginal,filterCfg ));
+ // cookie with increased time, pojo and servlet cookie
+ Cookie cookieWithIncreasedTime = AuthenticationCookieUtils.updateSessionTime(cookieWithOriginalTime, filterCfg);
+ AuthenticationCookie authenticationCookieIncreasedTime = AuthenticationCookieUtils.getAuthenticationCookie(cookieWithIncreasedTime, filterCfg);
+ // validation
+ long currentSessionTimeOriginal = authenticationCookieOriginal.getCurrentSessionTime();
+ long currentSessionTimeIncreased = authenticationCookieIncreasedTime.getCurrentSessionTime();
+ assertTrue(currentSessionTimeOriginal < currentSessionTimeIncreased);
+ }
+
+ @Test
+ public void validateSerializationEncriptionDeserializationDecryption() throws IOException, CipherUtilException {
+ // original cookie, pojo and servlet cookie
+ AuthenticationCookie authenticationCookieOriginal = new AuthenticationCookie("kuku");
+ Cookie cookieWithOriginalTime = new Cookie(filterCfg.getCookieName(), AuthenticationCookieUtils.getEncryptedCookie(authenticationCookieOriginal,filterCfg ));
+ // cookie with increased time, pojo and servlet cookie
+ AuthenticationCookie decriptedAndDeserializedAuthenticationCookie = AuthenticationCookieUtils.getAuthenticationCookie(cookieWithOriginalTime,filterCfg);
+ assertTrue(authenticationCookieOriginal.equals(decriptedAndDeserializedAuthenticationCookie));
+ }
+
+
+
+// @Test
+// public void getEncryptedCookie() {
+// }
+//
+// @Test
+// public void getAuthenticationCookie() {
+// }
+//
+// @Test
+// public void isSessionExpired() {
+// }
+} \ No newline at end of file
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/test/CipherUtilTest.java b/openecomp-be/backend/openecomp-sdc-security-util/src/test/CipherUtilTest.java
new file mode 100644
index 0000000000..753902fcf8
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/test/CipherUtilTest.java
@@ -0,0 +1,56 @@
+package org.onap.sdc.security;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.RandomStringUtils;
+import org.junit.Test;
+
+import java.util.Random;
+
+import static org.apache.commons.codec.binary.Base64.encodeBase64String;
+import static org.junit.Assert.*;
+
+public class CipherUtilTest {
+
+ private static final String KEY = "AGLDdG4D04BKm2IxIWEr8o==";
+ private static final String DATA = "data";
+
+ @Test
+ public void encryptDecryptPKC() throws CipherUtilException {
+ String generatedKey = RandomStringUtils.randomAlphabetic(16);
+ String base64Key = Base64.encodeBase64String(generatedKey.getBytes());
+ String encrypted = CipherUtil.encryptPKC(DATA, base64Key);
+ assertNotEquals(DATA, encrypted);
+ String decrypted = CipherUtil.decryptPKC(encrypted, base64Key);
+ assertEquals(decrypted, DATA);
+ }
+
+ @Test
+ public void encryptInvalidKey() {
+ try {
+ CipherUtil.encryptPKC(DATA, "invalidKey");
+ fail();
+ } catch (CipherUtilException ex) {
+ assertTrue(ex.getMessage().contains("Invalid AES key length"));
+ }
+ }
+
+ @Test
+ public void decryptInvalidKey() {
+ try {
+ CipherUtil.decryptPKC(DATA, "invalidKey");
+ fail();
+ } catch (CipherUtilException ex) {
+ assertTrue(ex.getMessage().contains("length"));
+ }
+ }
+
+ @Test
+ public void decryptInvalidData() {
+ try {
+ CipherUtil.decryptPKC(DATA, KEY);
+ fail();
+ } catch (CipherUtilException ex) {
+ assertTrue(ex.getMessage().contains("Wrong IV length"));
+ }
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/test/PasswordsTest.java b/openecomp-be/backend/openecomp-sdc-security-util/src/test/PasswordsTest.java
new file mode 100644
index 0000000000..6da62a92e5
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/test/PasswordsTest.java
@@ -0,0 +1,77 @@
+package org.onap.sdc.security;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class PasswordsTest {
+
+ @Test
+ public void hashPassword() throws Exception {
+ String hash = Passwords.hashPassword("hello1234");
+ assertTrue(Passwords.isExpectedPassword("hello1234", hash));
+
+ //test different salt-> result in different hash
+ String hash2 = Passwords.hashPassword("hello1234");
+ assertFalse(hash.equals(hash2));
+
+ String hash3 = Passwords.hashPassword("");
+ assertTrue(Passwords.isExpectedPassword("", hash3));
+
+ String hash4 = Passwords.hashPassword(null);
+ assertTrue(hash4 == null);
+ }
+
+ @Test
+ public void isExpectedPassword() throws Exception {
+ //region isExpectedPassword(String password, String salt, String hash)
+ assertTrue(Passwords.isExpectedPassword(null, null, null));
+ //valid hash
+ assertTrue(Passwords.isExpectedPassword("hello1234", "e0277df331f4ff8f74752ac4a8fbe03b", "6dfbad308cdf53c9ff2ee2dca811ee92f1b359586b33027580e2ff92578edbd0"));
+ //invalid salt
+ assertFalse(Passwords.isExpectedPassword("hello1234", "c0000df331f4ff8f74752ac4a00be03c", "6dfbad308cdf53c9ff2ee2dca811ee92f1b359586b33027580e2ff92578edbd0"));
+ assertFalse(Passwords.isExpectedPassword("hello1234", null, "6dfbad308cdf53c9ff2ee2dca811ee92f1b359586b33027580e2ff92578edbd0"));
+ //exacly 1 param uninitialized
+ assertFalse(Passwords.isExpectedPassword("hello1234", "", null));
+ assertFalse(Passwords.isExpectedPassword(null, "", "hello1234"));
+ //no salt & no hash
+ assertFalse(Passwords.isExpectedPassword("hello1234", null, "hello1234"));
+ //endregion
+
+ //region isExpectedPassword(String password, String expectedHash)
+ assertTrue(Passwords.isExpectedPassword(null, null));
+ //valid hash
+ assertTrue(Passwords.isExpectedPassword("hello1234", "e0277df331f4ff8f74752ac4a8fbe03b:6dfbad308cdf53c9ff2ee2dca811ee92f1b359586b33027580e2ff92578edbd0"));
+ //invalid salt
+ assertFalse(Passwords.isExpectedPassword("hello1234", "c0000df331f4ff8f74752ac4a00be03c:6dfbad308cdf53c9ff2ee2dca811ee92f1b359586b33027580e2ff92578edbd0"));
+ //exacly 1 param uninitialized
+ assertFalse(Passwords.isExpectedPassword("hello1234", null));
+ assertFalse(Passwords.isExpectedPassword(null, "hello1234"));
+ //no salt & no hash
+ assertFalse(Passwords.isExpectedPassword("hello1234", "hello1234"));
+ //endregion
+ }
+
+ @Test
+ public void hashtest() {
+ String password = "123456";
+ String hash = Passwords.hashPassword(password);
+ assertTrue(Passwords.isExpectedPassword(password, hash));
+ password = "1sdfgsgd23456";
+ hash = Passwords.hashPassword(password);
+ assertTrue(Passwords.isExpectedPassword(password, hash));
+ password = "1sdfgsgd2345((*&%$%6";
+ hash = Passwords.hashPassword(password);
+ assertTrue(Passwords.isExpectedPassword(password, hash));
+ password = "";
+ hash = Passwords.hashPassword(password);
+ assertTrue(Passwords.isExpectedPassword(password, hash));
+ password = " ";
+ hash = Passwords.hashPassword(password);
+ assertTrue(Passwords.isExpectedPassword(password, hash));
+ }
+
+
+} \ No newline at end of file
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/test/RepresentationUtilsTest.java b/openecomp-be/backend/openecomp-sdc-security-util/src/test/RepresentationUtilsTest.java
new file mode 100644
index 0000000000..7b12ac7eb2
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/test/RepresentationUtilsTest.java
@@ -0,0 +1,34 @@
+package org.onap.sdc.security;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.assertTrue;
+
+public class RepresentationUtilsTest {
+
+ private static AuthenticationCookie originalCookie = new AuthenticationCookie("kuku");
+
+ @Test
+ public void representationE2EwithRoleNull() throws IOException {
+ originalCookie.setRoles(null);
+ String jsonStr = RepresentationUtils.toRepresentation(originalCookie);
+ AuthenticationCookie cookieFromJson = RepresentationUtils.fromRepresentation(jsonStr, AuthenticationCookie.class);
+ assertTrue(originalCookie.equals(cookieFromJson));
+ }
+
+ @Test
+ public void representationE2EwithRoleNotNull() throws IOException {
+ Set<String> roles = new HashSet<String>();
+ roles.add("Designer");
+ roles.add("Admin");
+ roles.add("Tester");
+ originalCookie.setRoles(roles);
+ String jsonStr = RepresentationUtils.toRepresentation(originalCookie);
+ AuthenticationCookie cookieFromJson = RepresentationUtils.fromRepresentation(jsonStr, AuthenticationCookie.class);
+ assertTrue(originalCookie.equals(cookieFromJson));
+ }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/test/SecurityUtilTest.java b/openecomp-be/backend/openecomp-sdc-security-util/src/test/SecurityUtilTest.java
new file mode 100644
index 0000000000..6a47434efc
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/test/SecurityUtilTest.java
@@ -0,0 +1,30 @@
+package org.onap.sdc.security;
+
+import org.junit.Test;
+
+import java.util.Base64;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class SecurityUtilTest {
+
+ @Test
+ public void encryptDecryptAES128() {
+ String data = "decrypt SUCCESS!!";
+ String encrypted = SecurityUtil.INSTANCE.encrypt(data).left().value();
+ assertNotEquals( data, encrypted );
+ byte[] decryptMsg = Base64.getDecoder().decode(encrypted);
+ assertEquals( SecurityUtil.INSTANCE.decrypt( decryptMsg , false ).left().value() ,data );
+ assertEquals( SecurityUtil.INSTANCE.decrypt( encrypted.getBytes() , true ).left().value() ,data );
+ }
+
+ @Test
+ public void obfuscateKey() {
+ String key = "abcdefghij123456";
+ String expectedkey = "********ij123456";
+ String obfuscated = SecurityUtil.INSTANCE.obfuscateKey( key );
+ System.out.println( obfuscated );
+ assertEquals( obfuscated , expectedkey );
+ }
+} \ No newline at end of file
diff --git a/openecomp-be/backend/openecomp-sdc-security-util/src/test/SessionValidationFilterTest.java b/openecomp-be/backend/openecomp-sdc-security-util/src/test/SessionValidationFilterTest.java
new file mode 100644
index 0000000000..6838e3bfb7
--- /dev/null
+++ b/openecomp-be/backend/openecomp-sdc-security-util/src/test/SessionValidationFilterTest.java
@@ -0,0 +1,157 @@
+package org.onap.sdc.security;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.sdc.security.filters.ResponceWrapper;
+import org.onap.sdc.security.filters.SampleFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+//@RunWith(PowerMockRunner.class)
+//@PrepareForTest(fullyQualifiedNames = "org.onap.sdc.security.*")
+public class SessionValidationFilterTest {
+
+ @Mock
+ private HttpServletRequest request;
+ @Spy
+ private HttpServletResponse response;
+ @Mock
+ private FilterChain filterChain;
+ @Mock
+ private FilterConfig filterConfig;
+ @Mock
+ private ResponceWrapper responceWrapper;
+
+ // implementation of SessionValidationFilter
+ @InjectMocks
+ @Spy
+ private SampleFilter sessionValidationFilter = new SampleFilter();
+
+ @Before
+ public void setUpClass() throws ServletException {
+ sessionValidationFilter.init(filterConfig);
+ }
+
+ @Test
+ public void excludedUrlHealthcheck() throws IOException, ServletException {
+ when(request.getPathInfo()).thenReturn("/healthCheck");
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(filterChain, times(1)).doFilter(request, response);
+ }
+
+ @Test
+ public void excludedUrlUpload() throws IOException, ServletException {
+ when(request.getPathInfo()).thenReturn("/upload/123");
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(filterChain, times(1)).doFilter(request, response);
+ }
+
+ // case when url pattern in web.xml is forward slash (/)
+ @Test
+ public void pathInfoIsNull() throws IOException, ServletException {
+ when(request.getServletPath()).thenReturn("/upload/2");
+ when(request.getPathInfo()).thenReturn(null);
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(filterChain, times(1)).doFilter(request, response);
+ }
+
+ @Test
+ public void noCookiesInRequest() throws IOException, ServletException {
+ when(request.getPathInfo()).thenReturn("/resource");
+ when(request.getCookies()).thenReturn(new Cookie[0]);
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(response, times(1)).sendRedirect(sessionValidationFilter.getFilterConfiguration().getRedirectURL());
+ }
+
+ @Test
+ public void nullCookiesInRequest() throws IOException, ServletException {
+ when(request.getPathInfo()).thenReturn("/resource");
+ when(request.getCookies()).thenReturn(null);
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(response, times(1)).sendRedirect(sessionValidationFilter.getFilterConfiguration().getRedirectURL());
+ }
+
+ @Test
+ public void noCookiesWithCorrectNameInRequest() throws IOException, ServletException {
+ when(request.getPathInfo()).thenReturn("/resource");
+ String newNameNotContainsRealName = sessionValidationFilter.getFilterConfiguration().getCookieName().substring(1);
+ Cookie cookie = new Cookie("fake" + newNameNotContainsRealName + "fake2", RepresentationUtils.toRepresentation(new AuthenticationCookie("kuku")));
+ when(request.getCookies()).thenReturn(new Cookie[]{cookie});
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(response, times(1)).sendRedirect(sessionValidationFilter.getFilterConfiguration().getRedirectURL());
+ }
+
+ @Test
+ public void cookieMaxSessionTimeTimedOut() throws IOException, ServletException, CipherUtilException {
+ when(request.getPathInfo()).thenReturn("/resource");
+ AuthenticationCookie authenticationCookie = new AuthenticationCookie("kuku");
+ // set max session time to timout value
+ long maxSessionTimeOut = sessionValidationFilter.getFilterConfiguration().getMaxSessionTimeOut();
+ long startTime = authenticationCookie.getMaxSessionTime();
+ long timeout = startTime - maxSessionTimeOut - 1000l;
+ authenticationCookie.setMaxSessionTime(timeout);
+ Cookie cookie = new Cookie(sessionValidationFilter.getFilterConfiguration().getCookieName(), AuthenticationCookieUtils.getEncryptedCookie(authenticationCookie, sessionValidationFilter.getFilterConfiguration()));
+
+ when(request.getCookies()).thenReturn(new Cookie[]{cookie});
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(response, times(1)).sendRedirect(sessionValidationFilter.getFilterConfiguration().getRedirectURL());
+ }
+
+ @Test
+ public void cookieSessionIdle() throws IOException, ServletException, CipherUtilException {
+ when(request.getPathInfo()).thenReturn("/resource");
+ AuthenticationCookie authenticationCookie = new AuthenticationCookie("kuku");
+ // set session time to timout to idle
+ long idleSessionTimeOut = sessionValidationFilter.getFilterConfiguration().getSessionIdleTimeOut();
+ long sessionStartTime = authenticationCookie.getCurrentSessionTime();
+ long timeout = sessionStartTime - idleSessionTimeOut - 2000;
+ authenticationCookie.setCurrentSessionTime(timeout);
+ Cookie cookie = new Cookie(sessionValidationFilter.getFilterConfiguration().getCookieName(), AuthenticationCookieUtils.getEncryptedCookie(authenticationCookie, sessionValidationFilter.getFilterConfiguration()));
+
+ when(request.getCookies()).thenReturn(new Cookie[]{cookie});
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(response, times(1)).sendRedirect(sessionValidationFilter.getFilterConfiguration().getRedirectURL());
+ }
+
+ @Test
+ public void requestThatPassFilter() throws IOException, ServletException, CipherUtilException {
+ when(request.getPathInfo()).thenReturn("/resource");
+
+ AuthenticationCookie authenticationCookie = new AuthenticationCookie("kuku");
+ Cookie cookie = new Cookie(sessionValidationFilter.getFilterConfiguration().getCookieName(), AuthenticationCookieUtils.getEncryptedCookie(authenticationCookie, sessionValidationFilter.getFilterConfiguration()));
+
+ when(request.getCookies()).thenReturn(new Cookie[]{cookie});
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(filterChain, times(1)).doFilter(request, response);
+ }
+
+// test validate contains
+ @Test
+ public void requestThatPassFilterWithCookieNameAsPartOfOtherString() throws IOException, ServletException, CipherUtilException {
+ when(request.getPathInfo()).thenReturn("/resource");
+
+ AuthenticationCookie authenticationCookie = new AuthenticationCookie("kuku");
+ Cookie cookie = new Cookie("some" +sessionValidationFilter.getFilterConfiguration().getCookieName() + "Thing", AuthenticationCookieUtils.getEncryptedCookie(authenticationCookie, sessionValidationFilter.getFilterConfiguration()));
+
+ when(request.getCookies()).thenReturn(new Cookie[]{cookie});
+ sessionValidationFilter.doFilter(request, response, filterChain);
+ Mockito.verify(filterChain, times(1)).doFilter(request, response);
+ }
+
+} \ No newline at end of file
diff --git a/openecomp-be/backend/pom.xml b/openecomp-be/backend/pom.xml
index 5653946f76..1f6567b565 100644
--- a/openecomp-be/backend/pom.xml
+++ b/openecomp-be/backend/pom.xml
@@ -24,6 +24,7 @@
<module>openecomp-sdc-healthcheck-manager</module>
<module>openecomp-sdc-conflict-manager</module>
<module>openecomp-sdc-item-permissions-manager</module>
+ <module>openecomp-sdc-security-util</module>
</modules>
diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb
index c0f3e1b043..838a323348 100644
--- a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb
+++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb
@@ -30,4 +30,16 @@ cassandraConfig:
truststorePath: /var/lib/jetty/etc/truststore
truststorePassword: <%= @cassandra_truststore_password %>
-
+# access restriction
+authCookie:
+ securityKey: MlB1WHFpSHNVTWdJZU1PcQ==
+ maxSessionTimeOut: 86400000
+ sessionIdleTimeOut: 3600000
+ cookieName: "AuthenticationCookie"
+ path: /
+ domain: ""
+ isHttpOnly: true
+ # redirect variable name from portal.properties file
+ redirectURL: "redirect_url"
+ excludedUrls: ['/.*']
+ onboardingExcludedUrls: ['/.*'] \ No newline at end of file