Postpone authentication to version 1.2.1 59/659/2
authorLott, Christopher (cl778h) <cl778h@att.com>
Wed, 7 Aug 2019 18:46:08 +0000 (14:46 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Wed, 7 Aug 2019 21:12:32 +0000 (17:12 -0400)
Change-Id: I9a86348dca7dd79c2080019156b568f103f11dbe
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
docs/release-notes.rst
webapp-backend/README.md
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/WebSecurityConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CustomResponseEntityExceptionHandler.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/SimpleErrorController.java [deleted file]
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthenticationFilter.java
webapp-backend/src/main/resources/logback.xml

index a214b21..cfe16ac 100644 (file)
 RIC Dashboard Release Notes
 ===========================
 
 RIC Dashboard Release Notes
 ===========================
 
+Version 1.2.1, ? Aug 2019
+-------------------------
+* Add EPSDK-FW user management and Portal security
+
 Version 1.2.0, 7 Aug 2019
 -------------------------
 * Split URL properties into prefix/suffix parts
 * Add jacoco plugin to back-end for code coverage
 Version 1.2.0, 7 Aug 2019
 -------------------------
 * Split URL properties into prefix/suffix parts
 * Add jacoco plugin to back-end for code coverage
-* Compile with Java version 11, run with image openjdk:11
+* Compile with Java version 11, use base openjdk:11-jre-slim
 * Clean code of issues reported by Sonar
 * Drop mock RAN names feature that supported R1 testing
 * Extend mock endpoints to simulate delay seen in tests
 * Move mock configuration classes into test area
 * Clean code of issues reported by Sonar
 * Drop mock RAN names feature that supported R1 testing
 * Extend mock endpoints to simulate delay seen in tests
 * Move mock configuration classes into test area
-* Add EPSDK-FW user management and Portal security
 * Update A1 mediator client to spec version 0.10.0
 * Update App manager client to spec version 0.1.7
 
 * Update A1 mediator client to spec version 0.10.0
 * Update App manager client to spec version 0.1.7
 
index 6751ef9..67e4a3b 100644 (file)
@@ -14,9 +14,14 @@ server, see below.
 
 This server requires several configuration files:
 
 
 This server requires several configuration files:
 
-    application.properties (in launch directory)
-    key.properties (on Java classpath)
-    portal.properties (on Java classpath)
+    application.properties - read from filesystem
+    key.properties - read from Java classpath
+    portal.properties - read from Java classpath
+
+All files should be placed in a "config" directory.  That name is important;
+Spring automatically searches that directory for the application.properties file.
+Further, that directory is placed on the Java classpath so the additional
+files can be read at runtime.
 
 These steps are required:
 
 
 These steps are required:
 
@@ -24,14 +29,15 @@ These steps are required:
    files from templates as needed.  E.g., copy
    "key.properties.template" to "key.properties".
 2. Add the config folder to the Java classpath
    files from templates as needed.  E.g., copy
    "key.properties.template" to "key.properties".
 2. Add the config folder to the Java classpath
-3a. Launch the server with this command-line invocation:
+3a. Launch the server with this command-line invocation that includes the
+   config directory on the Java classpath:
 
     java -cp config:target/ric-dash-be-1.2.0-SNAPSHOT.jar \
         -Dloader.main=org.oransc.ric.portal.dashboard.DashboardApplication \
         org.springframework.boot.loader.PropertiesLauncher
 
 
     java -cp config:target/ric-dash-be-1.2.0-SNAPSHOT.jar \
         -Dloader.main=org.oransc.ric.portal.dashboard.DashboardApplication \
         org.springframework.boot.loader.PropertiesLauncher
 
-3b. To use the configuration in the "application-abc.properties" file, addd a
-key-value pair for "spring.config.name" and launch with an invocation like this:
+3b. Alternately, to use the configuration in the "application-abc.properties" file,
+add a key-value pair for "spring.config.name" and launch with this invocation:
 
     java -cp config:target/ric-dash-be-1.2.0-SNAPSHOT.jar \
         -Dspring.config.name=application-abc \
 
     java -cp config:target/ric-dash-be-1.2.0-SNAPSHOT.jar \
         -Dspring.config.name=application-abc \
@@ -40,6 +46,8 @@ key-value pair for "spring.config.name" and launch with an invocation like this:
 
 ### Production user authentication
 
 
 ### Production user authentication
 
+TODO AUTH: Authentication temporarily disabled for Sprint 2 testing!
+
 The regular server authenticates requests using cookies that are set
 by the ONAP Portal:
 
 The regular server authenticates requests using cookies that are set
 by the ONAP Portal:
 
index 4429701..6dc6563 100644 (file)
@@ -31,7 +31,6 @@ import org.oransc.ric.portal.dashboard.controller.AdminController;
 import org.oransc.ric.portal.dashboard.controller.AnrXappController;
 import org.oransc.ric.portal.dashboard.controller.AppManagerController;
 import org.oransc.ric.portal.dashboard.controller.E2ManagerController;
 import org.oransc.ric.portal.dashboard.controller.AnrXappController;
 import org.oransc.ric.portal.dashboard.controller.AppManagerController;
 import org.oransc.ric.portal.dashboard.controller.E2ManagerController;
-import org.oransc.ric.portal.dashboard.controller.SimpleErrorController;
 import org.oransc.ric.portal.dashboard.portalapi.DashboardUserManager;
 import org.oransc.ric.portal.dashboard.portalapi.PortalAuthManager;
 import org.oransc.ric.portal.dashboard.portalapi.PortalAuthenticationFilter;
 import org.oransc.ric.portal.dashboard.portalapi.DashboardUserManager;
 import org.oransc.ric.portal.dashboard.portalapi.PortalAuthManager;
 import org.oransc.ric.portal.dashboard.portalapi.PortalAuthenticationFilter;
@@ -48,6 +47,7 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
 
 @Configuration
 @EnableWebSecurity
 
 @Configuration
 @EnableWebSecurity
@@ -76,7 +76,7 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
                logger.debug("configure: portalapi.username {}", userName);
                // A chain of ".and()" always baffles me
                http.authorizeRequests().anyRequest().authenticated();
                logger.debug("configure: portalapi.username {}", userName);
                // A chain of ".and()" always baffles me
                http.authorizeRequests().anyRequest().authenticated();
-               // http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
+               http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
                http.addFilterBefore(portalAuthenticationFilterBean(), BasicAuthenticationFilter.class);
        }
 
                http.addFilterBefore(portalAuthenticationFilterBean(), BasicAuthenticationFilter.class);
        }
 
@@ -101,8 +101,8 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
                        AppManagerController.CONTROLLER_PATH + "/" + AppManagerController.VERSION_METHOD, //
                        E2ManagerController.CONTROLLER_PATH + "/" + E2ManagerController.HEALTH_METHOD, //
                        E2ManagerController.CONTROLLER_PATH + "/" + E2ManagerController.VERSION_METHOD, //
                        AppManagerController.CONTROLLER_PATH + "/" + AppManagerController.VERSION_METHOD, //
                        E2ManagerController.CONTROLLER_PATH + "/" + E2ManagerController.HEALTH_METHOD, //
                        E2ManagerController.CONTROLLER_PATH + "/" + E2ManagerController.VERSION_METHOD, //
-                       DashboardConstants.LOGIN_PAGE, //
-                       SimpleErrorController.ERROR_PATH };
+                       DashboardConstants.LOGIN_PAGE //
+       };
 
        @Override
        public void configure(WebSecurity web) throws Exception {
 
        @Override
        public void configure(WebSecurity web) throws Exception {
index b1ac2e8..6d8afa7 100644 (file)
@@ -24,10 +24,8 @@ import java.lang.invoke.MethodHandles;
 import org.oransc.ric.portal.dashboard.model.ErrorTransport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.oransc.ric.portal.dashboard.model.ErrorTransport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.HttpRequestMethodNotSupportedException;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.client.HttpStatusCodeException;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.client.HttpStatusCodeException;
@@ -41,11 +39,6 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
  * 
  * Why 502? I quote: <blockquote>HTTP server received an invalid response from a
  * server it consulted when acting as a proxy or gateway.</blockquote>
  * 
  * Why 502? I quote: <blockquote>HTTP server received an invalid response from a
  * server it consulted when acting as a proxy or gateway.</blockquote>
- *
- * This class and the methods are not strictly necessary, the
- * SimpleErrorController is invoked when any controller method takes an uncaught
- * exception, but this approach provides a better response to the front end and
- * doesn't signal internal server error.
  * 
  * Also see:<br>
  * https://www.baeldung.com/exception-handling-for-rest-with-spring
  * 
  * Also see:<br>
  * https://www.baeldung.com/exception-handling-for-rest-with-spring
@@ -61,11 +54,6 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio
         * Generates the response when a REST controller method takes an
         * HttpStatusCodeException.
         * 
         * Generates the response when a REST controller method takes an
         * HttpStatusCodeException.
         * 
-        * It appears that the container internally redirects to /error because the web
-        * request that arrives here has URI /error, and {@link
-        * org.oransc.ric.portal.dashboard.controller.SimpleErrorController} runs before
-        * this.
-        * 
         * @param ex The exception
         * 
         * @param request The original request
         * @param ex The exception
         * 
         * @param request The original request
@@ -81,21 +69,4 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio
                                HttpStatus.BAD_GATEWAY);
        }
 
                                HttpStatus.BAD_GATEWAY);
        }
 
-       /*
-        * This exception also happens when Spring security denies access to a method
-        * due to missing/wrong roles (granted authorities). Override the method to
-        * answer permission denied, even though that may obscure a genuine developer
-        * error.
-        * 
-        * The web request that arrives here has URI /error; how to obtain the URI of
-        * the original request?!?
-        */
-       @Override
-       public final ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
-                       HttpHeaders headers, HttpStatus status, WebRequest request) {
-               log.warn("handleHttpRequestMethodNotSupported: answering 'permission denied' for method {}", ex.getMethod());
-               return new ResponseEntity<Object>(new ErrorTransport(HttpStatus.UNAUTHORIZED.value(),
-                               "Permission denied for method " + ex.getMethod(), ex), HttpStatus.UNAUTHORIZED);
-       }
-
 }
 }
diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/SimpleErrorController.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/SimpleErrorController.java
deleted file mode 100644 (file)
index 531ea17..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 AT&T Intellectual Property and Nokia
- * %%
- * 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.oransc.ric.portal.dashboard.controller;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.web.servlet.error.ErrorAttributes;
-import org.springframework.boot.web.servlet.error.ErrorController;
-import org.springframework.util.Assert;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.context.request.ServletWebRequest;
-import org.springframework.web.context.request.WebRequest;
-
-import springfox.documentation.annotations.ApiIgnore;
-
-/**
- * Provides an endpoint that returns JSON, which is invoked following any error
- * within the Spring-managed context. This is NOT called for errors outside the
- * context; e.g., resource not found.
- * 
- * If trace is requested via request parameter ("?trace=true") and available,
- * adds stack trace information to the standard JSON error response.
- * 
- * Excluded from Swagger API documentation.
- * 
- * https://stackoverflow.com/questions/25356781/spring-boot-remove-whitelabel-error-page
- * https://www.baeldung.com/spring-boot-custom-error-page
- */
-@ApiIgnore
-@RestController
-public class SimpleErrorController implements ErrorController {
-
-       private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
-       public static final String ERROR_PATH = "/error";
-       private static final String TRACE = "trace";
-       private final ErrorAttributes errorAttributes;
-
-       /**
-        * Constructor
-        * 
-        * @param errorAttributes
-        *                            error attributes must not be null
-        */
-       @Autowired
-       public SimpleErrorController(ErrorAttributes errorAttributes) {
-               Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
-               this.errorAttributes = errorAttributes;
-       }
-
-       @Override
-       public String getErrorPath() {
-               return ERROR_PATH;
-       }
-
-       /**
-        * Builds a map with error details
-        * 
-        * @param aRequest
-        *                     HttpServletRequest
-        * @return Map of String to Object
-        */
-       @GetMapping(ERROR_PATH)
-       public Map<String, Object> error(HttpServletRequest aRequest) {
-               Map<String, Object> body = getErrorAttributes(aRequest, getTraceParameter(aRequest));
-               logger.warn("Failed in request for {}", body.get("path"));
-               body.put("decorated-by", SimpleErrorController.class.getName());
-               body.computeIfPresent(TRACE, (key, value) -> body.put(TRACE, ((String) value).split("\n\t")));
-               return body;
-       }
-
-       private boolean getTraceParameter(HttpServletRequest request) {
-               String parameter = request.getParameter(TRACE);
-               if (parameter == null)
-                       return false;
-               return !"false".equalsIgnoreCase(parameter);
-       }
-
-       private Map<String, Object> getErrorAttributes(HttpServletRequest aRequest, boolean includeStackTrace) {
-               WebRequest webRequest = new ServletWebRequest(aRequest);
-               return errorAttributes.getErrorAttributes(webRequest, includeStackTrace);
-       }
-
-}
index 2ec5938..95a3573 100644 (file)
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.lang.invoke.MethodHandles;
 import java.net.URLEncoder;
 import java.io.UnsupportedEncodingException;
 import java.lang.invoke.MethodHandles;
 import java.net.URLEncoder;
+import java.util.HashSet;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -36,11 +37,13 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
 
 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
+import org.onap.portalsdk.core.restful.domain.EcompRole;
 import org.onap.portalsdk.core.restful.domain.EcompUser;
 import org.oransc.ric.portal.dashboard.DashboardConstants;
 import org.oransc.ric.portal.dashboard.model.EcompUserDetails;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.onap.portalsdk.core.restful.domain.EcompUser;
 import org.oransc.ric.portal.dashboard.DashboardConstants;
 import org.oransc.ric.portal.dashboard.model.EcompUserDetails;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
 
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
 
@@ -99,13 +102,45 @@ public class PortalAuthenticationFilter implements Filter {
                // No resources to release
        }
 
                // No resources to release
        }
 
-       /**
+       /*
+        * Populates security context with a mock user in the admin role.
+        * 
+        * TODO: AUTH
+        */
+       @Override
+       public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+                       throws IOException, ServletException {
+               Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+               if (auth == null || auth.getAuthorities().isEmpty()) {
+                       logger.debug("doFilter adding auth to request {}", req);
+                       EcompRole admin = new EcompRole();
+                       admin.setId(1L);
+                       admin.setName(DashboardConstants.ROLE_ADMIN);
+                       HashSet<EcompRole> roles = new HashSet<>();
+                       roles.add(admin);
+                       EcompUser user = new EcompUser();
+                       user.setLoginId("fakeLoginId");
+                       user.setRoles(roles);
+                       user.setActive(true);
+                       EcompUserDetails userDetails = new EcompUserDetails(user);
+                       PreAuthenticatedAuthenticationToken authToken = new PreAuthenticatedAuthenticationToken(userDetails,
+                                       "fakeCredentials", userDetails.getAuthorities());
+                       SecurityContextHolder.getContext().setAuthentication(authToken);
+               }
+               else {
+                       logger.debug("doFilter: authorities {}", auth.getAuthorities());
+               }
+               chain.doFilter(req, res);
+       }
+
+       /*
         * Checks for valid cookies and allows request to be served if found; redirects
         * to Portal otherwise. Requests for pages ignored in the web security config do
         * not hit this filter.
         * Checks for valid cookies and allows request to be served if found; redirects
         * to Portal otherwise. Requests for pages ignored in the web security config do
         * not hit this filter.
+        * 
+        * TODO: AUTH
         */
         */
-       @Override
-       public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+       public void doFilter_EPSDKFW(ServletRequest req, ServletResponse res, FilterChain chain)
                        throws IOException, ServletException {
                logger.debug("doFilter {}", req);
                HttpServletRequest request = (HttpServletRequest) req;
                        throws IOException, ServletException {
                logger.debug("doFilter {}", req);
                HttpServletRequest request = (HttpServletRequest) req;
index b17cbe2..8a4efca 100644 (file)
@@ -70,4 +70,8 @@
        <!-- Report request URLs -->
        <logger name="org.springframework.web.client.RestTemplate" level="DEBUG" />
 
        <!-- Report request URLs -->
        <logger name="org.springframework.web.client.RestTemplate" level="DEBUG" />
 
+       <!-- for debugging security
+       <logger name="org.springframework.security" level="DEBUG" />
+       -->
+
 </configuration>
 </configuration>