aboutsummaryrefslogtreecommitdiffstats
path: root/services/src/main/java
diff options
context:
space:
mode:
authorDan Timoney <dtimoney@att.com>2021-03-22 09:45:16 -0400
committerDan Timoney <dtimoney@att.com>2021-09-02 10:25:07 -0400
commitad0b39dc92ef67ed6f2df714771bed1053d4125d (patch)
tree7ca3aded810f0f420ce954e50e9daf859a450858 /services/src/main/java
parenta67fa64ee0c4395de63b08c9178eb7fd04227715 (diff)
Carry forward honolulu fixes
This change carries forward the following fixes from Honolulu to master Update to allow ranges for ccsdk.sli.version Update to allow ccsdk.sli.version to be passed with a range as a value Change-Id: Ibb37082bf8162300ae2de37f33b0e4672b796293 Issue-ID: CCSDK-3209 Signed-off-by: Dan Timoney <dtimoney@att.com> (cherry picked from commit c3e800149c947ecc9b76a2e3b990664fc5d41ce1) Minor Refactoring of sliboot pom Issue-ID: CCSDK-3343 Change-Id: I66d4e2840ff86e092a23453384d02ce49b7048ac Signed-off-by: Singal, Kapil (ks220y) <ks220y@att.com> Use CadiFilter instead of shiro Microservices should use CadiFilter rather than shiro to integrate with AAF Change-Id: I95b9a844b7ac868f864134de7345013001357352 Issue-ID: SDNC-1523 Signed-off-by: Dan Timoney <dtimoney@att.com> (cherry picked from commit a90eecf70419ec4acba6f5a8425300eef7f45290) Minor Refactoring of sliboot pom Updating docker-maven-plugin to 0.34.0 and removing docker image build goal (it was there twice) Issue-ID: CCSDK-3343 Signed-off-by: Singal, Kapil (ks220y) <ks220y@att.com> Change-Id: I26401befaf235ddfe694c6206cbd547cbc56cc03 (cherry picked from commit 108a13c20757f4a437aea22880f019e6e6043841) missing logs Add filters for audit and request/response log Add filters for audit and request/response log Issue-ID: CCSDK-3367 Signed-off-by: lalena.aria <lalena.aria@att.com> Change-Id: Id292c1f5109f0c3846a0357d0618f607011825a4 Add code to handle content type plain/text Add code to handle content type plain/text Issue-ID: CCSDK-3378 Signed-off-by: lalena.aria <lalena.aria@att.com> Change-Id: Id4a30ad5ca81db0e7e3a328cc5d2496c42c9e150 Signed-off-by: Dan Timoney <dtimoney@att.com> 1201 sanity test Add bean for IpAddressTool plugin Add missing import Add bean for IpAddressTool plugin Add missing import Fx typo (text/plain instead of plain/text) Issue-ID: CCSDK-3379 Signed-off-by: lalena.aria <lalena.aria@att.com> Change-Id: I208a6eaf462f86c2a3015af9bf9026ad11efa14b Signed-off-by: Dan Timoney <dtimoney@att.com> Use version 1.1.8 of parent Use version 1.1.8 of parent in order to use APL-licensed version of liquibase Issue-ID: CCSDK-3423 Signed-off-by: Dan Timoney <dtimoney@att.com> Change-Id: I1db475fa8991d617d22536ce38d51f96c7806f85
Diffstat (limited to 'services/src/main/java')
-rw-r--r--services/src/main/java/org/onap/ccsdk/apps/filters/AuditLogFilter.java43
-rw-r--r--services/src/main/java/org/onap/ccsdk/apps/filters/ContentTypeFilter.java81
-rw-r--r--services/src/main/java/org/onap/ccsdk/apps/filters/PayloadLoggingFilter.java322
-rw-r--r--services/src/main/java/org/onap/ccsdk/apps/services/SvcLogicFactory.java1
4 files changed, 436 insertions, 11 deletions
diff --git a/services/src/main/java/org/onap/ccsdk/apps/filters/AuditLogFilter.java b/services/src/main/java/org/onap/ccsdk/apps/filters/AuditLogFilter.java
new file mode 100644
index 00000000..b6d52c52
--- /dev/null
+++ b/services/src/main/java/org/onap/ccsdk/apps/filters/AuditLogFilter.java
@@ -0,0 +1,43 @@
+package org.onap.ccsdk.apps.filters
+;
+
+import javax.servlet.http.HttpServletRequest;
+import org.onap.logging.filter.base.AuditLogServletFilter;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.MDC;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AuditLogFilter extends AuditLogServletFilter {
+ private static final String MDC_HTTP_METHOD_KEY = "HttpMethod";
+
+ @Override
+ protected void additionalPreHandling(HttpServletRequest httpServletRequest) {
+ // Don't overwrite service instance id if it was set outside of this automated method
+ if (MDC.get(ONAPLogConstants.MDCs.SERVICE_INSTANCE_ID) == null) {
+ String serviceInstanceId = getServiceInstanceId(httpServletRequest.getRequestURI());
+ if (serviceInstanceId != null) {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_INSTANCE_ID, serviceInstanceId);
+ }
+ }
+ MDC.put(MDC_HTTP_METHOD_KEY, httpServletRequest.getMethod());
+ }
+
+ // restconf URLs follow a pattern, this method attempts to extract the service instance id according to that pattern
+ protected String getServiceInstanceId(String path) {
+ int idx = path.indexOf("service-list");
+ if (idx != -1) {
+ // chomp off service-list/
+ String str = path.substring(idx + 13);
+ idx = str.indexOf("/");
+ //if there is another forward slash with more information chomp it off
+ if (idx != -1) {
+ return str.substring(0, idx);
+ } else {
+ return str;
+ }
+ }
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/services/src/main/java/org/onap/ccsdk/apps/filters/ContentTypeFilter.java b/services/src/main/java/org/onap/ccsdk/apps/filters/ContentTypeFilter.java
index 41c71a45..20f9ec47 100644
--- a/services/src/main/java/org/onap/ccsdk/apps/filters/ContentTypeFilter.java
+++ b/services/src/main/java/org/onap/ccsdk/apps/filters/ContentTypeFilter.java
@@ -3,6 +3,7 @@ package org.onap.ccsdk.apps.filters;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -14,6 +15,8 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@@ -24,33 +27,84 @@ public class ContentTypeFilter implements Filter {
String DEFAULT_CONTENT_TYPE = "application/json";
+
@Override
public void doFilter(ServletRequest httpReq, ServletResponse httpResp, FilterChain chain)
throws IOException, ServletException {
String defaultContentType = System.getProperty("ccsdk.defaults.content-type", DEFAULT_CONTENT_TYPE);
-
chain.doFilter(new DefaultContentTypeHttpRequest((HttpServletRequest) httpReq, defaultContentType), httpResp);
}
private class DefaultContentTypeHttpRequest extends HttpServletRequestWrapper {
HttpServletRequest httpRequest;
- String defaultContentType;
- boolean hasContentType;
+ String contentType;
+ List<String> acceptList;
List<String> headerNames;
public DefaultContentTypeHttpRequest(HttpServletRequest httpRequest, String defaultContentType) {
super(httpRequest);
+
this.httpRequest = httpRequest;
- this.defaultContentType = defaultContentType;
+ this.contentType = defaultContentType;
+ this.acceptList = null;
+
+ boolean hasContentType = false;
headerNames = new LinkedList<String>();
Enumeration<String> headerNameEnum = httpRequest.getHeaderNames();
- hasContentType = false;
while (headerNameEnum.hasMoreElements()) {
String curHeaderName = headerNameEnum.nextElement();
if ("Content-Type".equalsIgnoreCase(curHeaderName)) {
hasContentType = true;
+ contentType = super.getContentType();
+ if ("application/yang-data+json".equalsIgnoreCase(contentType)) {
+ contentType = "application/json";
+ } else if ("application/yang-data+xml".equalsIgnoreCase(contentType)) {
+ contentType = "application/xml";
+ } else if (contentType.startsWith("text/plain")) {
+ // Use Accept header, if present, to determine content type.
+ boolean acceptsXml = false;
+ boolean acceptsJson = false;
+ for (Enumeration<String> e = getHeaders("Accept") ; e.hasMoreElements() ;) {
+ String curAcceptValue = e.nextElement();
+ if ("application/json".equalsIgnoreCase(curAcceptValue)) {
+ acceptsJson = true;
+ } else if ("application/yang-data+json".equalsIgnoreCase(curAcceptValue)) {
+ acceptsJson = true;
+ } else if ("application/xml".equalsIgnoreCase(curAcceptValue)) {
+ acceptsXml = true;
+ } else if ("application/yang-data+xml".equalsIgnoreCase(curAcceptValue)) {
+ acceptsXml = true;
+ }
+ }
+ if (acceptsJson) {
+ contentType = "application/json";
+ } else if (acceptsXml) {
+ contentType = "application/xml";
+ } else {
+ // If Accept does not specify XML or JSON (could be Accept is missing), use default content type
+ contentType = defaultContentType;
+ }
+ }
+ } else if ("Accept".equalsIgnoreCase(curHeaderName)) {
+ acceptList = new LinkedList<String>();
+ for (Enumeration<String> e = getHeaders("Accept") ; e.hasMoreElements() ;) {
+ String acceptValue = e.nextElement();
+ if ("application/yang-data+json".equalsIgnoreCase(acceptValue)) {
+ if (!acceptList.contains("application/json")) {
+ acceptList.add("application/json");
+ }
+ } else if ("application/yang-data+xml".equalsIgnoreCase(acceptValue)) {
+ if (!acceptList.contains("application/xml")) {
+ acceptList.add("application/xml");
+ }
+ } else {
+ if (!acceptList.contains(acceptValue)) {
+ acceptList.add(acceptValue);
+ }
+ }
+ }
}
headerNames.add(curHeaderName);
}
@@ -69,6 +123,17 @@ public class ContentTypeFilter implements Filter {
}
}
+
+
+ @Override
+ public Enumeration<String> getHeaders(String name) {
+ if ("Accept".equalsIgnoreCase(name) && (acceptList != null)) {
+ return Collections.enumeration(acceptList);
+ } else {
+ return super.getHeaders(name);
+ }
+ }
+
@Override
public Enumeration<String> getHeaderNames() {
return(Collections.enumeration(headerNames));
@@ -76,11 +141,7 @@ public class ContentTypeFilter implements Filter {
@Override
public String getContentType() {
- if (hasContentType) {
- return super.getContentType();
- } else {
- return defaultContentType;
- }
+ return contentType;
}
}
diff --git a/services/src/main/java/org/onap/ccsdk/apps/filters/PayloadLoggingFilter.java b/services/src/main/java/org/onap/ccsdk/apps/filters/PayloadLoggingFilter.java
new file mode 100644
index 00000000..e53c50a7
--- /dev/null
+++ b/services/src/main/java/org/onap/ccsdk/apps/filters/PayloadLoggingFilter.java
@@ -0,0 +1,322 @@
+package org.onap.ccsdk.apps.filters;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.WriteListener;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+import org.onap.logging.filter.base.AbstractServletFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PayloadLoggingFilter extends AbstractServletFilter implements Filter {
+
+ private static final Logger log = LoggerFactory.getLogger(PayloadLoggingFilter.class);
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ RequestWrapper req = new RequestWrapper((HttpServletRequest) request);
+ Request requestData = req.getMessageRequest();
+
+ StringBuilder requestHeaders = new StringBuilder("REQUEST|");
+ requestHeaders.append(requestData.method);
+ requestHeaders.append(":");
+ requestHeaders.append(requestData.uri);
+ requestHeaders.append("|");
+ mapstr(requestHeaders, requestData.headers);
+
+ log.info(requestHeaders.toString());
+ log.info("REQUEST BODY|{}", requestData.body);
+
+ ResponseWrapper res = new ResponseWrapper((HttpServletResponse) response);
+
+ chain.doFilter(req, res);
+
+ Response responseData = res.getMessageResponse();
+
+ StringBuilder responseHeaders = new StringBuilder();
+ responseHeaders.append("RESPONSE HEADERS|");
+ mapstr(responseHeaders, responseData.headers);
+ responseHeaders.append("Status:").append(responseData.code);
+ responseHeaders.append(";IsCommitted:").append(res.isCommitted());
+
+ log.info(responseHeaders.toString());
+ log.info("RESPONSE BODY|{}", responseData.body);
+
+ res.writeBody();
+ }
+
+ private static class Request {
+
+ public String method;
+ public String uri;
+ public Map<String, Object> headers;
+ public Map<String, Object> param;
+ public String body;
+
+ @Override
+ public String toString() {
+ StringBuilder ss = new StringBuilder();
+ ss.append("REQUEST|").append(method).append(":").append(uri).append("|");
+ ss.append("Headers: ");
+ mapstr(ss, headers);
+ if (param != null && !param.isEmpty()) {
+ ss.append("Parameters: ");
+ mapstr(ss, param);
+ }
+ ss.append("REQUEST BODY|\n");
+ ss.append(body);
+ return ss.toString();
+ }
+ }
+
+ private static class Response {
+
+ public int code;
+ public String message;
+ public Map<String, Object> headers;
+ public String body;
+
+ @Override
+ public String toString() {
+ StringBuilder ss = new StringBuilder();
+ ss.append("HTTP Response: ").append(code).append(" ").append(message).append("\n");
+ ss.append("Headers:\n");
+ mapstr(ss, headers);
+ ss.append("Body:\n");
+ ss.append(body);
+ return ss.toString();
+ }
+ }
+
+ private static class RequestWrapper extends HttpServletRequestWrapper {
+
+ private final String body;
+
+ public RequestWrapper(HttpServletRequest request) throws IOException {
+ super(request);
+
+ StringBuilder stringBuilder = new StringBuilder();
+ InputStream inputStream = request.getInputStream();
+ if (inputStream != null) {
+ try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
+ char[] charBuffer = new char[128];
+ int bytesRead = -1;
+ while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+ stringBuilder.append(charBuffer, 0, bytesRead);
+ }
+ }
+ }
+ body = stringBuilder.toString();
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
+ ServletInputStream servletInputStream = new ServletInputStream() {
+
+ @Override
+ public int read() throws IOException {
+ return byteArrayInputStream.read();
+ }
+
+ @Override
+ public boolean isFinished() {
+ return byteArrayInputStream.available() == 0;
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setReadListener(ReadListener listener) {
+ }
+ };
+ return servletInputStream;
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ return new BufferedReader(new InputStreamReader(getInputStream()));
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public Request getMessageRequest() {
+ Request r = new Request();
+ r.method = getMethod();
+ r.uri = getRequestURI();
+ r.param = getParamMap();
+
+ r.headers = new HashMap<>();
+ Enumeration<String> headerNames = getHeaderNames();
+ while (headerNames.hasMoreElements()) {
+ String name = headerNames.nextElement();
+
+ if (name.equalsIgnoreCase("authorization")) {
+ r.headers.put(name, "***REDACTED***");
+ continue;
+ }
+
+ Enumeration<String> values = getHeaders(name);
+ List<String> valueList = new ArrayList<>();
+ while (values.hasMoreElements()) {
+ valueList.add(values.nextElement());
+ }
+ if (valueList.size() > 1) {
+ r.headers.put(name, valueList);
+ } else if (valueList.size() > 0) {
+ r.headers.put(name, valueList.get(0));
+ }
+ }
+
+ r.body = getBody();
+
+ return r;
+ }
+
+ private Map<String, Object> getParamMap() {
+ Map<String, String[]> parameterMap = getParameterMap();
+ Map<String, Object> paramMap = new HashMap<>();
+ if (parameterMap != null) {
+ for (Entry<String, String[]> entry : parameterMap.entrySet()) {
+ String name = entry.getKey();
+ String[] values = entry.getValue();
+ if (values != null && values.length > 0) {
+ if (values.length == 1) {
+ paramMap.put(name, values[0]);
+ } else {
+ paramMap.put(name, Arrays.<String> asList(values));
+ }
+ }
+ }
+ }
+ return paramMap;
+ }
+ }
+
+ public class ResponseWrapper extends HttpServletResponseWrapper {
+
+ private CharArrayWriter writer = new CharArrayWriter();
+
+ private String statusMessage;
+
+ public ResponseWrapper(HttpServletResponse response) {
+ super(response);
+ }
+
+ @Override
+ public PrintWriter getWriter() {
+ return new PrintWriter(writer);
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() {
+ return new ServletOutputStream() {
+
+ @Override
+ public void write(int b) throws IOException {
+ writer.write(b);
+ }
+
+ @Override
+ public void setWriteListener(WriteListener listener) {
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+ };
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void setStatus(int sc, String sm) {
+ super.setStatus(sc, sm);
+ statusMessage = sm;
+ }
+
+ public Response getMessageResponse() {
+ Response r = new Response();
+ r.code = getStatus();
+ r.message = statusMessage == null ? "" : statusMessage;
+
+ r.headers = new HashMap<>();
+ Collection<String> headerNames = getHeaderNames();
+ for (String name : headerNames) {
+
+ if (name.equalsIgnoreCase("authorization")) {
+ r.headers.put(name, "***REDACTED***");
+ continue;
+ }
+
+ Collection<String> values = getHeaders(name);
+ List<String> valueList = new ArrayList<>(values);
+ if (valueList.size() > 1) {
+ r.headers.put(name, valueList);
+ } else {
+ r.headers.put(name, valueList.get(0));
+ }
+ }
+
+ r.body = writer.toString();
+
+ return r;
+ }
+
+ public void writeBody() throws IOException {
+ String body = writer.toString();
+ setContentLength(body.length());
+ super.getWriter().write(body);
+ }
+ }
+
+ private static void mapstr(StringBuilder ss, Map<String, Object> m) {
+ if (m != null) {
+ for (Entry<String, Object> entry : m.entrySet()) {
+ ss.append(entry.getKey()).append(": ").append(entry.getValue()).append(";");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/services/src/main/java/org/onap/ccsdk/apps/services/SvcLogicFactory.java b/services/src/main/java/org/onap/ccsdk/apps/services/SvcLogicFactory.java
index 44c56af3..9ab5656c 100644
--- a/services/src/main/java/org/onap/ccsdk/apps/services/SvcLogicFactory.java
+++ b/services/src/main/java/org/onap/ccsdk/apps/services/SvcLogicFactory.java
@@ -209,6 +209,5 @@ public class SvcLogicFactory {
return new PropertiesNode();
}
-
}