aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ms/neng/pom.xml1
-rw-r--r--ms/pom.xml1
-rw-r--r--ms/sliboot/pom.xml34
-rw-r--r--ms/sliboot/src/main/java/org/onap/ccsdk/apps/ms/sliboot/SlibootApp.java2
-rw-r--r--services/pom.xml3
-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
9 files changed, 472 insertions, 16 deletions
diff --git a/ms/neng/pom.xml b/ms/neng/pom.xml
index b9a16ffa..84b9cc51 100644
--- a/ms/neng/pom.xml
+++ b/ms/neng/pom.xml
@@ -18,7 +18,6 @@
* limitations under the License.
* ============LICENSE_END=========================================================
-->
-
<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">
<modelVersion>4.0.0</modelVersion>
diff --git a/ms/pom.xml b/ms/pom.xml
index 836a4b56..94cd841e 100644
--- a/ms/pom.xml
+++ b/ms/pom.xml
@@ -18,7 +18,6 @@
* limitations under the License.
* ============LICENSE_END=========================================================
-->
-
<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">
<modelVersion>4.0.0</modelVersion>
diff --git a/ms/sliboot/pom.xml b/ms/sliboot/pom.xml
index a9ffec0b..783e7fd3 100644
--- a/ms/sliboot/pom.xml
+++ b/ms/sliboot/pom.xml
@@ -105,6 +105,40 @@
<version>${aaf.cadi.version}</version>
<scope>runtime</scope>
</dependency>
+ <!-- Needed by logging-analytics payload logging filter -->
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
+ <version>3.4.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aaf.authz</groupId>
+ <artifactId>aaf-cadi-client</artifactId>
+ <version>${aaf.cadi.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aaf.authz</groupId>
+ <artifactId>aaf-cadi-core</artifactId>
+ <version>${aaf.cadi.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aaf.authz</groupId>
+ <artifactId>aaf-auth-client</artifactId>
+ <version>${aaf.cadi.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aaf.authz</groupId>
+ <artifactId>aaf-misc-env</artifactId>
+ <version>${aaf.cadi.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aaf.authz</groupId>
+ <artifactId>aaf-misc-rosetta</artifactId>
+ <version>${aaf.cadi.version}</version>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>services</artifactId>
diff --git a/ms/sliboot/src/main/java/org/onap/ccsdk/apps/ms/sliboot/SlibootApp.java b/ms/sliboot/src/main/java/org/onap/ccsdk/apps/ms/sliboot/SlibootApp.java
index beab2569..2bca1dbc 100644
--- a/ms/sliboot/src/main/java/org/onap/ccsdk/apps/ms/sliboot/SlibootApp.java
+++ b/ms/sliboot/src/main/java/org/onap/ccsdk/apps/ms/sliboot/SlibootApp.java
@@ -50,8 +50,6 @@ public class SlibootApp {
SpringApplication.run(SlibootApp.class, args);
}
-
-
@Bean
@ConditionalOnProperty("cadi.properties.path")
@Order(1)
diff --git a/services/pom.xml b/services/pom.xml
index 5328b55f..c3f1e91f 100644
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -22,6 +22,7 @@
<ccsdk.project.version>${project.version}</ccsdk.project.version>
<ccsdk.build.timestamp>${maven.build.timestamp}</ccsdk.build.timestamp>
<maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
+ <logging.analytics.version>1.6.9</logging.analytics.version>
</properties>
<dependencies>
@@ -90,7 +91,7 @@
<dependency>
<groupId>org.onap.logging-analytics</groupId>
<artifactId>logging-filter-spring</artifactId>
- <version>1.6.6</version>
+ <version>${logging.analytics.version}</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
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();
}
-
}