This is an automated email from the ASF dual-hosted git repository.
jinmeiliao pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 3493e8c GEODE-6185: management rest end point returns correct status
code and message
3493e8c is described below
commit 3493e8c8bfab0b7373f517f78762ea0921d7ef3c
Author: jinmeiliao <[email protected]>
AuthorDate: Tue Jan 29 10:31:17 2019 -0800
GEODE-6185: management rest end point returns correct status code and
message
Co-authored-by: Jens Deppe <[email protected]>
---
.../RegionManagementSecurityIntegrationTest.java | 21 +++++---
.../internal/web/security/RestSecurityService.java | 14 ++---
.../controllers/AbstractManagementController.java | 63 ----------------------
...roller.java => ManagementControllerAdvice.java} | 41 ++------------
.../rest/security/RestSecurityConfiguration.java | 36 +++++++++++--
.../rest/security/RestSecurityService.java | 14 ++---
6 files changed, 62 insertions(+), 127 deletions(-)
diff --git
a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementSecurityIntegrationTest.java
b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementSecurityIntegrationTest.java
index ed991d0..831c2e1 100644
---
a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementSecurityIntegrationTest.java
+++
b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementSecurityIntegrationTest.java
@@ -63,23 +63,32 @@ public class RegionManagementSecurityIntegrationTest {
@Test
public void sanityCheck_not_authorized() throws Exception {
ClusterManagementResult result =
- restClient.doPostAndAssert("/regions", json, "test", "test")
+ restClient.doPostAndAssert("/regions", json, "user", "user")
.hasStatusCode(403)
.getClusterManagementResult();
assertThat(result.isSuccessful()).isFalse();
- assertThat(result.getPersistenceStatus().getMessage()).isEqualTo("Access
is denied");
+ assertThat(result.getPersistenceStatus().getMessage())
+ .isEqualTo("user not authorized for DATA:MANAGE");
}
@Test
public void sanityCheckWithNoCredentials() throws Exception {
- restClient.doPostAndAssert("/regions", json, null, null)
- .hasStatusCode(401);
+ ClusterManagementResult result =
+ restClient.doPostAndAssert("/regions", json, null, null)
+ .hasStatusCode(401).getClusterManagementResult();
+ assertThat(result.getPersistenceStatus().getMessage())
+ .isEqualTo("Full authentication is required to access this resource");
+ assertThat(result.isSuccessful()).isFalse();
}
@Test
public void sanityCheckWithWrongCredentials() throws Exception {
- restClient.doPostAndAssert("/regions", json, "test", "invalid_pswd")
- .hasStatusCode(401);
+ ClusterManagementResult result =
+ restClient.doPostAndAssert("/regions", json, "test", "invalid_pswd")
+ .hasStatusCode(401).getClusterManagementResult();
+ assertThat(result.getPersistenceStatus().getMessage())
+ .isEqualTo("Authentication error. Please check your credentials.");
+ assertThat(result.isSuccessful()).isFalse();
}
@Test
diff --git
a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java
b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java
index 4e9cad5..26fe8ec 100644
---
a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java
+++
b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java
@@ -21,7 +21,6 @@ import org.springframework.web.context.ServletContextAware;
import org.apache.geode.internal.cache.HttpService;
import org.apache.geode.internal.security.SecurityService;
-import org.apache.geode.security.GemFireSecurityException;
import org.apache.geode.security.ResourcePermission;
import org.apache.geode.security.ResourcePermission.Operation;
import org.apache.geode.security.ResourcePermission.Resource;
@@ -51,21 +50,18 @@ public class RestSecurityService implements
ServletContextAware {
* calls used in @PreAuthorize tag needs to return a boolean
*/
public boolean authorize(String resource, String operation, String region,
String key) {
- try {
- securityService.authorize(Resource.valueOf(resource),
Operation.valueOf(operation), region,
- key);
- return true;
- } catch (GemFireSecurityException ex) {
- return false;
- }
+ securityService.authorize(Resource.valueOf(resource),
Operation.valueOf(operation), region,
+ key);
+ return true;
}
public boolean authorize(String operation, String region, String[] keys) {
boolean authorized = false;
for (String key : keys) {
authorized = authorize("DATA", operation, region, key);
- if (!authorized)
+ if (!authorized) {
return false;
+ }
}
return true;
}
diff --git
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/AbstractManagementController.java
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/AbstractManagementController.java
index 7012ee3..4cba54a 100644
---
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/AbstractManagementController.java
+++
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/AbstractManagementController.java
@@ -15,27 +15,16 @@
package org.apache.geode.management.internal.rest.controllers;
-import javax.management.InstanceNotFoundException;
-import javax.management.MalformedObjectNameException;
import javax.servlet.ServletContext;
-import org.apache.logging.log4j.Logger;
import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.context.ServletContextAware;
import org.apache.geode.internal.cache.HttpService;
-import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.security.SecurityService;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
import
org.apache.geode.management.internal.api.LocatorClusterManagementService;
-import org.apache.geode.security.AuthenticationFailedException;
-import org.apache.geode.security.NotAuthorizedException;
public class AbstractManagementController implements ServletContextAware {
@@ -51,58 +40,6 @@ public class AbstractManagementController implements
ServletContextAware {
.getAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM);
}
- private static final Logger logger = LogService.getLogger();
-
- @ExceptionHandler(Exception.class)
- public ResponseEntity<ClusterManagementResult> internalError(final Exception
e) {
- logger.error(e.getMessage(), e);
- return new ResponseEntity<>(new ClusterManagementResult(false,
e.getMessage()),
- HttpStatus.INTERNAL_SERVER_ERROR);
- }
-
- @ExceptionHandler(AuthenticationFailedException.class)
- public ResponseEntity<ClusterManagementResult>
unauthorized(AuthenticationFailedException e) {
- return new ResponseEntity<>(new ClusterManagementResult(false,
e.getMessage()),
- HttpStatus.UNAUTHORIZED);
- }
-
- @ExceptionHandler({NotAuthorizedException.class, SecurityException.class})
- public ResponseEntity<ClusterManagementResult> forbidden(Exception e) {
- logger.info(e.getMessage());
- return new ResponseEntity<>(new ClusterManagementResult(false,
e.getMessage()),
- HttpStatus.FORBIDDEN);
- }
-
- @ExceptionHandler(MalformedObjectNameException.class)
- public ResponseEntity<ClusterManagementResult> badRequest(final
MalformedObjectNameException e) {
- logger.info(e.getMessage(), e);
- return new ResponseEntity<>(new ClusterManagementResult(false,
e.getMessage()),
- HttpStatus.BAD_REQUEST);
- }
-
- @ExceptionHandler(InstanceNotFoundException.class)
- public ResponseEntity<ClusterManagementResult> notFound(final
InstanceNotFoundException e) {
- logger.info(e.getMessage(), e);
- return new ResponseEntity<>(new ClusterManagementResult(false,
e.getMessage()),
- HttpStatus.NOT_FOUND);
- }
-
- /**
- * Handles an AccessDenied Exception thrown by a REST API web service
endpoint, HTTP request
- * handler method.
- * <p/>
- *
- * @param cause the Exception causing the error.
- * @return a ResponseEntity with an appropriate HTTP status code (403 -
Forbidden)
- */
- @ExceptionHandler(AccessDeniedException.class)
- public ResponseEntity<ClusterManagementResult> handleException(
- final AccessDeniedException cause) {
- logger.info(cause.getMessage(), cause);
- return new ResponseEntity<>(new ClusterManagementResult(false,
cause.getMessage()),
- HttpStatus.FORBIDDEN);
- }
-
/**
* Initializes data bindings for various HTTP request handler method
parameter Java class types.
*
diff --git
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/AbstractManagementController.java
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
similarity index 68%
copy from
geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/AbstractManagementController.java
copy to
geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
index 7012ee3..1ecd13e 100644
---
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/AbstractManagementController.java
+++
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
@@ -12,45 +12,26 @@
* or implied. See the License for the specific language governing permissions
and limitations under
* the License.
*/
-
package org.apache.geode.management.internal.rest.controllers;
import javax.management.InstanceNotFoundException;
import javax.management.MalformedObjectNameException;
-import javax.servlet.ServletContext;
import org.apache.logging.log4j.Logger;
-import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
-import org.springframework.web.bind.WebDataBinder;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.InitBinder;
-import org.springframework.web.context.ServletContextAware;
-import org.apache.geode.internal.cache.HttpService;
import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.internal.security.SecurityService;
import org.apache.geode.management.internal.api.ClusterManagementResult;
-import
org.apache.geode.management.internal.api.LocatorClusterManagementService;
import org.apache.geode.security.AuthenticationFailedException;
import org.apache.geode.security.NotAuthorizedException;
-public class AbstractManagementController implements ServletContextAware {
-
- protected static final String MANAGEMENT_API_VERSION = "/v2";
- protected SecurityService securityService;
- protected LocatorClusterManagementService clusterManagementService;
-
- @Override
- public void setServletContext(ServletContext servletContext) {
- securityService = (SecurityService) servletContext
- .getAttribute(HttpService.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM);
- clusterManagementService = (LocatorClusterManagementService) servletContext
- .getAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM);
- }
-
+@ControllerAdvice
+public class ManagementControllerAdvice {
private static final Logger logger = LogService.getLogger();
@ExceptionHandler(Exception.class)
@@ -60,7 +41,7 @@ public class AbstractManagementController implements
ServletContextAware {
HttpStatus.INTERNAL_SERVER_ERROR);
}
- @ExceptionHandler(AuthenticationFailedException.class)
+ @ExceptionHandler({AuthenticationFailedException.class,
AuthenticationException.class})
public ResponseEntity<ClusterManagementResult>
unauthorized(AuthenticationFailedException e) {
return new ResponseEntity<>(new ClusterManagementResult(false,
e.getMessage()),
HttpStatus.UNAUTHORIZED);
@@ -103,16 +84,4 @@ public class AbstractManagementController implements
ServletContextAware {
HttpStatus.FORBIDDEN);
}
- /**
- * Initializes data bindings for various HTTP request handler method
parameter Java class types.
- *
- * @param dataBinder the DataBinder implementation used for Web transactions.
- * @see WebDataBinder
- * @see InitBinder
- */
- @InitBinder
- public void initBinder(final WebDataBinder dataBinder) {
- dataBinder.registerCustomEditor(String[].class,
- new
StringArrayPropertyEditor(StringArrayPropertyEditor.DEFAULT_SEPARATOR, false));
- }
}
diff --git
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
index 6d28733..2bc6bc6 100644
---
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
+++
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
@@ -14,10 +14,19 @@
*/
package org.apache.geode.management.internal.rest.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import
org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import
org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
@@ -25,6 +34,10 @@ import
org.springframework.security.config.annotation.web.builders.HttpSecurity;
import
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+
+import org.apache.geode.management.internal.api.ClusterManagementResult;
@Configuration
@EnableWebSecurity
@@ -37,6 +50,9 @@ public class RestSecurityConfiguration extends
WebSecurityConfigurerAdapter {
@Autowired
private GeodeAuthenticationProvider authProvider;
+ @Autowired
+ private ObjectMapper objectMapper;
+
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(authProvider);
@@ -51,13 +67,25 @@ public class RestSecurityConfiguration extends
WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
- // .antMatchers("/ping", "/docs/**", "/swagger-ui.html",
"/v2/api-docs/**",
- // "/webjars/springfox-swagger-ui/**", "/swagger-resources/**")
- // .permitAll()
+ .antMatchers("/ping", "/docs/**", "/swagger-ui.html",
"/v2/api-docs/**",
+ "/webjars/springfox-swagger-ui/**", "/swagger-resources/**")
+ .permitAll()
.anyRequest().authenticated().and().csrf().disable();
if (this.authProvider.getSecurityService().isIntegratedSecurity()) {
- http.httpBasic();
+ http.httpBasic().authenticationEntryPoint(new AuthenticationEntryPoint()
{
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse
response,
+ AuthenticationException authException)
+ throws IOException, ServletException {
+ response.addHeader("WWW-Authenticate", "Basic realm=\"GEODE\"");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ response.setContentType(MediaType.APPLICATION_JSON_UTF8.getType());
+ ClusterManagementResult result =
+ new ClusterManagementResult(false, authException.getMessage());
+ objectMapper.writeValue(response.getWriter(), result);
+ }
+ });
} else {
http.authorizeRequests().anyRequest().permitAll();
}
diff --git
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityService.java
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityService.java
index 4860ab8..afe19f4 100644
---
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityService.java
+++
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityService.java
@@ -21,7 +21,6 @@ import org.springframework.web.context.ServletContextAware;
import org.apache.geode.internal.cache.HttpService;
import org.apache.geode.internal.security.SecurityService;
-import org.apache.geode.security.GemFireSecurityException;
import org.apache.geode.security.ResourcePermission;
import org.apache.geode.security.ResourcePermission.Operation;
import org.apache.geode.security.ResourcePermission.Resource;
@@ -51,21 +50,18 @@ public class RestSecurityService implements
ServletContextAware {
* calls used in @PreAuthorize tag needs to return a boolean
*/
public boolean authorize(String resource, String operation, String region,
String key) {
- try {
- securityService.authorize(Resource.valueOf(resource),
Operation.valueOf(operation), region,
- key);
- return true;
- } catch (GemFireSecurityException ex) {
- return false;
- }
+ securityService.authorize(Resource.valueOf(resource),
Operation.valueOf(operation), region,
+ key);
+ return true;
}
public boolean authorize(String operation, String region, String[] keys) {
boolean authorized = false;
for (String key : keys) {
authorized = authorize("DATA", operation, region, key);
- if (!authorized)
+ if (!authorized) {
return false;
+ }
}
return true;
}