Reading the request response payload leads to an exception, adding a buffer class which enables multiple reads. Also adding logging of AAF.
Check if response not sent
Check if someone else didn't already flush the response
Changing interpretation of role
Letting users with advanced roles run non-gremlin queries. Adding logging.
Change-Id: If5c9c94b63c3203d2193b43eed5fcd5993f0c4fa
Issue-ID: AAI-1762
Signed-off-by: Kajur, Harish (vk250x) <vk250x@att.com>
*/
package org.onap.aai.config.aaf;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.apache.commons.io.IOUtils;
import org.onap.aai.Profiles;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.filter.OrderedRequestContextFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
-import java.util.stream.Collectors;
-
-import static org.onap.aai.config.aaf.ResponseFormatter.errorResponse;
+import java.nio.charset.StandardCharsets;
/**
* AAF authorization filter
@PropertySource("file:${server.local.startpath}/aaf/permissions.properties")
public class AafAuthorizationFilter extends OrderedRequestContextFilter {
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(AafAuthorizationFilter.class.getName());
+
private static final String ADVANCED = "advanced";
private static final String BASIC = "basic";
+ private static final String ECHO_ENDPOINT = "^.*/util/echo$";
@Value("${permission.type}")
String type;
}
@Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
+ protected void doFilterInternal(HttpServletRequest req, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
- if(request.getRequestURI().matches("^.*/util/echo$")){
+ PayloadBufferingRequestWrapper request = new PayloadBufferingRequestWrapper(req);
+
+ if(request.getRequestURI().matches(ECHO_ENDPOINT)){
filterChain.doFilter(request, response);
}
- boolean containsWordGremlin = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())).contains("\"gremlin\"");
- //if the request contains the word "gremlin" it's an advanced query
- String queryType = containsWordGremlin ? ADVANCED : BASIC;
- String permission = String.format("%s|%s|%s", type, instance, queryType);
+ String payload = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8.name());
+ boolean containsWordGremlin = payload.contains("\"gremlin\"");
+
+ //if the request contains the word "gremlin" it's an "advanced" query needing an "advanced" role
+ String permissionBasic = String.format("%s|%s|%s", type, instance, ADVANCED);
+ String permissionAdvanced = String.format("%s|%s|%s", type, instance, BASIC);
+
+ boolean isAuthorized;
+
+ if(containsWordGremlin){
+ isAuthorized = request.isUserInRole(permissionAdvanced);
+ }else{
+ isAuthorized = request.isUserInRole(permissionAdvanced) || request.isUserInRole(permissionBasic);
+ }
- if(!request.isUserInRole(permission)){
- errorResponse(request, response);
+ if(!isAuthorized){
+ String name = request.getUserPrincipal() != null ? request.getUserPrincipal().getName() : "unknown";
+ logger.info("User " + name + " does not have a role for " + (containsWordGremlin ? "gremlin" : "non-gremlin") + " query" );
+ response.setStatus(403);
}else{
filterChain.doFilter(request,response);
}
*/
package org.onap.aai.config.aaf;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
import org.onap.aaf.cadi.PropAccess;
import org.onap.aaf.cadi.filter.CadiFilter;
import org.onap.aai.Profiles;
@Profile(Profiles.AAF_AUTHENTICATION)
public class AafFilter extends OrderedRequestContextFilter {
+ private static final EELFLogger log = EELFManager.getInstance().getLogger(AafFilter.class.getName());
+
private final CadiFilter cadiFilter;
public AafFilter() throws IOException, ServletException {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
if(!request.getRequestURI().matches("^.*/util/echo$")) {
cadiFilter.doFilter(request, response, filterChain);
- if (response.getStatus() >= 400 && response.getStatus() < 500) {
+ if (response.getStatus() == 401 || response.getStatus() == 403) {
+ log.info("User does not have permissions to run the query" );
errorResponse(request, response);
}
}
--- /dev/null
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 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=========================================================
+ */
+package org.onap.aai.config.aaf;
+
+import org.apache.commons.io.IOUtils;
+import org.onap.aaf.cadi.BufferedServletInputStream;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.*;
+
+/**
+ * This class buffers the payload of the servlet request. The reason is that we access the payload multiple times,
+ * which is not supported by the request per se.
+ */
+
+class PayloadBufferingRequestWrapper extends HttpServletRequestWrapper {
+
+ private byte[] buffer;
+
+ PayloadBufferingRequestWrapper(HttpServletRequest req) throws IOException {
+ super(req);
+ this.buffer = IOUtils.toByteArray(req.getInputStream());
+ }
+
+ @Override
+ public ServletInputStream getInputStream() {
+ ByteArrayInputStream bais = new ByteArrayInputStream(this.buffer);
+ return new BufferedServletInputStream(bais);
+ }
+}
private static final String ACCEPT_HEADER = "accept";
static void errorResponse(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ if (response.isCommitted()){
+ return;
+ }
+
String accept = request.getHeader(ACCEPT_HEADER) == null ? MediaType.APPLICATION_XML : request.getHeader(ACCEPT_HEADER);
AAIException aaie = new AAIException("AAI_3300");
response.setStatus(aaie.getErrorObject().getHTTPResponseCode().getStatusCode());
- response.getWriter().write(ErrorLogHelper.getRESTAPIErrorResponse(Collections.singletonList(MediaType.valueOf(accept)), aaie, new ArrayList<>()));
- response.getWriter().flush();
- response.getWriter().close();
+ response.resetBuffer();
+ response.getOutputStream().print(ErrorLogHelper.getRESTAPIErrorResponse(Collections.singletonList(MediaType.valueOf(accept)), aaie, new ArrayList<>()));
+ response.flushBuffer();
}
-
}
cadi_alias=aai@aai.onap.org
cadi_truststore=aai-traversal/src/main/resources/aaf/truststoreONAPall.jks
cadi_truststore_password=enc:s77wlnZFoQ08NhnU3OSeWO6uKgRwC6sAK-wTvVubNz2
-cadi_loglevel=INFO
+cadi_loglevel=DEBUG
cadi_bath_convert=aai-traversal/src/main/resources/aaf/bath_config.csv
<logger name="org.apache.commons" level="WARN" />
<logger name="org.apache.coyote" level="WARN" />
<logger name="org.apache.jasper" level="WARN" />
+ <logger name="org.onap.aaf" level="DEBUG" />
<!-- Camel Related Loggers (including restlet/servlet/jaxrs/cxf logging.
May aid in troubleshooting) -->